package app.controllers; import java.net.URL; import java.util.Collection; import java.util.ResourceBundle; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import org.fxmisc.richtext.CodeArea; import org.fxmisc.richtext.LineNumberFactory; import org.fxmisc.richtext.model.StyleSpans; import org.fxmisc.richtext.model.TwoDimensional.Bias; import org.fxmisc.richtext.model.TwoDimensional.Position; import app.events.EditorChangedEvent; import app.events.LanguageChangedEvent; import app.events.ToggleCommentEvent; import app.events.ToggleWrapTextEvent; import app.events.FileSaveStateChangedEvent; import app.model.Model; import app.service.LanguageOperations; import javafx.fxml.FXML; import javafx.fxml.Initializable; public class EditorController implements Initializable, Controller { @FXML private CodeArea editor; private EventBus eventBus; /** * Initializes the controller, and binds the event of change in editor content * to {@link #editorChanged() editorChanged} */ @Override public void initialize(URL url, ResourceBundle resourceBundle) { editor.setParagraphGraphicFactory(LineNumberFactory.get(editor)); editor .textProperty() .addListener((obs, oldV, newV) -> this.editorChanged()); } @Override public void setEventBus(EventBus eventBus) { this.eventBus = eventBus; this.eventBus.register(this); } /** * Applies highlighting to the editor. * * @param highlighting highlighting data */ private void setHighlighting(StyleSpans> highlighting) { this.editor.setStyleSpans(0, highlighting); } /** * Recalculates and refreshes the syntax highlighting of the editor. */ private void refreshHighlighting() { this.setHighlighting(LanguageOperations.syntaxHighlight(this.editor.getText(), Model.getLanguage())); } /** * Uses Model.language to determine whether the current line/selection * is commented or not, and toggles the comment. */ private void toggleComment() { if (editor.getSelectedText().equals("")) { String currentLine = editor.getText(editor.getCurrentParagraph()); String newText; if (Model.getLanguage().isCommentedLine(currentLine)) newText = Model.getLanguage().unCommentLine(currentLine); else newText = Model.getLanguage().commentLine(currentLine); editor.replaceText( editor.getCurrentParagraph(), 0, editor.getCurrentParagraph(), currentLine.length(), newText ); } else { // Comment selection String newText; if (Model.getLanguage().isCommentedSelection(editor.getSelectedText())) newText = Model.getLanguage().unCommentSelection(editor.getSelectedText()); else newText = Model.getLanguage().commentSelection(editor.getSelectedText()); editor.replaceSelection(newText); } } private void setWrapText(boolean isWrapText) { this.editor.setWrapText(isWrapText); } /** * Handles the event whenever the content of the editor is changed. */ private void editorChanged() { int offset = this.editor.getCaretPosition(); Position pos = this.editor.offsetToPosition(offset, Bias.Forward); this.eventBus.post(new EditorChangedEvent(pos.getMajor() + 1, pos.getMinor())); if (Model.getFileIsSaved()) this.eventBus.post(new FileSaveStateChangedEvent(false)); this.refreshHighlighting(); } /** * Refreshes the editor whenever the language is changed. * @param event */ @Subscribe private void handle(LanguageChangedEvent event) { this.refreshHighlighting(); } /** * Toggles a language specific comment of the line/selection * @param event */ @Subscribe private void handle(ToggleCommentEvent event) { this.toggleComment(); } @Subscribe private void handle(ToggleWrapTextEvent event) { this.setWrapText(event.getIsWrapped()); } }