diff --git a/META-INF/plugin.xml b/META-INF/plugin.xml index 0d166fb..f2d370d 100644 --- a/META-INF/plugin.xml +++ b/META-INF/plugin.xml @@ -65,6 +65,9 @@ + diff --git a/src/mobi/hsz/idea/latex/editor/LatexFileEditor.java b/src/mobi/hsz/idea/latex/editor/LatexFileEditor.java index a9e23bd..a62d04f 100644 --- a/src/mobi/hsz/idea/latex/editor/LatexFileEditor.java +++ b/src/mobi/hsz/idea/latex/editor/LatexFileEditor.java @@ -27,13 +27,12 @@ import com.intellij.codeHighlighting.BackgroundEditorHighlighter; import com.intellij.ide.structureView.StructureViewBuilder; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.fileEditor.FileEditor; -import com.intellij.openapi.fileEditor.FileEditorLocation; -import com.intellij.openapi.fileEditor.FileEditorState; -import com.intellij.openapi.fileEditor.FileEditorStateLevel; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; +import com.intellij.pom.Navigatable; import mobi.hsz.idea.latex.lang.LatexLanguage; import mobi.hsz.idea.latex.ui.LatexFileEditorForm; import org.jetbrains.annotations.NotNull; @@ -48,10 +47,7 @@ * @author Jakub Chrzanowski * @since 0.1 */ -public class LatexFileEditor implements FileEditor { - -// private final JBPanel panel = new JBPanel(); -// private final Editor editor; +public class LatexFileEditor implements TextEditor { /** UI form that holds all editor's components. */ private final LatexFileEditorForm form; @@ -201,9 +197,7 @@ public StructureViewBuilder getStructureViewBuilder() { @Override public void dispose() { Disposer.dispose(this); -// if (!editor.isDisposed()) { -// EditorFactory.getInstance().releaseEditor(editor); -// } + form.dispose(); } @Nullable @@ -216,4 +210,21 @@ public T getUserData(@NotNull Key key) { public void putUserData(@NotNull Key key, @Nullable T value) { } + + @NotNull + @Override + public Editor getEditor() { + return form.getEditor(); + } + + @Override + public boolean canNavigateTo(@NotNull Navigatable navigatable) { + return navigatable instanceof OpenFileDescriptor && (((OpenFileDescriptor)navigatable).getOffset() >= 0 || + ((OpenFileDescriptor)navigatable).getLine() != -1); } + + @Override + public void navigateTo(@NotNull Navigatable navigatable) { + OpenFileDescriptor d = (OpenFileDescriptor)navigatable; + d.navigateIn(getEditor()); + } } diff --git a/src/mobi/hsz/idea/latex/editor/LatexFileEditorProvider.java b/src/mobi/hsz/idea/latex/editor/LatexFileEditorProvider.java index 5eb9a0f..1c8451b 100644 --- a/src/mobi/hsz/idea/latex/editor/LatexFileEditorProvider.java +++ b/src/mobi/hsz/idea/latex/editor/LatexFileEditorProvider.java @@ -27,9 +27,8 @@ import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.components.JBLabel; -import mobi.hsz.idea.latex.lang.LatexLanguage; import mobi.hsz.idea.latex.file.LatexFileType; +import mobi.hsz.idea.latex.lang.LatexLanguage; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -68,14 +67,7 @@ public boolean accept(@NotNull Project project, @NotNull VirtualFile file) { @NotNull @Override public FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile file) { - LatexFileEditor a = new LatexFileEditor(project, FileDocumentManager.getInstance().getDocument(file)); - - FileEditorManager m = FileEditorManager.getInstance(project); -// for (FileEditor editor : m.getEditors(file)) { - m.addTopComponent(a, new JBLabel("zzzzzzz")); -// } - - return a; + return new LatexFileEditor(project, FileDocumentManager.getInstance().getDocument(file)); } /** diff --git a/src/mobi/hsz/idea/latex/lang/LatexParserDefinition.java b/src/mobi/hsz/idea/latex/lang/LatexParserDefinition.java index 3757843..26b917f 100644 --- a/src/mobi/hsz/idea/latex/lang/LatexParserDefinition.java +++ b/src/mobi/hsz/idea/latex/lang/LatexParserDefinition.java @@ -134,6 +134,16 @@ public TokenSet getCommentTokens() { return COMMENTS; } + /** + * Returns the set of token types which are treated as argument by the PSI builder. + * + * @return the set of argument token types. + */ + @NotNull + public TokenSet getArgumentTokens() { + return ARGUMENTS; + } + /** * Returns the set of token types which are treated as instructions by the PSI builder. * diff --git a/src/mobi/hsz/idea/latex/lexer/Latex.flex b/src/mobi/hsz/idea/latex/lexer/Latex.flex index 3e7455c..dfb160f 100644 --- a/src/mobi/hsz/idea/latex/lexer/Latex.flex +++ b/src/mobi/hsz/idea/latex/lexer/Latex.flex @@ -28,33 +28,43 @@ LINE_WS = [\ \t\f] WHITE_SPACE = ({LINE_WS}|{EOL})+ INSTRUCTION = \\[a-zA-Z]+ -ARGUMENT = [\w ]+ +ARGUMENT = [^\ \n\r\t\f]+ COMMENT = %.* SPECIAL = [\S] CRLF = [\s\r\n]+ -%state IN_ENTRY +%state IN_GROUP %% { {WHITE_SPACE}+ { return WHITE_SPACE; } - "{" { return LBRACE; } - "}" { return RBRACE; } - "[" { return LBRACKET; } - "]" { return RBRACKET; } - "(" { return LPAREN; } - ")" { return RPAREN; } + "{" { yypushback(1); yybegin(IN_GROUP); } + "[" { yypushback(1); yybegin(IN_GROUP); } + "(" { yypushback(1); yybegin(IN_GROUP); } + "," { return COMMA; } ":" { return COLON; } "*" { return ASTERISK; } "\\\\" { return LINE_BREAK; } {INSTRUCTION} { return INSTRUCTION; } - {ARGUMENT} { return ARGUMENT; } {COMMENT} { return COMMENT; } {SPECIAL} { return SPECIAL; } {CRLF} { return CRLF; } [^] { yybegin(YYINITIAL); return BAD_CHARACTER; } } // + + { + {WHITE_SPACE}+ { yybegin(YYINITIAL); return CRLF; } + + "{" { return LBRACE; } + "[" { return LBRACKET; } + "(" { return LPAREN; } + "}" { return RBRACE; } + "]" { return RBRACKET; } + ")" { return RPAREN; } + + {ARGUMENT} { return ARGUMENT; } +} diff --git a/src/mobi/hsz/idea/latex/lexer/LatexLexer.java b/src/mobi/hsz/idea/latex/lexer/LatexLexer.java index 7ea2985..19ccb77 100644 --- a/src/mobi/hsz/idea/latex/lexer/LatexLexer.java +++ b/src/mobi/hsz/idea/latex/lexer/LatexLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 16.01.15 22:43 */ +/* The following code was generated by JFlex 1.4.3 on 17.01.15 00:19 */ package mobi.hsz.idea.latex.lexer; @@ -14,7 +14,7 @@ /** * This class is a scanner generated by * JFlex 1.4.3 - * on 16.01.15 22:43 from the specification file + * on 17.01.15 00:19 from the specification file * /home/hsz/Projects/idea-latex/src/mobi/hsz/idea/latex/lexer/Latex.flex */ public class LatexLexer implements FlexLexer { @@ -23,7 +23,7 @@ public class LatexLexer implements FlexLexer { /** lexical states */ public static final int YYINITIAL = 0; - public static final int IN_ENTRY = 2; + public static final int IN_GROUP = 2; /** * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l @@ -39,10 +39,10 @@ public class LatexLexer implements FlexLexer { * Translates characters to character classes */ private static final String ZZ_CMAP_PACKED = - "\11\0\1\3\1\2\1\0\1\3\1\1\22\0\1\6\4\0\1\10"+ - "\2\0\1\17\1\20\1\23\1\0\1\21\15\0\1\22\6\0\22\5"+ - "\1\11\7\5\1\15\1\4\1\16\3\0\22\5\1\12\3\5\1\7"+ - "\3\5\1\13\1\0\1\14\uff82\0"; + "\11\0\1\3\1\2\1\0\1\3\1\1\22\0\1\3\4\0\1\6"+ + "\2\0\1\13\1\21\1\16\1\0\1\14\15\0\1\15\6\0\22\5"+ + "\1\7\7\5\1\12\1\4\1\20\3\0\22\5\1\10\7\5\1\11"+ + "\1\0\1\17\uff82\0"; /** * Translates characters to character classes @@ -55,12 +55,12 @@ public class LatexLexer implements FlexLexer { private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = - "\2\0\1\1\2\2\1\1\1\2\1\3\1\4\1\5"+ - "\1\6\1\7\1\10\1\11\1\12\1\13\1\14\1\15"+ - "\1\16\1\17\1\20\1\21"; + "\2\0\1\1\2\2\1\1\1\3\1\4\1\5\1\6"+ + "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\1\16"+ + "\1\17\1\20\1\21\1\22\1\23"; private static int [] zzUnpackAction() { - int [] result = new int[22]; + int [] result = new int[23]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -85,12 +85,12 @@ private static int zzUnpackAction(String packed, int offset, int [] result) { private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\24\0\24\0\50\0\74\0\120\0\144\0\170"+ - "\0\214\0\24\0\240\0\24\0\24\0\24\0\24\0\24"+ - "\0\24\0\24\0\24\0\24\0\24\0\264"; + "\0\0\0\22\0\44\0\66\0\110\0\132\0\154\0\44"+ + "\0\176\0\44\0\44\0\44\0\44\0\220\0\242\0\220"+ + "\0\220\0\220\0\220\0\220\0\220\0\44\0\264"; private static int [] zzUnpackRowMap() { - int [] result = new int[22]; + int [] result = new int[23]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -114,16 +114,15 @@ private static int zzUnpackRowMap(String packed, int offset, int [] result) { private static final String ZZ_TRANS_PACKED_0 = "\1\3\2\4\1\5\1\6\1\3\1\7\1\10\1\11"+ - "\1\12\1\13\1\14\1\15\1\16\1\17\1\20\1\21"+ - "\1\22\1\23\1\24\25\0\2\4\1\5\2\0\1\5"+ - "\3\0\1\13\12\0\3\5\2\0\1\5\21\0\1\25"+ - "\1\26\1\0\1\26\1\0\2\26\12\0\3\5\2\0"+ - "\1\7\1\10\22\0\2\10\14\0\2\11\1\0\21\11"+ - "\1\0\2\13\7\0\1\13\16\0\1\26\1\0\1\26"+ - "\1\0\2\26\11\0"; + "\3\12\1\13\1\14\1\15\3\3\1\16\3\17\5\16"+ + "\1\20\1\21\1\22\3\16\1\23\1\24\1\25\23\0"+ + "\2\4\1\5\4\0\1\11\12\0\3\5\22\0\1\26"+ + "\1\27\1\0\2\27\11\0\2\7\1\0\17\7\1\0"+ + "\2\11\5\0\1\11\11\0\1\16\3\0\16\16\1\0"+ + "\3\17\23\0\1\27\1\0\2\27\11\0"; private static int [] zzUnpackTrans() { - int [] result = new int[200]; + int [] result = new int[198]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -164,10 +163,11 @@ private static int zzUnpackTrans(String packed, int offset, int [] result) { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\1\0\1\10\1\11\6\1\1\11\1\1\12\11\1\1"; + "\2\0\1\11\4\1\1\11\1\1\4\11\10\1\1\11"+ + "\1\1"; private static int [] zzUnpackAttribute() { - int [] result = new int[22]; + int [] result = new int[23]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -252,7 +252,7 @@ public LatexLexer(java.io.InputStream in) { char [] map = new char[0x10000]; int i = 0; /* index in packed string */ int j = 0; /* index in unpacked array */ - while (i < 70) { + while (i < 66) { int count = packed.charAt(i++); char value = packed.charAt(i++); do map[j++] = value; while (--count > 0); @@ -462,74 +462,82 @@ else if (zzAtEOF) { zzMarkedPos = zzMarkedPosL; switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 6: - { return CRLF; - } - case 18: break; - case 1: - { yybegin(YYINITIAL); return BAD_CHARACTER; - } - case 19: break; - case 2: - { return WHITE_SPACE; + case 7: + { return COMMA; } case 20: break; - case 10: - { return RBRACKET; + case 4: + { return SPECIAL; } case 21: break; - case 8: - { return RBRACE; + case 3: + { return COMMENT; } case 22: break; - case 17: - { return INSTRUCTION; + case 18: + { return LINE_BREAK; } case 23: break; - case 11: - { return LPAREN; + case 10: + { return ARGUMENT; } case 24: break; - case 5: - { return SPECIAL; + case 1: + { yybegin(YYINITIAL); return BAD_CHARACTER; } case 25: break; - case 15: - { return ASTERISK; + case 8: + { return COLON; } case 26: break; - case 4: - { return COMMENT; + case 12: + { return LBRACE; } case 27: break; - case 13: - { return COMMA; + case 14: + { return LPAREN; } case 28: break; - case 9: - { return LBRACKET; + case 11: + { yybegin(YYINITIAL); return CRLF; } case 29: break; - case 14: - { return COLON; + case 6: + { yypushback(1); yybegin(IN_GROUP); } case 30: break; - case 12: - { return RPAREN; + case 13: + { return LBRACKET; } case 31: break; - case 7: - { return LBRACE; + case 2: + { return WHITE_SPACE; } case 32: break; - case 3: - { return ARGUMENT; + case 17: + { return RPAREN; } case 33: break; - case 16: - { return LINE_BREAK; + case 15: + { return RBRACE; } case 34: break; + case 9: + { return ASTERISK; + } + case 35: break; + case 5: + { return CRLF; + } + case 36: break; + case 19: + { return INSTRUCTION; + } + case 37: break; + case 16: + { return RBRACKET; + } + case 38: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; diff --git a/src/mobi/hsz/idea/latex/ui/LatexFileEditorForm.form b/src/mobi/hsz/idea/latex/ui/LatexFileEditorForm.form index 8544a90..483edc6 100644 --- a/src/mobi/hsz/idea/latex/ui/LatexFileEditorForm.form +++ b/src/mobi/hsz/idea/latex/ui/LatexFileEditorForm.form @@ -1,6 +1,6 @@
- + @@ -8,18 +8,10 @@ - - - - - - - - - + diff --git a/src/mobi/hsz/idea/latex/ui/LatexFileEditorForm.java b/src/mobi/hsz/idea/latex/ui/LatexFileEditorForm.java index 358c10e..9f537c7 100644 --- a/src/mobi/hsz/idea/latex/ui/LatexFileEditorForm.java +++ b/src/mobi/hsz/idea/latex/ui/LatexFileEditorForm.java @@ -25,22 +25,25 @@ package mobi.hsz.idea.latex.ui; import com.intellij.ide.CommonActionsManager; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.ActionPlaces; -import com.intellij.openapi.actionSystem.ActionToolbar; -import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.ide.ui.customization.CustomActionsSchema; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.event.EditorMouseEvent; +import com.intellij.openapi.editor.event.EditorMouseEventArea; +import com.intellij.openapi.editor.event.EditorMouseListener; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.project.Project; import com.intellij.ui.JBSplitter; -import com.intellij.ui.components.JBPanel; +import com.intellij.util.EditorPopupHandler; import mobi.hsz.idea.latex.file.LatexFileType; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; +import java.awt.event.MouseEvent; /** * {@link LatexFileEditorForm} holds whole LaTeX editor UI elements. @@ -48,7 +51,7 @@ * @author Jakub Chrzanowski * @since 0.1 */ -public class LatexFileEditorForm { +public class LatexFileEditorForm implements Disposable { /** Current project. */ private final Project project; @@ -59,12 +62,15 @@ public class LatexFileEditorForm { /** Root form element. */ private JPanel root; - /** Action toolbar panel. */ - private JPanel toolbarPanel; - /** Splitter for editor (left side) and content preview (right side). */ private JPanel splitter; + /** Main LaTeX editor. */ + private Editor editor; + + /** Editor's mouse listener. */ + private EditorMouseListener mouseListener; + public LatexFileEditorForm(Project project, Document document, FileEditor fileEditor) { this.project = project; this.document = document; @@ -84,34 +90,25 @@ public JPanel getComponent() { * Creates and configures UI components. */ private void createUIComponents() { - toolbarPanel = new JBPanel(new BorderLayout()); - - Editor editor = createEditor(project, document); - JComponent toolbar = createActionsToolbar(editor.getComponent()).getComponent(); - - toolbarPanel.add(toolbar); - + editor = createEditor(project, document); splitter = new JBSplitter(0.4f); ((JBSplitter) splitter).setFirstComponent(editor.getComponent()); // ((JBSplitter) splitter).setSecondComponent(); } - /** * Creates tree toolbar panel with actions for working with templates tree. * - * @param target templates tree * @return action toolbar */ - private ActionToolbar createActionsToolbar(JComponent target) { + private ActionToolbar createActionsToolbar() { final CommonActionsManager actionManager = CommonActionsManager.getInstance(); DefaultActionGroup actions = new DefaultActionGroup(); - actions.add(actionManager.createHelpAction("xxx")); + actions.add(actionManager.createHelpAction("Be patient - work in progress")); final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, actions, true); actionToolbar.setMinimumButtonSize(ActionToolbar.NAVBAR_MINIMUM_BUTTON_SIZE); - actionToolbar.setTargetComponent(target); return actionToolbar; } @@ -123,11 +120,58 @@ private ActionToolbar createActionsToolbar(JComponent target) { * @return editor */ @NotNull - private static Editor createEditor(@NotNull Project project, @NotNull Document document) { + private Editor createEditor(@NotNull Project project, @NotNull Document document) { Editor editor = EditorFactory.getInstance().createEditor(document, project, LatexFileType.INSTANCE, false); + this.mouseListener = new MouseListener(); + + ActionToolbar actionToolbar = createActionsToolbar(); + actionToolbar.setTargetComponent(editor.getComponent()); + editor.setHeaderComponent(actionToolbar.getComponent()); + editor.addEditorMouseListener(mouseListener); + +// editor.setHeaderComponent(new JBLabel("foo")); // EditorColorsScheme colorsScheme = editor.getColorsScheme(); // colorsScheme.setColor(EditorColors.CARET_ROW_COLOR, null); return editor; } + + /** + * Releases LaTeX editor. + */ + @Override + public void dispose() { + if (!editor.isDisposed()) { + editor.removeEditorMouseListener(mouseListener); + EditorFactory.getInstance().releaseEditor(editor); + } + } + + /** + * Returns LaTeX editor. + * + * @return LaTeX editor + */ + public Editor getEditor() { + return editor; + } + + /** + * Shows popup menu + */ + private static final class MouseListener extends EditorPopupHandler { + @Override + public void invokePopup(final EditorMouseEvent event) { + if (!event.isConsumed() && event.getArea() == EditorMouseEventArea.EDITING_AREA) { + ActionGroup group = (ActionGroup) CustomActionsSchema.getInstance().getCorrectedAction(IdeActions.GROUP_EDITOR_POPUP); + ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.EDITOR_POPUP, group); + MouseEvent e = event.getMouseEvent(); + final Component c = e.getComponent(); + if (c != null && c.isShowing()) { + popupMenu.getComponent().show(c, e.getX(), e.getY()); + } + e.consume(); + } + } + } }