package bluej.editor.moe;

import bluej.Config;
import bluej.editor.moe.MoeEditor.FindNavigator;
import bluej.utility.javafx.JavaFXUtil;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.InnerShadow;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polygon;
import org.fxmisc.wellbehaved.event.EventPattern;
import org.fxmisc.wellbehaved.event.InputMap;
import org.fxmisc.wellbehaved.event.Nodes;
import threadchecker.OnThread;
import threadchecker.Tag;

import static javafx.scene.input.KeyCombination.SHIFT_DOWN;


| The FindPanel class implements the find functionality of the MoeEditor. | It provides both the user interface panel and the high level implementation | of the find functionality.It also is a link to the replace panel. | | @author Marion Zalk | @author Michael Kölling | @OnThread(Tag.FXPlatform) public class FindPanel extends GridPane{ private final TextField replaceField; private final MoeEditor editor; private final CheckBox matchCaseCheckBox; private final Button previousButton; private final Button nextButton; private final TextField findField; private FindNavigator currentNavigator; private final BooleanProperty findResultsFound = new SimpleBooleanProperty(false); private final SimpleBooleanProperty showingReplace;
| Constructor that creates and displays the different elements of the Find Panel | public FindPanel(MoeEditor ed) { editor = ed; JavaFXUtil.addStyleClass(this, "moe-find-panel"); managedProperty().bind(visibleProperty()); JavaFXUtil.addStyleClass(this, "moe-find-grid"); HBox mcBody = new HBox(); BorderPane closeBody = new BorderPane(); JavaFXUtil.addStyleClass(closeBody, "moe-find-close-wrapper"); Label findLabel = new Label(Config.getString("editor.findpanel.findLabel")); JavaFXUtil.addStyleClass(findLabel, "moe-find-label"); Label replaceDummyLabel = new Label(Config.getString("editor.replacePanel.replaceLabel")); JavaFXUtil.addStyleClass(replaceDummyLabel, "moe-find-label"); replaceDummyLabel.setVisible(false); StackPane findLabelPane = new StackPane(replaceDummyLabel, findLabel); Label replaceFoldOutLabel = new Label(Config.getString("editor.findpanel.replacePanel")); StackPane.setAlignment(findLabel, Pos.CENTER_RIGHT); findField = new TextField(); JavaFXUtil.addStyleClass(findField, "moe-find-field"); JavaFXUtil.addChangeListenerPlatform(findField.textProperty(), search -> { updateFindResult(); }); matchCaseCheckBox = new CheckBox(); matchCaseCheckBox.setText(Config.getString("editor.findpanel.matchCase")); matchCaseCheckBox.setSelected(false); JavaFXUtil.addChangeListenerPlatform(matchCaseCheckBox.selectedProperty(), cs -> { updateFindResult(); }); Label closeIconLabel = new Label(); closeIconLabel.setGraphic(makeCloseIcon()); closeIconLabel.setOnMouseClicked(e -> cancelFind()); previousButton = new Button(); previousButton.setOnAction(e -> { updateFindResult(); if (currentNavigator != null && currentNavigator.validProperty().get()) { currentNavigator.selectPrev(); } }); Label prevShortcut = new Label("\u21e7\u23ce"); previousButton.setText(Config.getString("editor.findpanel.findPrevious")); previousButton.setGraphic(prevShortcut); previousButton.setDisable(true); nextButton = new Button(); nextButton.setOnAction(e -> { updateFindResult(); if (currentNavigator != null && currentNavigator.validProperty().get()) { currentNavigator.selectNext(false); } }); nextButton.setText(Config.getString("editor.findpanel.findNext")); Label nextShortcut = new Label("\u23ce"); nextButton.setGraphic(nextShortcut); nextButton.setDisable(true); nextShortcut.visibleProperty().bind(findField.focusedProperty()); prevShortcut.visibleProperty().bind(findField.focusedProperty()); Nodes.addInputMap(findField, InputMap.sequence( InputMap.consume(EventPattern.keyPressed(KeyCode.ESCAPE), e -> cancelFind()), InputMap.consume(EventPattern.keyPressed(KeyCode.ENTER), e -> nextButton.fire()), InputMap.consume(EventPattern.keyPressed(KeyCode.ENTER, SHIFT_DOWN), e -> previousButton.fire()) )); showingReplace = new SimpleBooleanProperty(false); Polygon triangle = new Polygon(0, 0, 8, 5, 0, 10); triangle.rotateProperty().bind(Bindings.when(showingReplace).then(90).otherwise(0)); replaceFoldOutLabel.setGraphic(triangle); replaceFoldOutLabel.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> { showingReplace.set(!showingReplace.get()); e.consume(); }); GridPane.setHalignment(closeBody, HPos.RIGHT); closeBody.setMaxWidth(Double.MAX_VALUE); GridPane.setHgrow(closeBody, Priority.ALWAYS); closeBody.setCenter(closeIconLabel); BorderPane.setAlignment(closeIconLabel, Pos.CENTER_RIGHT); JavaFXUtil.addStyleClass(mcBody, "moe-find-options"); mcBody.setAlignment(Pos.CENTER); matchCaseCheckBox.setAlignment(Pos.CENTER); replaceFoldOutLabel.setAlignment(Pos.CENTER); mcBody.getChildren().add(matchCaseCheckBox); mcBody.getChildren().add(replaceFoldOutLabel); Label replaceLabel = new Label(Config.getString("editor.replacePanel.replaceLabel")); JavaFXUtil.addStyleClass(replaceLabel, "moe-find-label"); replaceField = new TextField(); Nodes.addInputMap(replaceField, InputMap.sequence( InputMap.consume(EventPattern.keyPressed(KeyCode.ESCAPE), e -> cancelFind()) )); Button replaceOne = new Button(Config.getString("editor.replacePanel.replaceOnce")); Button replaceAll = new Button(Config.getString("editor.replacePanel.replaceAll")); replaceOne.setOnAction(e -> { updateFindResult(); if (currentNavigator.validProperty().get()) { setCurrentNavigator(currentNavigator.replaceCurrent(replaceField.getText())); } }); replaceAll.setOnAction(e -> { updateFindResult(); if (currentNavigator.validProperty().get()) { currentNavigator.replaceAll(replaceField.getText()); } }); replaceOne.disableProperty().bind(findField.textProperty().isEmpty().or(findResultsFound.not())); replaceAll.disableProperty().bind(replaceOne.disableProperty()); add(findLabelPane, 0, 0); add(findField, 1, 0); add(replaceField, 1, 1); add(previousButton, 2, 0); add(nextButton, 3, 0); add(mcBody, 4, 0); add(closeBody, 5, 0); add(replaceLabel, 0, 1); add(replaceOne, 2, 1); add(replaceAll, 3, 1); for (Node n : new Node[] {replaceLabel, replaceField, replaceOne, replaceAll }) { n.visibleProperty().bind(showingReplace); n.managedProperty().bind(n.visibleProperty()); } mcBody.setFillHeight(true); for (Button b : new Button[]{previousButton, nextButton, replaceOne, replaceAll }) { b.setMaxHeight(Double.MAX_VALUE); b.setMaxWidth(Double.MAX_VALUE); } }
| Makes a cross inside a circle for the close icon | private static Node makeCloseIcon() { Circle circle = new Circle(10); circle.setEffect(new InnerShadow(BlurType.GAUSSIAN, Color.rgb(128, 128, 128, 0.4), 2, 0.5, 1, 1)); circle.setFill(Color.rgb(190, 190, 190, 1.0)); Line lineA = new Line(0, 0, 7, 7); lineA.setStrokeWidth(3); lineA.setStroke(Color.rgb(240, 240, 240)); Line lineB = new Line(0, 7, 7, 0); lineB.setStrokeWidth(3); lineB.setStroke(Color.rgb(240, 240, 240)); StackPane stackPane = new StackPane(circle, lineA, lineB); stackPane.setPickOnBounds(true); return stackPane; }
| Hides the panel and clears the text fields. | private void cancelFind() { findField.clear(); replaceField.clear(); setReplaceEnabled(false); setVisible(false); }
| Finds a instance of the search string (forward, from the current selection beginning, | including the possibility that the search result begins at current selection beginning). | private void updateFindResult() { setCurrentNavigator(editor.doFind(getSearchString(), !matchCaseCheckBox.isSelected())); }
| Updates the search state based on the given FindNavigator object. | | This occurs either when the search term changes, or a replacement has occurred | (which basically triggers a new find). | | All results will be highlighted, and if there are any results, the first will be selected. | private void setCurrentNavigator(FindNavigator navigator) { currentNavigator = navigator; previousButton.disableProperty().unbind(); nextButton.disableProperty().unbind(); if (currentNavigator == null) { JavaFXUtil.setPseudoclass("bj-no-find-result", !getSearchString().isEmpty(), findField); previousButton.setDisable(true); nextButton.setDisable(true); findResultsFound.set(false); } else { JavaFXUtil.setPseudoclass("bj-no-find-result", false, findField); currentNavigator.highlightAll(); currentNavigator.selectNext(true); previousButton.disableProperty().bind(findResultsFound.not()); nextButton.disableProperty().bind(findResultsFound.not()); findResultsFound.set(true); } }
| Display the find panel and initiate a search. If the selection is null the search | the previous search String is used (if there is a previous search) | public void displayFindPanel(String selection) { if (selection == null) { selection = getSearchString(); } this.setVisible(true); populateFindTextfield(selection); } public String getSearchString() { return findField.getText(); }
| Display either writes an empty message or a message reflecting the | number of occurrences found | private void writeMessage(boolean emptyMessage, int counter) { if (!emptyMessage) { editor.writeMessage(" "); return; } if (counter > 0) { editor.writeMessage(Config.getString("editor.highlight.found").trim() + " " + counter + " " + Config.getString("editor.replaceAll.intancesOf").trim() + " " + getSearchString()); } else { if (counter < 1 && getSearchString().length() > 0) { editor.writeMessage(Config.getString("editor.replaceAll.string").trim() + " " + getSearchString() + " " + Config.getString("editor.highlight.notFound").trim()); } } }
| Removes the highlights and sets the find and replace panel to invisible | Also resets the replace icon to closed | public void close() { editor.removeSearchHighlights(); this.setVisible(false); editor.getCurrentTextPane().requestFocus(); }
| Puts the focus in the find field | protected void requestFindfieldFocus() { findField.requestFocus(); }
| Populates the field and puts the focus in the text field | protected void populateFindTextfield(String selection) { findField.setText(selection); findField.selectAll(); findField.requestFocus(); }
| Allows the replace button to be en/disabled | @param isEnable true for enable; false if not | protected void setReplaceEnabled(boolean isEnabled) { showingReplace.set(isEnabled); } }
top, use, map, class FindPanel

.   FindPanel
.   makeCloseIcon
.   cancelFind
.   updateFindResult
.   setCurrentNavigator
.   displayFindPanel
.   getSearchString
.   writeMessage
.   close
.   requestFindfieldFocus
.   populateFindTextfield
.   setReplaceEnabled




398 neLoCode + 24 LoComm