diff --git a/editor.lib/nbproject/project.properties b/editor.lib/nbproject/project.properties --- a/editor.lib/nbproject/project.properties +++ b/editor.lib/nbproject/project.properties @@ -39,7 +39,7 @@ javac.compilerargs=-Xlint:unchecked javac.source=1.5 -spec.version.base=1.33.0 +spec.version.base=1.34.0 is.autoload=true javadoc.arch=${basedir}/arch.xml diff --git a/editor.lib/nbproject/project.xml b/editor.lib/nbproject/project.xml --- a/editor.lib/nbproject/project.xml +++ b/editor.lib/nbproject/project.xml @@ -104,7 +104,7 @@ - 6.5 + 7.7 diff --git a/editor.lib/src/org/netbeans/editor/ActionFactory.java b/editor.lib/src/org/netbeans/editor/ActionFactory.java --- a/editor.lib/src/org/netbeans/editor/ActionFactory.java +++ b/editor.lib/src/org/netbeans/editor/ActionFactory.java @@ -71,11 +71,11 @@ import javax.swing.JCheckBoxMenuItem; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; -import javax.swing.ImageIcon; import javax.swing.JToggleButton; import javax.swing.event.ChangeListener; import javax.swing.text.AbstractDocument; import javax.swing.text.View; +import org.netbeans.api.editor.EditorActionRegistration; import org.netbeans.api.editor.fold.Fold; import org.netbeans.api.editor.fold.FoldHierarchy; import org.netbeans.api.editor.fold.FoldUtilities; @@ -102,13 +102,16 @@ private ActionFactory() { // no instantiation } - + + // No registration since shared instance gets created + //@EditorActionRegistration(name = BaseKit.removeTabAction) public static class RemoveTabAction extends LocalBaseAction { static final long serialVersionUID =-1537748600593395706L; public RemoveTabAction() { - super(BaseKit.removeTabAction, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET); + super(BaseKit.removeTabAction, + MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET); } public void actionPerformed(final ActionEvent evt, final JTextComponent target) { @@ -197,10 +200,11 @@ } */ + @EditorActionRegistration(name = BaseKit.removePreviousWordAction) public static class RemoveWordPreviousAction extends LocalBaseAction { public RemoveWordPreviousAction() { - super(BaseKit.removePreviousWordAction, MAGIC_POSITION_RESET + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } @@ -233,12 +237,11 @@ } } - + @EditorActionRegistration(name = BaseKit.removeNextWordAction) public static class RemoveWordNextAction extends LocalBaseAction { public RemoveWordNextAction() { - super(BaseKit.removeNextWordAction, MAGIC_POSITION_RESET - | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed (final ActionEvent evt, final JTextComponent target) { @@ -271,13 +274,13 @@ } + @EditorActionRegistration(name = BaseKit.removeLineBeginAction) public static class RemoveLineBeginAction extends LocalBaseAction { static final long serialVersionUID =9193117196412195554L; public RemoveLineBeginAction() { - super(BaseKit.removeLineBeginAction, MAGIC_POSITION_RESET - | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed (final ActionEvent evt, final JTextComponent target) { @@ -321,13 +324,13 @@ } } + @EditorActionRegistration(name = BaseKit.removeLineAction) public static class RemoveLineAction extends LocalBaseAction { static final long serialVersionUID =-536315497241419877L; public RemoveLineAction() { - super(BaseKit.removeLineAction, MAGIC_POSITION_RESET - | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed (final ActionEvent evt, final JTextComponent target) { @@ -359,13 +362,13 @@ } } - /* package */ static class MoveSelectionElseLineUpAction extends LocalBaseAction { + @EditorActionRegistration(name = BaseKit.moveSelectionElseLineUpAction) + public static class MoveSelectionElseLineUpAction extends LocalBaseAction { static final long serialVersionUID = 1L; public MoveSelectionElseLineUpAction() { - super(BaseKit.moveSelectionElseLineUpAction, MAGIC_POSITION_RESET - | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed (final ActionEvent evt, final JTextComponent target) { @@ -455,13 +458,13 @@ } } - /* package */ static class MoveSelectionElseLineDownAction extends LocalBaseAction { + @EditorActionRegistration(name = BaseKit.moveSelectionElseLineDownAction) + public static class MoveSelectionElseLineDownAction extends LocalBaseAction { static final long serialVersionUID = 1L; public MoveSelectionElseLineDownAction() { - super(BaseKit.moveSelectionElseLineDownAction, MAGIC_POSITION_RESET - | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed (final ActionEvent evt, final JTextComponent target) { @@ -552,13 +555,13 @@ } } - /* package */ static class CopySelectionElseLineUpAction extends LocalBaseAction { + @EditorActionRegistration(name = BaseKit.copySelectionElseLineUpAction) + public static class CopySelectionElseLineUpAction extends LocalBaseAction { static final long serialVersionUID = 1L; public CopySelectionElseLineUpAction() { - super(BaseKit.copySelectionElseLineUpAction, MAGIC_POSITION_RESET - | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed (final ActionEvent evt, final JTextComponent target) { @@ -639,13 +642,13 @@ } } - /* package */ static class CopySelectionElseLineDownAction extends LocalBaseAction { + @EditorActionRegistration(name = BaseKit.copySelectionElseLineDownAction) + public static class CopySelectionElseLineDownAction extends LocalBaseAction { static final long serialVersionUID = 1L; public CopySelectionElseLineDownAction() { - super(BaseKit.copySelectionElseLineDownAction, MAGIC_POSITION_RESET - | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed (final ActionEvent evt, final JTextComponent target) { @@ -727,13 +730,15 @@ } /* Useful for popup menu - remove selected block or do nothing */ + // No annotation registration since shared instance exists in BaseKit + //@EditorActionRegistration(name = BaseKit.removeSelectionAction) public static class RemoveSelectionAction extends LocalBaseAction { static final long serialVersionUID =-1419424594746686573L; public RemoveSelectionAction() { - super(BaseKit.removeSelectionAction, MAGIC_POSITION_RESET - | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + super(BaseKit.removeSelectionAction, + MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); //#54893 putValue ("helpID", RemoveSelectionAction.class.getName ()); // NOI18N } @@ -760,12 +765,13 @@ } /** Switch to overwrite mode or back to insert mode */ + @EditorActionRegistration(name = BaseKit.toggleTypingModeAction) public static class ToggleTypingModeAction extends LocalBaseAction { static final long serialVersionUID =-2431132686507799723L; public ToggleTypingModeAction() { - super(BaseKit.toggleTypingModeAction); + super(); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -916,6 +922,7 @@ * @deprecated Without any replacement. This action is not used anymore. */ public static class StartMacroRecordingAction extends LocalBaseAction { + // Not registered by annotation since it's not actively used static final long serialVersionUID =1L; @@ -937,6 +944,7 @@ * is no longer functional. */ public static class StopMacroRecordingAction extends LocalBaseAction { + // Not registered by annotation since it's not actively used static final long serialVersionUID =1L; @@ -1010,13 +1018,27 @@ public static class ChangeCaseAction extends LocalBaseAction { + @EditorActionRegistration(name = BaseKit.toUpperCaseAction) + public static ChangeCaseAction createToUpperCase() { + return new ChangeCaseAction(Utilities.CASE_UPPER); + } + + @EditorActionRegistration(name = BaseKit.toLowerCaseAction) + public static ChangeCaseAction createToLowerCase() { + return new ChangeCaseAction(Utilities.CASE_LOWER); + } + + @EditorActionRegistration(name = BaseKit.switchCaseAction) + public static ChangeCaseAction createSwitchCase() { + return new ChangeCaseAction(Utilities.CASE_SWITCH); + } + int changeCaseMode; static final long serialVersionUID =5680212865619897402L; - public ChangeCaseAction(String name, int changeCaseMode) { - super(name, ABBREV_RESET - | MAGIC_POSITION_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + private ChangeCaseAction(int changeCaseMode) { + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); this.changeCaseMode = changeCaseMode; } @@ -1047,16 +1069,14 @@ } } - + @EditorActionRegistration(name = BaseKit.findNextAction, + iconResource = "org/netbeans/modules/editor/resources/find_next.png") // NOI18N public static class FindNextAction extends LocalBaseAction { static final long serialVersionUID =6878814427731642684L; public FindNextAction() { - super(BaseKit.findNextAction, ABBREV_RESET - | MAGIC_POSITION_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); - putValue(BaseAction.ICON_RESOURCE_PROPERTY, - "org/netbeans/modules/editor/resources/find_next.png"); // NOI18N + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1066,15 +1086,14 @@ } } + @EditorActionRegistration(name = BaseKit.findPreviousAction, + iconResource = "org/netbeans/modules/editor/resources/find_previous.png") // NOI18N public static class FindPreviousAction extends LocalBaseAction { static final long serialVersionUID =-43746947902694926L; public FindPreviousAction() { - super(BaseKit.findPreviousAction, ABBREV_RESET - | MAGIC_POSITION_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); - putValue(BaseAction.ICON_RESOURCE_PROPERTY, - "org/netbeans/modules/editor/resources/find_previous.png"); // NOI18N + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1087,14 +1106,14 @@ /** Finds either selection or if there's no selection it finds * the word where the cursor is standing. */ + @EditorActionRegistration(name = BaseKit.findSelectionAction, + iconResource = "org/netbeans/modules/editor/resources/find_selection.png") // NOI18N public static class FindSelectionAction extends LocalBaseAction { static final long serialVersionUID =-5601618936504699565L; public FindSelectionAction() { - super(BaseKit.findSelectionAction); - putValue(BaseAction.ICON_RESOURCE_PROPERTY, - "org/netbeans/modules/editor/resources/find_selection.png"); // NOI18N + super(); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1152,13 +1171,14 @@ } } + @EditorActionRegistration(name = BaseKit.toggleHighlightSearchAction, + iconResource = "org/netbeans/modules/editor/resources/toggle_highlight.png") public static class ToggleHighlightSearchAction extends LocalBaseAction implements Presenter.Toolbar { static final long serialVersionUID =4603809175771743200L; public ToggleHighlightSearchAction() { - super(BaseKit.toggleHighlightSearchAction, CLEAR_STATUS_TEXT); - putValue(Action.SMALL_ICON, ImageUtilities.loadImageIcon("org/netbeans/modules/editor/resources/toggle_highlight.png", false)); // NOI18N + super(CLEAR_STATUS_TEXT); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1301,22 +1321,24 @@ } } + @EditorActionRegistration(name = { BaseKit.wordMatchNextAction, BaseKit.wordMatchPrevAction }, + iconResource = { "org/netbeans/modules/editor/resources/next_matching.png", + "org/netbeans/modules/editor/resources/previous_matching.png" } + ) public static class WordMatchAction extends LocalBaseAction { - private boolean direction; + private boolean matchNext; static final long serialVersionUID =595571114685133170L; - public WordMatchAction(String name, boolean direction) { - super(name, ABBREV_RESET - | MAGIC_POSITION_RESET | UNDO_MERGE_RESET); - this.direction = direction; - putValue(BaseAction.ICON_RESOURCE_PROPERTY, - direction - ? "org/netbeans/modules/editor/resources/next_matching.png" // NOI18N - : "org/netbeans/modules/editor/resources/previous_matching.png" // NOI18N - ); - + public WordMatchAction() { + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET); + } + + @Override + protected void actionNameUpdate(String actionName) { + super.actionNameUpdate(actionName); + this.matchNext = BaseKit.wordMatchNextAction.equals(actionName); } public void actionPerformed(final ActionEvent evt, final JTextComponent target) { @@ -1336,7 +1358,7 @@ } final int dotPos = caret.getDot(); - final String s = editorUI.getWordMatch().getMatchWord(dotPos, direction); + final String s = editorUI.getWordMatch().getMatchWord(dotPos, matchNext); final String prevWord = editorUI.getWordMatch().getPreviousWord(); if (s != null) { doc.runAtomicAsUser (new Runnable () { @@ -1359,24 +1381,25 @@ } } } + } + @EditorActionRegistration(name = { BaseKit.shiftLineLeftAction, BaseKit.shiftLineRightAction }, + iconResource = { "org/netbeans/modules/editor/resources/shift_line_left.png", + "org/netbeans/modules/editor/resources/shift_line_right.png" } + ) public static class ShiftLineAction extends LocalBaseAction { - boolean right; - static final long serialVersionUID =-5124732597493699582L; - public ShiftLineAction(String name, boolean right) { - super(name, MAGIC_POSITION_RESET | UNDO_MERGE_RESET); - this.right = right; - putValue(BaseAction.ICON_RESOURCE_PROPERTY, - right - ? "org/netbeans/modules/editor/resources/shift_line_right.png" // NOI18N - : "org/netbeans/modules/editor/resources/shift_line_left.png" // NOI18N - ); + public ShiftLineAction() { + super(MAGIC_POSITION_RESET | UNDO_MERGE_RESET); + } + @Override + protected void actionNameUpdate(String actionName) { + super.actionNameUpdate(actionName); } public void actionPerformed (final ActionEvent evt, final JTextComponent target) { @@ -1393,6 +1416,7 @@ DocumentUtilities.setTypingModification(doc, true); Formatter.pushFormattingContextDocument(doc); try { + boolean right = BaseKit.shiftLineRightAction.equals(getValue(Action.NAME)); if (Utilities.isSelectionShowing(caret)) { doc.getFormatter().changeBlockIndent(doc, target.getSelectionStart(), target.getSelectionEnd(), @@ -1414,14 +1438,14 @@ } } + @EditorActionRegistration(name = BaseKit.reindentLineAction) public static class ReindentLineAction extends LocalBaseAction { static final long serialVersionUID =1L; public ReindentLineAction() { // TODO: figure out what these flags are all about - super(BaseKit.reindentLineAction, - ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET); + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET); //putValue ("helpID", ReindentLineAction.class.getName ()); } @@ -1495,12 +1519,26 @@ public static class AdjustWindowAction extends LocalBaseAction { + @EditorActionRegistration(name = BaseKit.adjustWindowTopAction) + public static AdjustWindowAction createAdjustTop() { + return new AdjustWindowAction(0); + } + + @EditorActionRegistration(name = BaseKit.adjustWindowCenterAction) + public static AdjustWindowAction createAdjustCenter() { + return new AdjustWindowAction(50); + } + + @EditorActionRegistration(name = BaseKit.adjustWindowBottomAction) + public static AdjustWindowAction createAdjustBottom() { + return new AdjustWindowAction(100); + } + int percentFromWindowTop; static final long serialVersionUID =8864278998999643292L; - public AdjustWindowAction(String name, int percentFromWindowTop) { - super(name); + public AdjustWindowAction(int percentFromWindowTop) { this.percentFromWindowTop = percentFromWindowTop; } @@ -1513,12 +1551,26 @@ public static class AdjustCaretAction extends LocalBaseAction { + @EditorActionRegistration(name = BaseKit.adjustCaretTopAction) + public static AdjustCaretAction createAdjustTop() { + return new AdjustCaretAction(0); + } + + @EditorActionRegistration(name = BaseKit.adjustCaretCenterAction) + public static AdjustCaretAction createAdjustCenter() { + return new AdjustCaretAction(50); + } + + @EditorActionRegistration(name = BaseKit.adjustCaretBottomAction) + public static AdjustCaretAction createAdjustBottom() { + return new AdjustCaretAction(100); + } + int percentFromWindowTop; static final long serialVersionUID =3223383913531191066L; - public AdjustCaretAction(String name, int percentFromWindowTop) { - super(name); + public AdjustCaretAction(int percentFromWindowTop) { this.percentFromWindowTop = percentFromWindowTop; } @@ -1529,13 +1581,13 @@ } } + @EditorActionRegistration(name = BaseKit.formatAction) public static class FormatAction extends LocalBaseAction { static final long serialVersionUID =-7666172828961171865L; public FormatAction() { - super(BaseKit.formatAction, - ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET); + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET); //#54893 putValue ("helpID", FormatAction.class.getName ()); // NOI18N } @@ -1619,16 +1671,13 @@ } + @EditorActionRegistration(name = { BaseKit.firstNonWhiteAction, BaseKit.selectionFirstNonWhiteAction }) public static class FirstNonWhiteAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =-5888439539790901158L; - public FirstNonWhiteAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET - | WORD_MATCH_RESET); - this.select = select; + public FirstNonWhiteAction() { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1638,6 +1687,7 @@ int pos = Utilities.getRowFirstNonWhite((BaseDocument)target.getDocument(), caret.getDot()); if (pos >= 0) { + boolean select = BaseKit.selectionFirstNonWhiteAction.equals(getValue(Action.NAME)); if (select) { caret.moveDot(pos); } else { @@ -1651,16 +1701,13 @@ } } + @EditorActionRegistration(name = { BaseKit.lastNonWhiteAction, BaseKit.selectionLastNonWhiteAction }) public static class LastNonWhiteAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =4503533041729712917L; - public LastNonWhiteAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET - | WORD_MATCH_RESET); - this.select = select; + public LastNonWhiteAction() { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1670,6 +1717,7 @@ int pos = Utilities.getRowLastNonWhite((BaseDocument)target.getDocument(), caret.getDot()); if (pos >= 0) { + boolean select = BaseKit.selectionLastNonWhiteAction.equals(getValue(Action.NAME)); if (select) { caret.moveDot(pos); } else { @@ -1683,12 +1731,13 @@ } } + @EditorActionRegistration(name = BaseKit.selectIdentifierAction) public static class SelectIdentifierAction extends LocalBaseAction { static final long serialVersionUID =-7288216961333147873L; public SelectIdentifierAction() { - super(BaseKit.selectIdentifierAction, MAGIC_POSITION_RESET); + super(MAGIC_POSITION_RESET); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1712,6 +1761,7 @@ } } + @EditorActionRegistration(name = BaseKit.selectNextParameterAction) public static class SelectNextParameterAction extends LocalBaseAction { static final long serialVersionUID =8045372985336370934L; @@ -1762,6 +1812,7 @@ * in the editor module. */ public static class JumpListNextAction extends LocalBaseAction { + // Not registered by annotation since it's not actively used static final long serialVersionUID =6891721278404990446L; PropertyChangeListener pcl; @@ -1790,6 +1841,7 @@ * in the editor module. */ public static class JumpListPrevAction extends LocalBaseAction { + // Not registered by annotation since it's not actively used static final long serialVersionUID =7174907031986424265L; PropertyChangeListener pcl; @@ -1818,6 +1870,7 @@ * in the editor module. */ public static class JumpListNextComponentAction extends LocalBaseAction { + // Not registered by annotation since it's not actively used static final long serialVersionUID =-2059070050865876892L; @@ -1837,6 +1890,7 @@ * in the editor module. */ public static class JumpListPrevComponentAction extends LocalBaseAction { + // Not registered by annotation since it's not actively used static final long serialVersionUID =2032230534727849525L; @@ -1851,10 +1905,10 @@ } } + @EditorActionRegistration(name = BaseKit.scrollUpAction) public static class ScrollUpAction extends LocalBaseAction { public ScrollUpAction() { - super(BaseKit.scrollUpAction); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1869,10 +1923,10 @@ } + @EditorActionRegistration(name = BaseKit.scrollDownAction) public static class ScrollDownAction extends LocalBaseAction { public ScrollDownAction() { - super(BaseKit.scrollDownAction); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1887,13 +1941,13 @@ } + @EditorActionRegistration(name = BaseKit.insertDateTimeAction) public static class InsertDateTimeAction extends LocalBaseAction { static final long serialVersionUID =2865619897402L; public InsertDateTimeAction() { - super(BaseKit.insertDateTimeAction, - ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1921,12 +1975,12 @@ } /** Select text of whole document */ + @EditorActionRegistration(name = BaseKit.generateGutterPopupAction) public static class GenerateGutterPopupAction extends LocalBaseAction { static final long serialVersionUID =-3502499718130556525L; public GenerateGutterPopupAction() { - super(BaseKit.generateGutterPopupAction); putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE); } @@ -1945,6 +1999,7 @@ } /** Switch visibility of line numbers in editor */ + @EditorActionRegistration(name = BaseKit.toggleLineNumbersAction) public static class ToggleLineNumbersAction extends LocalBaseAction { static final long serialVersionUID =-3502499718130556526L; @@ -1952,7 +2007,7 @@ private JCheckBoxMenuItem item = null; public ToggleLineNumbersAction() { - super(BaseKit.toggleLineNumbersAction); + super(BaseKit.toggleLineNumbersAction); // Due to creation from MainMenuAction } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1981,10 +2036,10 @@ } /** Cycle through annotations on the current line */ + @EditorActionRegistration(name = BaseKit.annotationsCyclingAction) public static class AnnotationsCyclingAction extends LocalBaseAction { public AnnotationsCyclingAction() { - super(BaseKit.annotationsCyclingAction); putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE); } @@ -2079,9 +2134,9 @@ } /** Collapse a fold. Depends on the current caret position. */ + @EditorActionRegistration(name = BaseKit.collapseFoldAction) public static class CollapseFold extends LocalBaseAction { public CollapseFold(){ - super(BaseKit.collapseFoldAction); } private boolean dotInFoldArea(JTextComponent target, Fold fold, int dot) throws BadLocationException{ @@ -2121,9 +2176,9 @@ } /** Expand a fold. Depends on the current caret position. */ + @EditorActionRegistration(name = BaseKit.expandFoldAction) public static class ExpandFold extends LocalBaseAction { public ExpandFold(){ - super(BaseKit.expandFoldAction); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -2148,9 +2203,9 @@ } /** Collapse all existing folds in the document. */ + @EditorActionRegistration(name = BaseKit.collapseAllFoldsAction) public static class CollapseAllFolds extends LocalBaseAction { public CollapseAllFolds(){ - super(BaseKit.collapseAllFoldsAction); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -2161,9 +2216,9 @@ } /** Expand all existing folds in the document. */ + @EditorActionRegistration(name = BaseKit.expandAllFoldsAction) public static class ExpandAllFolds extends LocalBaseAction { public ExpandAllFolds(){ - super(BaseKit.expandAllFoldsAction); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -2174,10 +2229,10 @@ } /** Expand all existing folds in the document. */ + @EditorActionRegistration(name = "dump-view-hierarchy") public static class DumpViewHierarchyAction extends LocalBaseAction { public DumpViewHierarchyAction() { - super("dump-view-hierarchy"); // NOI18N putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE); } @@ -2223,10 +2278,10 @@ } /** Starts a new line in code. */ + @EditorActionRegistration(name = BaseKit.startNewLineAction) public static class StartNewLine extends LocalBaseAction { public StartNewLine(){ - super( BaseKit.startNewLineAction, ABBREV_RESET - | MAGIC_POSITION_RESET | UNDO_MERGE_RESET); + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET); } public void actionPerformed (final ActionEvent evt, final JTextComponent target) { @@ -2268,22 +2323,16 @@ * Cut text from the caret position to either begining or end * of the line with the caret. */ + @EditorActionRegistration(name = { BaseKit.cutToLineBeginAction, BaseKit.cutToLineEndAction }) public static class CutToLineBeginOrEndAction extends LocalBaseAction { /** - * Whether cutting to line end instead of line begin. - */ - private final boolean toLineEnd; - - /** * Construct new action. * * @param toLineEnd whether cutting to line end instead of line begin. */ - public CutToLineBeginOrEndAction(boolean toLineEnd) { - super(toLineEnd ? BaseKit.cutToLineEndAction : BaseKit.cutToLineBeginAction, - ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET); - this.toLineEnd = toLineEnd; + public CutToLineBeginOrEndAction() { + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET); } public void actionPerformed (final ActionEvent evt, final JTextComponent target) { @@ -2304,6 +2353,7 @@ if (actionMap != null && (cutAction = actionMap.get(DefaultEditorKit.cutAction)) != null) { Caret caret = target.getCaret(); int caretOffset = caret.getDot(); + boolean toLineEnd = BaseKit.cutToLineEndAction.equals(getValue(Action.NAME)); int boundOffset = toLineEnd ? Utilities.getRowEnd(target, caretOffset) : Utilities.getRowStart(target, caretOffset); diff --git a/editor.lib/src/org/netbeans/editor/BaseAction.java b/editor.lib/src/org/netbeans/editor/BaseAction.java --- a/editor.lib/src/org/netbeans/editor/BaseAction.java +++ b/editor.lib/src/org/netbeans/editor/BaseAction.java @@ -127,6 +127,14 @@ static final long serialVersionUID =-4255521122272110786L; + public BaseAction() { + this(null); + } + + public BaseAction(int updateMask) { + this(null, updateMask); + } + public BaseAction(String name) { this(name, 0); } @@ -156,7 +164,27 @@ return obj; } - + + @Override + public void putValue(String key, Object value) { + super.putValue(key, value); + if (Action.NAME.equals(key) && value instanceof String) { + actionNameUpdate((String)value); + } + } + + /** + * Called by {@link #putValue(String,String)} when {@link Action#NAME} property + * is set to a non-null String value. This allows a "polymorphic" action (with + * Action.NAME-specific behavior) to update certain properties (e.g. an icon) + * according to the name that was set. + * + * @param actionName non-null action's name (value of Action.NAME property). + * @since 1.34 + */ + protected void actionNameUpdate(String actionName) { + } + /** * This method is called when there is no value for the particular key. *
diff --git a/editor.lib/src/org/netbeans/editor/BaseKit.java b/editor.lib/src/org/netbeans/editor/BaseKit.java --- a/editor.lib/src/org/netbeans/editor/BaseKit.java +++ b/editor.lib/src/org/netbeans/editor/BaseKit.java @@ -77,6 +77,7 @@ import javax.swing.text.AbstractDocument; import javax.swing.text.EditorKit; import javax.swing.text.Position; +import org.netbeans.api.editor.EditorActionRegistration; import org.netbeans.api.editor.mimelookup.MimeLookup; import org.netbeans.api.editor.mimelookup.MimePath; import org.netbeans.api.editor.settings.KeyBindingSettings; @@ -691,9 +692,17 @@ */ public static Map actionsToMap(Action[] actions) { Map map = new HashMap(); - for (Action a : actions) { + for (int i = 0; i < actions.length; i++) { + Action a = actions[i]; + if (a == null) { + throw new IllegalStateException("actions[] contains null at index " + i + + ((i > 0) ? ". Preceding action is " + actions[i - 1] : "")); + } String name = (String) a.getValue(Action.NAME); - map.put(((name != null) ? name : ""), a); // NOI18N + if (name == null) { + throw new IllegalStateException("Null Action.NAME property of action " + a); + } + map.put(name, a); // NOI18N } return map; } @@ -824,107 +833,107 @@ */ protected Action[] createActions() { return new Action[] { - new DefaultKeyTypedAction(), - new InsertContentAction(), +// annotation-registration new DefaultKeyTypedAction(), +// annotation-registration new InsertContentAction(), insertBreakActionDef, - new SplitLineAction(), +// annotation-registration new SplitLineAction(), insertTabActionDef, deletePrevCharActionDef, deleteNextCharActionDef, - new ReadOnlyAction(), - new WritableAction(), +// annotation-registration new ReadOnlyAction(), +// annotation-registration new WritableAction(), cutActionDef, copyActionDef, pasteActionDef, new PasteAction(true), - new BeepAction(), - new UpAction(upAction, false), - new UpAction(selectionUpAction, true), - new PageUpAction(pageUpAction, false), - new PageUpAction(selectionPageUpAction, true), - new DownAction(downAction, false), - new DownAction(selectionDownAction, true), - new PageDownAction(selectionPageDownAction, true), - new PageDownAction(pageDownAction, false), - new ForwardAction(forwardAction, false), - new ForwardAction(selectionForwardAction, true), - new BackwardAction(backwardAction, false), - new BackwardAction(selectionBackwardAction, true), - new BeginLineAction(lineFirstColumnAction, false, true), - new BeginLineAction(selectionLineFirstColumnAction, true, true), - new BeginLineAction(beginLineAction, false), - new BeginLineAction(selectionBeginLineAction, true), - new EndLineAction(endLineAction, false), - new EndLineAction(selectionEndLineAction, true), - new BeginAction(beginAction, false), - new BeginAction(selectionBeginAction, true), - new EndAction(endAction, false), - new EndAction(selectionEndAction, true), - new NextWordAction(nextWordAction, false), - new NextWordAction(selectionNextWordAction, true), - new PreviousWordAction(previousWordAction, false), - new PreviousWordAction(selectionPreviousWordAction, true), - new BeginWordAction(beginWordAction, false), - new BeginWordAction(selectionBeginWordAction, true), - new EndWordAction(endWordAction, false), - new EndWordAction(selectionEndWordAction, true), - new SelectWordAction(), - new SelectLineAction(), - new SelectAllAction(), - new RemoveTrailingSpacesAction(), +// annotation-registration new BeepAction(), +// annotation-registration new UpAction(upAction, false), +// annotation-registration new UpAction(selectionUpAction, true), +// annotation-registration new PageUpAction(pageUpAction, false), +// annotation-registration new PageUpAction(selectionPageUpAction, true), +// annotation-registration new DownAction(downAction, false), +// annotation-registration new DownAction(selectionDownAction, true), +// annotation-registration new PageDownAction(selectionPageDownAction, true), +// annotation-registration new PageDownAction(pageDownAction, false), +// annotation-registration new ForwardAction(forwardAction, false), +// annotation-registration new ForwardAction(selectionForwardAction, true), +// annotation-registration new BackwardAction(backwardAction, false), +// annotation-registration new BackwardAction(selectionBackwardAction, true), +// annotation-registration new BeginLineAction(lineFirstColumnAction, false, true), +// annotation-registration new BeginLineAction(selectionLineFirstColumnAction, true, true), +// annotation-registration new BeginLineAction(beginLineAction, false), +// annotation-registration new BeginLineAction(selectionBeginLineAction, true), +// annotation-registration new EndLineAction(endLineAction, false), +// annotation-registration new EndLineAction(selectionEndLineAction, true), +// annotation-registration new BeginAction(beginAction, false), +// annotation-registration new BeginAction(selectionBeginAction, true), +// annotation-registration new EndAction(endAction, false), +// annotation-registration new EndAction(selectionEndAction, true), +// annotation-registration new NextWordAction(nextWordAction, false), +// annotation-registration new NextWordAction(selectionNextWordAction, true), +// annotation-registration new PreviousWordAction(previousWordAction, false), +// annotation-registration new PreviousWordAction(selectionPreviousWordAction, true), +// annotation-registration new BeginWordAction(beginWordAction, false), +// annotation-registration new BeginWordAction(selectionBeginWordAction, true), +// annotation-registration new EndWordAction(endWordAction, false), +// annotation-registration new EndWordAction(selectionEndWordAction, true), +// annotation-registration new SelectWordAction(), +// annotation-registration new SelectLineAction(), +// annotation-registration new SelectAllAction(), +// annotation-registration new RemoveTrailingSpacesAction(), removeTabActionDef, //new ActionFactory.RemoveWordAction(), #47709 - new ActionFactory.RemoveWordPreviousAction(), - new ActionFactory.RemoveWordNextAction(), - new ActionFactory.RemoveLineBeginAction(), - new ActionFactory.RemoveLineAction(), - new ActionFactory.MoveSelectionElseLineUpAction(), - new ActionFactory.MoveSelectionElseLineDownAction(), - new ActionFactory.CopySelectionElseLineUpAction(), - new ActionFactory.CopySelectionElseLineDownAction(), +// annotation-registration new ActionFactory.RemoveWordPreviousAction(), +// annotation-registration new ActionFactory.RemoveWordNextAction(), +// annotation-registration new ActionFactory.RemoveLineBeginAction(), +// annotation-registration new ActionFactory.RemoveLineAction(), +// annotation-registration new ActionFactory.MoveSelectionElseLineUpAction(), +// annotation-registration new ActionFactory.MoveSelectionElseLineDownAction(), +// annotation-registration new ActionFactory.CopySelectionElseLineUpAction(), +// annotation-registration new ActionFactory.CopySelectionElseLineDownAction(), removeSelectionActionDef, - new ActionFactory.ToggleTypingModeAction(), - new ActionFactory.ChangeCaseAction(toUpperCaseAction, Utilities.CASE_UPPER), - new ActionFactory.ChangeCaseAction(toLowerCaseAction, Utilities.CASE_LOWER), - new ActionFactory.ChangeCaseAction(switchCaseAction, Utilities.CASE_SWITCH), - new ActionFactory.FindNextAction(), - new ActionFactory.FindPreviousAction(), - new ActionFactory.FindSelectionAction(), - new ActionFactory.ToggleHighlightSearchAction(), +// annotation-registration new ActionFactory.ToggleTypingModeAction(), +// annotation-registration new ActionFactory.ChangeCaseAction(toUpperCaseAction, Utilities.CASE_UPPER), +// annotation-registration new ActionFactory.ChangeCaseAction(toLowerCaseAction, Utilities.CASE_LOWER), +// annotation-registration new ActionFactory.ChangeCaseAction(switchCaseAction, Utilities.CASE_SWITCH), +// annotation-registration new ActionFactory.FindNextAction(), +// annotation-registration new ActionFactory.FindPreviousAction(), +// annotation-registration new ActionFactory.FindSelectionAction(), +// annotation-registration new ActionFactory.ToggleHighlightSearchAction(), undoActionDef, redoActionDef, - new ActionFactory.WordMatchAction(wordMatchNextAction, true), - new ActionFactory.WordMatchAction(wordMatchPrevAction, false), - new ActionFactory.ReindentLineAction(), - new ActionFactory.ShiftLineAction(shiftLineLeftAction, false), - new ActionFactory.ShiftLineAction(shiftLineRightAction, true), - new ActionFactory.AdjustWindowAction(adjustWindowTopAction, 0), - new ActionFactory.AdjustWindowAction(adjustWindowCenterAction, 50), - new ActionFactory.AdjustWindowAction(adjustWindowBottomAction, 100), - new ActionFactory.AdjustCaretAction(adjustCaretTopAction, 0), - new ActionFactory.AdjustCaretAction(adjustCaretCenterAction, 50), - new ActionFactory.AdjustCaretAction(adjustCaretBottomAction, 100), - new ActionFactory.FormatAction(), - new ActionFactory.FirstNonWhiteAction(firstNonWhiteAction, false), - new ActionFactory.FirstNonWhiteAction(selectionFirstNonWhiteAction, true), - new ActionFactory.LastNonWhiteAction(lastNonWhiteAction, false), - new ActionFactory.LastNonWhiteAction(selectionLastNonWhiteAction, true), - new ActionFactory.SelectIdentifierAction(), - new ActionFactory.SelectNextParameterAction(), - new ActionFactory.ScrollUpAction(), - new ActionFactory.ScrollDownAction(), - new ActionFactory.InsertDateTimeAction(), - new ActionFactory.GenerateGutterPopupAction(), - new ActionFactory.ToggleLineNumbersAction(), - new ActionFactory.AnnotationsCyclingAction(), - new ActionFactory.CollapseFold(), - new ActionFactory.ExpandFold(), - new ActionFactory.CollapseAllFolds(), - new ActionFactory.ExpandAllFolds(), - new ActionFactory.DumpViewHierarchyAction(), - new ActionFactory.StartNewLine(), - new ActionFactory.CutToLineBeginOrEndAction(false), - new ActionFactory.CutToLineBeginOrEndAction(true), +// annotation-registration new ActionFactory.WordMatchAction(wordMatchNextAction, true), +// annotation-registration new ActionFactory.WordMatchAction(wordMatchPrevAction, false), +// annotation-registration new ActionFactory.ReindentLineAction(), +// annotation-registration new ActionFactory.ShiftLineAction(shiftLineLeftAction, false), +// annotation-registration new ActionFactory.ShiftLineAction(shiftLineRightAction, true), +// annotation-registration new ActionFactory.AdjustWindowAction(adjustWindowTopAction, 0), +// annotation-registration new ActionFactory.AdjustWindowAction(adjustWindowCenterAction, 50), +// annotation-registration new ActionFactory.AdjustWindowAction(adjustWindowBottomAction, 100), +// annotation-registration new ActionFactory.AdjustCaretAction(adjustCaretTopAction, 0), +// annotation-registration new ActionFactory.AdjustCaretAction(adjustCaretCenterAction, 50), +// annotation-registration new ActionFactory.AdjustCaretAction(adjustCaretBottomAction, 100), +// annotation-registration new ActionFactory.FormatAction(), +// annotation-registration new ActionFactory.FirstNonWhiteAction(firstNonWhiteAction, false), +// annotation-registration new ActionFactory.FirstNonWhiteAction(selectionFirstNonWhiteAction, true), +// annotation-registration new ActionFactory.LastNonWhiteAction(lastNonWhiteAction, false), +// annotation-registration new ActionFactory.LastNonWhiteAction(selectionLastNonWhiteAction, true), +// annotation-registration new ActionFactory.SelectIdentifierAction(), +// annotation-registration new ActionFactory.SelectNextParameterAction(), +// annotation-registration new ActionFactory.ScrollUpAction(), +// annotation-registration new ActionFactory.ScrollDownAction(), +// annotation-registration new ActionFactory.InsertDateTimeAction(), +// annotation-registration new ActionFactory.GenerateGutterPopupAction(), +// annotation-registration new ActionFactory.ToggleLineNumbersAction(), +// annotation-registration new ActionFactory.AnnotationsCyclingAction(), +// annotation-registration new ActionFactory.CollapseFold(), +// annotation-registration new ActionFactory.ExpandFold(), +// annotation-registration new ActionFactory.CollapseAllFolds(), +// annotation-registration new ActionFactory.ExpandAllFolds(), +// annotation-registration new ActionFactory.DumpViewHierarchyAction(), +// annotation-registration new ActionFactory.StartNewLine(), +// annotation-registration new ActionFactory.CutToLineBeginOrEndAction(false), +// annotation-registration new ActionFactory.CutToLineBeginOrEndAction(true), // Self test actions // new EditorDebug.SelfTestAction(), @@ -1033,11 +1042,13 @@ /** Default typed action */ + @EditorActionRegistration(name = defaultKeyTypedAction) public static class DefaultKeyTypedAction extends LocalBaseAction { static final long serialVersionUID =3069164318144463899L; public DefaultKeyTypedAction() { + // Construct with defaultKeyTypedAction name to retain full compatibility for extending actions super(defaultKeyTypedAction, MAGIC_POSITION_RESET | CLEAR_STATUS_TEXT); putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE); LOG.fine("DefaultKeyTypedAction with enhanced logging, see issue #145306"); //NOI18N @@ -1246,12 +1257,13 @@ } } + @EditorActionRegistration(name = splitLineAction) public static class SplitLineAction extends LocalBaseAction { static final long serialVersionUID =7966576342334158659L; public SplitLineAction() { - super(splitLineAction, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET); + super(MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET); } public void actionPerformed(final ActionEvent evt, final JTextComponent target) { @@ -1417,6 +1429,15 @@ static final long serialVersionUID =8415246475764264835L; + public KitCompoundAction(String actionNames[]) { + this(0, actionNames); + } + + public KitCompoundAction(int resetMask, String actionNames[]) { + super(resetMask); + this.actionNames = actionNames; + } + public KitCompoundAction(String nm, String actionNames[]) { this(nm, 0, actionNames); } @@ -1445,13 +1466,13 @@ } } + @EditorActionRegistration(name = insertContentAction) public static class InsertContentAction extends LocalBaseAction { static final long serialVersionUID =5647751370952797218L; public InsertContentAction() { - super(insertContentAction, MAGIC_POSITION_RESET | ABBREV_RESET - | WORD_MATCH_RESET); + super(MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET); putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE); } @@ -1559,12 +1580,12 @@ } } + @EditorActionRegistration(name = readOnlyAction) public static class ReadOnlyAction extends LocalBaseAction { static final long serialVersionUID =9204335480208463193L; public ReadOnlyAction() { - super(readOnlyAction); putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE); } @@ -1575,12 +1596,12 @@ } } + @EditorActionRegistration(name = writableAction) public static class WritableAction extends LocalBaseAction { static final long serialVersionUID =-5982547952800937954L; public WritableAction() { - super(writableAction); putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE); } @@ -1668,12 +1689,10 @@ public static class PasteAction extends LocalBaseAction { static final long serialVersionUID =5839791453996432149L; - private boolean formatted; - public PasteAction(boolean formated) { - super(formated ? pasteFormatedAction : pasteAction, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); - //#54893 putValue ("helpID", PasteAction.class.getName ()); // NOI18N - this.formatted = formated; + public PasteAction(boolean formatted) { + super(formatted ? pasteFormatedAction : pasteAction, + ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed(final ActionEvent evt, final JTextComponent target) { @@ -1694,6 +1713,7 @@ } final Formatter formatter = doc.getFormatter(); + final boolean formatted = pasteFormatedAction.equals(getValue(Action.NAME)); if (formatted) { formatter.reformatLock(); } @@ -1792,13 +1812,12 @@ } - + @EditorActionRegistration(name = beepAction) public static class BeepAction extends LocalBaseAction { static final long serialVersionUID =-4474054576633223968L; public BeepAction() { - super(beepAction); putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE); } @@ -1810,16 +1829,13 @@ } + @EditorActionRegistration(name = { upAction, selectionUpAction }) public static class UpAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =4621760742646981563L; - public UpAction(String nm, boolean select) { - super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET - | CLEAR_STATUS_TEXT); - this.select = select; + public UpAction() { + super(ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1839,6 +1855,7 @@ } try { dot = Utilities.getPositionAbove(target, dot, p.x); + boolean select = selectionUpAction.equals(getValue(Action.NAME)); if (select) { caret.moveDot(dot); } else { @@ -1854,16 +1871,13 @@ } } + @EditorActionRegistration(name = { downAction, selectionDownAction }) public static class DownAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =-5635702355125266822L; - public DownAction(String nm, boolean select) { - super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET - | CLEAR_STATUS_TEXT); - this.select = select; + public DownAction() { + super(ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1883,6 +1897,7 @@ } try { dot = Utilities.getPositionBelow(target, dot, p.x); + boolean select = selectionDownAction.equals(getValue(Action.NAME)); if (select) { caret.moveDot(dot); } else { @@ -1899,16 +1914,13 @@ } /** Go one page up */ + @EditorActionRegistration(name = { pageUpAction, selectionPageUpAction }) public static class PageUpAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =-3107382148581661079L; - public PageUpAction(String nm, boolean select) { - super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET - | CLEAR_STATUS_TEXT); - this.select = select; + public PageUpAction() { + super(ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1985,7 +1997,8 @@ newCaretOffset = target.viewToModel(newCaretPoint); newCaretBounds = target.modelToView(newCaretOffset); } - + + boolean select = selectionPageUpAction.equals(getValue(Action.NAME)); if (select) { caret.moveDot(newCaretOffset); } else { @@ -2003,16 +2016,14 @@ } } + @EditorActionRegistration(name = { forwardAction, selectionForwardAction }) public static class ForwardAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =8007293230193334414L; - public ForwardAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET - | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); - this.select = select; + public ForwardAction() { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET + | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -2020,6 +2031,7 @@ Caret caret = target.getCaret(); try { int pos; + boolean select = selectionForwardAction.equals(getValue(Action.NAME)); if (!select && Utilities.isSelectionShowing(caret)) { pos = target.getSelectionEnd(); @@ -2048,23 +2060,20 @@ } /** Go one page down */ + @EditorActionRegistration(name = { pageDownAction, selectionPageDownAction }) public static class PageDownAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =8942534850985048862L; - public PageDownAction(String nm, boolean select) { - super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET - | CLEAR_STATUS_TEXT); - this.select = select; + public PageDownAction() { + super(ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET + | CLEAR_STATUS_TEXT); } public void actionPerformed(ActionEvent evt, JTextComponent target) { if (target != null) { try { Caret caret = target.getCaret(); - BaseDocument doc = (BaseDocument)target.getDocument(); int caretOffset = caret.getDot(); Rectangle caretBounds = ((BaseTextUI)target.getUI()).modelToView(target, caretOffset); if (caretBounds == null) { @@ -2129,7 +2138,8 @@ newCaretOffset = target.viewToModel(newCaretPoint); newCaretBounds = target.modelToView(newCaretOffset); } - + + boolean select = selectionPageDownAction.equals(getValue(Action.NAME)); if (select) { caret.moveDot(newCaretOffset); } else { @@ -2147,16 +2157,14 @@ } } + @EditorActionRegistration(name = { backwardAction, selectionBackwardAction }) public static class BackwardAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =-3048379822817847356L; - public BackwardAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET + public BackwardAction() { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); - this.select = select; } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -2164,6 +2172,7 @@ Caret caret = target.getCaret(); try { int pos; + boolean select = selectionBackwardAction.equals(getValue(Action.NAME)); if (!select && Utilities.isSelectionShowing(caret)) { pos = target.getSelectionStart(); @@ -2193,7 +2202,15 @@ public static class BeginLineAction extends LocalBaseAction { - protected boolean select; + @EditorActionRegistration(name = { beginLineAction, selectionBeginLineAction }) + public static BeginLineAction create() { + return new BeginLineAction(false); + } + + @EditorActionRegistration(name = { lineFirstColumnAction, selectionLineFirstColumnAction }) + public static BeginLineAction createColumnOne() { + return new BeginLineAction(true); + } /** Whether the action should go to the begining of * the text on the line or to the first column on the line*/ @@ -2201,15 +2218,9 @@ static final long serialVersionUID =3269462923524077779L; - public BeginLineAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET + public BeginLineAction(boolean columnOne) { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); - this.select = select; - homeKeyColumnOne = false; - } - - public BeginLineAction(String nm, boolean select, boolean columnOne) { - this(nm, select); homeKeyColumnOne = columnOne; } @@ -2235,6 +2246,9 @@ dot = textStartPos; } } + String actionName = (String) getValue(Action.NAME); + boolean select = selectionBeginLineAction.equals(actionName) + || selectionLineFirstColumnAction.equals(actionName); if (select) { caret.moveDot(dot); } else { @@ -2247,16 +2261,14 @@ } } + @EditorActionRegistration(name = { endLineAction, selectionEndLineAction }) public static class EndLineAction extends LocalBaseAction { - protected boolean select; - static final long serialVersionUID =5216077634055190170L; - public EndLineAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET + public EndLineAction() { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); - this.select = select; } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -2264,6 +2276,7 @@ Caret caret = target.getCaret(); try { int dot = Utilities.getRowEnd(target, caret.getDot()); + boolean select = selectionEndLineAction.equals(getValue(Action.NAME)); if (select) { caret.moveDot(dot); } else { @@ -2283,22 +2296,21 @@ } } + @EditorActionRegistration(name = { beginAction, selectionBeginAction }) public static class BeginAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =3463563396210234361L; - public BeginAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET + public BeginAction() { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | SAVE_POSITION | CLEAR_STATUS_TEXT); - this.select = select; } public void actionPerformed(ActionEvent evt, JTextComponent target) { if (target != null) { Caret caret = target.getCaret(); int dot = 0; // begin of document + boolean select = selectionBeginAction.equals(getValue(Action.NAME)); if (select) { caret.moveDot(dot); } else { @@ -2308,22 +2320,21 @@ } } + @EditorActionRegistration(name = { endAction, selectionEndAction }) public static class EndAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =8547506353130203657L; - public EndAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET + public EndAction() { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | SAVE_POSITION | CLEAR_STATUS_TEXT); - this.select = select; } public void actionPerformed(ActionEvent evt, JTextComponent target) { if (target != null) { Caret caret = target.getCaret(); int dot = target.getDocument().getLength(); // end of document + boolean select = selectionEndAction.equals(getValue(Action.NAME)); if (select) { caret.moveDot(dot); } else { @@ -2333,16 +2344,14 @@ } } + @EditorActionRegistration(name = { nextWordAction, selectionNextWordAction }) public static class NextWordAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =-5909906947175434032L; - public NextWordAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET + public NextWordAction() { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); - this.select = select; } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -2351,6 +2360,7 @@ try { int dotPos = caret.getDot(); dotPos = Utilities.getNextWord(target, dotPos); + boolean select = selectionNextWordAction.equals(getValue(Action.NAME)); if (caret instanceof BaseCaret){ BaseCaret bCaret = (BaseCaret) caret; if (select) { @@ -2372,16 +2382,14 @@ } } + @EditorActionRegistration(name = { previousWordAction, selectionPreviousWordAction }) public static class PreviousWordAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =-5465143382669785799L; - public PreviousWordAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET + public PreviousWordAction() { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); - this.select = select; } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -2389,6 +2397,7 @@ Caret caret = target.getCaret(); try { int dot = Utilities.getPreviousWord(target, caret.getDot()); + boolean select = selectionPreviousWordAction.equals(getValue(Action.NAME)); if (caret instanceof BaseCaret){ BaseCaret bCaret = (BaseCaret) caret; if (select) { @@ -2410,16 +2419,14 @@ } } + @EditorActionRegistration(name = { beginWordAction, selectionBeginAction }) public static class BeginWordAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =3991338381212491110L; - public BeginWordAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET + public BeginWordAction() { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); - this.select = select; } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -2427,6 +2434,7 @@ Caret caret = target.getCaret(); try { int dot = Utilities.getWordStart(target, caret.getDot()); + boolean select = selectionBeginAction.equals(getValue(Action.NAME)); if (select) { caret.moveDot(dot); } else { @@ -2439,16 +2447,14 @@ } } + @EditorActionRegistration(name = { endWordAction, selectionEndWordAction }) public static class EndWordAction extends LocalBaseAction { - boolean select; - static final long serialVersionUID =3812523676620144633L; - public EndWordAction(String nm, boolean select) { - super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET + public EndWordAction() { + super(MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET | CLEAR_STATUS_TEXT); - this.select = select; } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -2456,6 +2462,7 @@ Caret caret = target.getCaret(); try { int dot = Utilities.getWordEnd(target, caret.getDot()); + boolean select = selectionEndWordAction.equals(getValue(Action.NAME)); if (select) { caret.moveDot(dot); } else { @@ -2469,13 +2476,13 @@ } /** Select word around caret */ + @EditorActionRegistration(name = selectWordAction) public static class SelectWordAction extends KitCompoundAction { static final long serialVersionUID =7678848538073016357L; public SelectWordAction() { - super(selectWordAction, - new String[] { + super(new String[] { beginWordAction, selectionEndWordAction } @@ -2485,12 +2492,12 @@ } /** Select line around caret */ + @EditorActionRegistration(name = selectLineAction) public static class SelectLineAction extends LocalBaseAction { static final long serialVersionUID =-7407681863035740281L; public SelectLineAction() { - super(selectLineAction); } public void actionPerformed(final ActionEvent evt, final JTextComponent target) { @@ -2519,13 +2526,13 @@ } /** Select text of whole document */ + @EditorActionRegistration(name = selectAllAction) public static class SelectAllAction extends KitCompoundAction { static final long serialVersionUID =-3502499718130556524L; public SelectAllAction() { - super(selectAllAction, - new String[] { + super(new String[] { beginAction, selectionEndAction } @@ -2533,11 +2540,11 @@ } } - + + @EditorActionRegistration(name = removeTrailingSpacesAction) public static class RemoveTrailingSpacesAction extends LocalBaseAction { public RemoveTrailingSpacesAction() { - super(removeTrailingSpacesAction); } protected boolean asynchonous() { diff --git a/editor.lib/src/org/netbeans/editor/LocalBaseAction.java b/editor.lib/src/org/netbeans/editor/LocalBaseAction.java --- a/editor.lib/src/org/netbeans/editor/LocalBaseAction.java +++ b/editor.lib/src/org/netbeans/editor/LocalBaseAction.java @@ -51,6 +51,14 @@ abstract class LocalBaseAction extends BaseAction { + public LocalBaseAction() { + super(); + } + + public LocalBaseAction(int updateMask) { + super(updateMask); + } + public LocalBaseAction(String name) { super(name); } diff --git a/editor.lib/src/org/netbeans/editor/ext/ExtKit.java b/editor.lib/src/org/netbeans/editor/ext/ExtKit.java --- a/editor.lib/src/org/netbeans/editor/ext/ExtKit.java +++ b/editor.lib/src/org/netbeans/editor/ext/ExtKit.java @@ -56,6 +56,7 @@ import javax.swing.text.JTextComponent; import javax.swing.text.TextAction; import javax.swing.text.BadLocationException; +import org.netbeans.api.editor.EditorActionRegistration; import org.netbeans.api.editor.mimelookup.MimeLookup; import org.netbeans.editor.BaseKit; import org.netbeans.editor.EditorUI; @@ -171,6 +172,7 @@ private static ReplaceAction replaceActionDef = new ReplaceAction(); private static GotoAction gotoActionDef = new GotoAction(); + private static final String editorBundleHash = "org.netbeans.editor.Bundle#"; /** Whether editor popup menu creation should be dumped to console */ private static final boolean debugPopupMenu @@ -214,22 +216,22 @@ protected @Override Action[] createActions() { ArrayList actions = new ArrayList(); - actions.add(new BuildPopupMenuAction()); - actions.add(new ShowPopupMenuAction()); - actions.add(new BuildToolTipAction()); +// annotation-registration actions.add(new BuildPopupMenuAction()); +// annotation-registration actions.add(new ShowPopupMenuAction()); +// annotation-registration actions.add(new BuildToolTipAction()); actions.add(replaceActionDef); actions.add(gotoActionDef); - actions.add(new ToggleCaseIdentifierBeginAction()); +// annotation-registration actions.add(new ToggleCaseIdentifierBeginAction()); // XXX: remove // if (!ExtCaret.NO_HIGHLIGHT_BRACE_LAYER) { // actions.add(new MatchBraceAction(matchBraceAction, false)); // actions.add(new MatchBraceAction(selectionMatchBraceAction, true)); // } - actions.add(new ExtDefaultKeyTypedAction()); - actions.add(new CompletionShowAction()); - actions.add(new AllCompletionShowAction()); - actions.add(new DocumentationShowAction()); - actions.add(new CompletionTooltipShowAction()); +// annotation-registration actions.add(new ExtDefaultKeyTypedAction()); +// annotation-registration actions.add(new CompletionShowAction()); +// annotation-registration actions.add(new AllCompletionShowAction()); +// annotation-registration actions.add(new DocumentationShowAction()); +// annotation-registration actions.add(new CompletionTooltipShowAction()); actions.add(new CommentAction()); // to make ctrl-shift-T in Netbeans55 profile work actions.add(new UncommentAction()); // to make ctrl-shift-D in Netbeans55 profile work @@ -242,7 +244,15 @@ * BaseKit.class is used as a bundle class. */ private abstract static class BaseKitLocalizedAction extends BaseAction { - + + public BaseKitLocalizedAction() { + super(); + } + + public BaseKitLocalizedAction(int updateMask) { + super(updateMask); + } + public BaseKitLocalizedAction(String name) { super(name); } @@ -260,12 +270,16 @@ /** Called before the popup menu is shown to possibly rebuild * the popup menu. */ + @EditorActionRegistration( + name = buildPopupMenuAction, + shortDescription = editorBundleHash + buildPopupMenuAction + ) public static class BuildPopupMenuAction extends BaseKitLocalizedAction { static final long serialVersionUID =4257043398248915291L; public BuildPopupMenuAction() { - super(buildPopupMenuAction, NO_RECORDING); + super(NO_RECORDING); putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE); } @@ -396,12 +410,16 @@ /** Show the popup menu. */ + @EditorActionRegistration( + name = showPopupMenuAction, + shortDescription = editorBundleHash + showPopupMenuAction + ) public static class ShowPopupMenuAction extends BaseKitLocalizedAction { static final long serialVersionUID =4257043398248915291L; public ShowPopupMenuAction() { - super(showPopupMenuAction, NO_RECORDING); + super(NO_RECORDING); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -423,14 +441,17 @@ } + @EditorActionRegistration( + name = buildToolTipAction, + shortDescription = editorBundleHash + buildToolTipAction + ) public static class BuildToolTipAction extends BaseAction { static final long serialVersionUID =-2701131863705941250L; public BuildToolTipAction() { - super(buildToolTipAction, NO_RECORDING); + super(NO_RECORDING); putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE); - putValue(Action.SHORT_DESCRIPTION, ""); // No explicit description NOI18N } protected String buildText(JTextComponent target) { @@ -455,6 +476,7 @@ * @deprecated Without any replacement. */ public static class FindAction extends BaseKitLocalizedAction { + // Not registered by annotation since it's not actively used static final long serialVersionUID =719554648887497427L; @@ -577,13 +599,13 @@ } } + @EditorActionRegistration(name = toggleCaseIdentifierBeginAction, shortDescription = "") public static class ToggleCaseIdentifierBeginAction extends BaseKitLocalizedAction { static final long serialVersionUID =584392193824931979L; ToggleCaseIdentifierBeginAction() { - super(toggleCaseIdentifierBeginAction, ABBREV_RESET - | MAGIC_POSITION_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -997,6 +1019,10 @@ // Completion customized actions + @EditorActionRegistration( + name = defaultKeyTypedAction, + shortDescription = editorBundleHash + defaultKeyTypedAction + ) public static class ExtDefaultKeyTypedAction extends DefaultKeyTypedAction { static final long serialVersionUID =5273032708909044812L; @@ -1104,12 +1130,15 @@ * @deprecated Please use Editor Code Completion API instead, for details see * Editor Code Completion. */ + @EditorActionRegistration( + name = completionShowAction, + shortDescription = editorBundleHash + completionShowAction + ) public static class CompletionShowAction extends BaseKitLocalizedAction { static final long serialVersionUID =1050644925893851146L; public CompletionShowAction() { - super(completionShowAction); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1121,10 +1150,13 @@ * @deprecated Please use Editor Code Completion API instead, for details see * Editor Code Completion. */ + @EditorActionRegistration( + name = allCompletionShowAction, + shortDescription = editorBundleHash + allCompletionShowAction + ) public static class AllCompletionShowAction extends BaseKitLocalizedAction { public AllCompletionShowAction() { - super(allCompletionShowAction); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1136,10 +1168,13 @@ * @deprecated Please use Editor Code Completion API instead, for details see * Editor Code Completion. */ + @EditorActionRegistration( + name = documentationShowAction, + shortDescription = editorBundleHash + documentationShowAction + ) public static class DocumentationShowAction extends BaseKitLocalizedAction { public DocumentationShowAction() { - super(documentationShowAction); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -1151,10 +1186,13 @@ * @deprecated Please use Editor Code Completion API instead, for details see * Editor Code Completion. */ + @EditorActionRegistration( + name = completionTooltipShowAction, + shortDescription = editorBundleHash + completionTooltipShowAction + ) public static class CompletionTooltipShowAction extends BaseKitLocalizedAction { public CompletionTooltipShowAction() { - super(completionTooltipShowAction); } public void actionPerformed(ActionEvent evt, JTextComponent target) { diff --git a/editor.lib2/apichanges.xml b/editor.lib2/apichanges.xml --- a/editor.lib2/apichanges.xml +++ b/editor.lib2/apichanges.xml @@ -105,6 +105,21 @@ + + EditorActionRegistration annotation added + + + + + + EditorActionRegistration allows to easily register an editor action + into the list of actions of an editor kit. It also allows a lazy + action's class loading (more details in javadoc). + + + + + Code Generation SPI added @@ -118,7 +133,7 @@ them into documents on the Insert Code editor action invocation. The CodeGeneratorContextProvider implementations registered for the mime types could provide the respective - CodeGenerators with an additional context information. + CodeGenerators with an additional context information. diff --git a/editor.lib2/nbproject/project.properties b/editor.lib2/nbproject/project.properties --- a/editor.lib2/nbproject/project.properties +++ b/editor.lib2/nbproject/project.properties @@ -40,7 +40,10 @@ is.autoload=true javac.source=1.5 javac.compilerargs=-Xlint:unchecked -spec.version.base=1.9.0 +spec.version.base=1.10.0 +cp.extra=${nb_all}/apisupport.harness/external/openjdk-javac-6-b12.jar +test.unit.cp.extra= +test.unit.run.cp.extra=${nb_all}/apisupport.harness/external/openjdk-javac-6-b12.jar javadoc.arch=${basedir}/arch.xml javadoc.apichanges=${basedir}/apichanges.xml diff --git a/editor.lib2/nbproject/project.xml b/editor.lib2/nbproject/project.xml --- a/editor.lib2/nbproject/project.xml +++ b/editor.lib2/nbproject/project.xml @@ -87,7 +87,7 @@ - 7.0 + 7.7
@@ -144,6 +144,14 @@ org.netbeans.modules.editor.mimelookup.impl + + org.openide.loaders + + + org.openide.util + + + qa-functional diff --git a/editor.lib2/src/org/netbeans/api/editor/EditorActionRegistration.java b/editor.lib2/src/org/netbeans/api/editor/EditorActionRegistration.java new file mode 100644 --- /dev/null +++ b/editor.lib2/src/org/netbeans/api/editor/EditorActionRegistration.java @@ -0,0 +1,135 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ + +package org.netbeans.api.editor; + +/** + * Registration of an editor action so that it's automatically added into the list + * of editor actions even without being explicitly created by BaseKit.createActions(). + *
+ * The corresponding annotation processor will build a xml-layer entry file + * in the corresponding /Editors/<mime-type>/Actions folder. + * + * @since 1.10 + * @author Miloslav Metelka + */ +public @interface EditorActionRegistration { + + /** + * Name(s) of the action that will appear as Action.NAME attribute's value. + *
+ * If array is given then multiple registrations (for each name) will be done + * (the action may internally switch its functioning according to its Action.NAME). + *
+ * The Swing's text package actions use convention of lowercase letters with hyphens + * - see String constants in {@link javax.swing.text.DefaultEditorKit}. + * + * @return value of Action.NAME attribute. + */ + String[] name(); + + /** + * Mime type for which the action will be registered. + *
+ * It implies the target folder of the registration /Editors/<mime-type>/Actions. + * + * @return mime-type of the action registration (for example "text/x-java" + * or empty string which means that the action will be registered as global (for all mime-types). + */ + String mimeType() default ""; + + /** + * Resource specification(s) for small icon. + * If multiple names are given in {@link #name()} then the same-size array + * should be used for icon resources. + * + * @return icon resource specification or default (empty string which means no icon). + */ + String[] iconResource() default ""; + + /** + * Short description bundle key(s) of the registered action(s). + * Several constructions are allowed:
    + *
  • + * Leave the annotation's default value which means that the short description + * will be searched in a bundle located in the same package as the action's class + * by a key equal to action's name (value of Action.NAME property). + *
  • + *
  • + * Value starting with a hash "#key" searches in a bundle in the same package + * as the action's class. + *
  • + *
  • + * "bundle#key" allows specification of both bundle and a corresponding key. + *
  • + *
  • + * Empty string "" means that nothing will be generated and delegate action + * will be created and asked for the value of Action.SHORT_DESCRIPTION property. + *
  • + *
+ */ + String[] shortDescription() default "BY_ACTION_NAME"; + + /** + * Menu text bundle key(s) of the registered action(s). + * If an empty string is used (the default) it will be set to the same value + * like action's short description. + *
+ * Value starting with a hash "#key" searches in a bundle in the same package + * as the action's class. + *
+ * "bundle#key" allows specification of both bundle and a corresponding key. + */ + String[] menuText() default ""; + + /** + * Popup menu text bundle key(s) of the registered action(s). + * If an empty string is used (the default) it will be set to the same value + * like menu text. + *
+ * Value starting with a hash "#key" searches in a bundle in the same package + * as the action's class. + *
+ * "bundle#key" allows specification of both bundle and a corresponding key. + */ + String[] popupText() default ""; + +} diff --git a/editor.lib2/src/org/netbeans/modules/editor/lib2/EditorActionRegistrationProcessor.java b/editor.lib2/src/org/netbeans/modules/editor/lib2/EditorActionRegistrationProcessor.java new file mode 100644 --- /dev/null +++ b/editor.lib2/src/org/netbeans/modules/editor/lib2/EditorActionRegistrationProcessor.java @@ -0,0 +1,353 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.editor.lib2; + +import java.io.IOException; +import java.util.MissingResourceException; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; +import java.util.Set; +import javax.annotation.processing.Filer; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.swing.Action; +import javax.tools.StandardLocation; +import org.netbeans.api.editor.EditorActionRegistration; +import org.openide.filesystems.annotations.LayerBuilder; +import org.openide.filesystems.annotations.LayerGeneratingProcessor; +import org.openide.filesystems.annotations.LayerGenerationException; +import org.openide.util.lookup.ServiceProvider; + +/** + * Annotation processor for + */ +@ServiceProvider(service=Processor.class) +@SupportedSourceVersion(SourceVersion.RELEASE_6) +@SupportedAnnotationTypes("org.netbeans.api.editor.EditorActionRegistration")//NOI18N +public final class EditorActionRegistrationProcessor extends LayerGeneratingProcessor { + + @Override + protected boolean handleProcess(Set annotations, + RoundEnvironment roundEnv) throws LayerGenerationException + { + if (roundEnv.processingOver()) { + return false; + } + for (Element e : roundEnv.getElementsAnnotatedWith(EditorActionRegistration.class)) { + EditorActionRegistration annotation = e.getAnnotation(EditorActionRegistration.class); + String className; + String methodName; + TypeMirror swingActionType = processingEnv.getTypeUtils().getDeclaredType( + processingEnv.getElementUtils().getTypeElement("javax.swing.Action")); + + switch (e.getKind()) { + case CLASS: + className = processingEnv.getElementUtils().getBinaryName((TypeElement)e).toString(); + if (e.getModifiers().contains(Modifier.ABSTRACT)) { + throw new LayerGenerationException(className + " must not be abstract", e); + } + if (!e.getModifiers().contains(Modifier.PUBLIC)) { + throw new LayerGenerationException(className + " is not public", e); + } + boolean hasDefaultCtor = false; + for (ExecutableElement constructor : ElementFilter.constructorsIn(e.getEnclosedElements())) { + if (constructor.getParameters().isEmpty()) { + if (!constructor.getModifiers().contains(Modifier.PUBLIC)) { + throw new LayerGenerationException("Default constructor of " + className + " is not public", e); + } + hasDefaultCtor = true; + break; + } + } + if (!hasDefaultCtor) { + throw new LayerGenerationException(className + " must have a no-argument constructor", e); + } + + if (!processingEnv.getTypeUtils().isAssignable(e.asType(), swingActionType)) { + throw new LayerGenerationException(className + " is not assignable to javax.swing.Action", e); + } + + methodName = null; + break; + + case METHOD: + className = processingEnv.getElementUtils().getBinaryName((TypeElement) e.getEnclosingElement()).toString(); + methodName = e.getSimpleName().toString(); + if (!e.getModifiers().contains(Modifier.STATIC)) { + throw new LayerGenerationException(className + "." + methodName + " must be static", e); + } + // It appears that actually even non-public method registration works - so commented following +// if (!e.getModifiers().contains(Modifier.PUBLIC)) { +// throw new LayerGenerationException(className + "." + methodName + " must be public", e); +// } + if (!((ExecutableElement) e).getParameters().isEmpty()) { + throw new LayerGenerationException(className + "." + methodName + " must not take arguments", e); + } + if (swingActionType != null && !processingEnv.getTypeUtils().isAssignable(((ExecutableElement)e).getReturnType(), swingActionType)) { + throw new LayerGenerationException(className + "." + methodName + " is not assignable to javax.swing.Action", e); + } + break; + + default: + throw new IllegalArgumentException("Annotated element is not loadable as an instance: " + e); + + } + + String[] actionNames = annotation.name(); // name() is Array of names + String[] iconResources = annotation.iconResource(); // Array of strings in fact + String[] shortDescriptions = annotation.shortDescription(); + String[] menuTexts = annotation.menuText(); + String[] popupTexts = annotation.popupText(); + BundleHandler commonBundleHandler = null; // Bundle in action's package + + // For more than one name the same amount of icon resources is expected + // If annotation's default value is used an array with one default item is passed. + // If non-default single value is used then it's possibly used for all declared actions. + checkArraySize(actionNames, iconResources, "iconResource", className); + checkArraySize(actionNames, shortDescriptions, "shortDescription", className); + checkArraySize(actionNames, menuTexts, "menuText", className); + checkArraySize(actionNames, popupTexts, "popupText", className); + + for (int i = 0; i < actionNames.length; i++) { + String actionName = actionNames[i]; + StringBuilder filePath = new StringBuilder(50); + filePath.append("Editors"); + if (annotation.mimeType().length() > 0) { + filePath.append("/").append(annotation.mimeType()); + } + filePath.append("/Actions/").append(actionName).append(".instance"); + LayerBuilder.File file = layer(e).file(filePath.toString()); + + file.stringvalue("displayName", actionName); + + // Resolve icon resource + String iconResource = (iconResources.length > 1) ? iconResources[i] : iconResources[0]; + if (iconResource.length() > 0) { + file.stringvalue("iconBase", iconResource); + } + + // Resolve short description bundle key + String shortDescription = (shortDescriptions.length > 1) + ? shortDescriptions[i] + : shortDescriptions[0]; + if (shortDescription.length() > 0) { + BundleHandler bundleHandler = new BundleHandler(actionName, className); + String key; + if ("BY_ACTION_NAME".equals(shortDescription)) { + // Leave bundlePkg and bundleName null + key = actionName; + } else { + key = bundleHandler.parseKey(shortDescription); + } + if (bundleHandler.initBundle(commonBundleHandler)) { + commonBundleHandler = bundleHandler; + } + bundleHandler.verifyBundleKey(key); + shortDescription = bundleHandler.completeKey(key); + file.bundlevalue(Action.SHORT_DESCRIPTION, shortDescription); + } + + // Resolve menu text bundle key + String menuText = (menuTexts.length > 1) ? menuTexts[i] : menuTexts[0]; + if (menuText.length() > 0) { + BundleHandler bundleHandler = new BundleHandler(actionName, className); + String key = bundleHandler.parseKey(menuText); + if (bundleHandler.initBundle(commonBundleHandler)) { + commonBundleHandler = bundleHandler; + } + bundleHandler.verifyBundleKey(key); + menuText = bundleHandler.completeKey(key); + file.bundlevalue("menuText", menuText); + } else if (shortDescription.length() > 0) { // Use shortDesc (already verified) + menuText = shortDescription; + file.bundlevalue("menuText", menuText); + } + + // Resolve popup menu text bundle key + String popupText = (popupTexts.length > 1) ? popupTexts[i] : popupTexts[0]; + if (popupText.length() > 0) { + BundleHandler bundleHandler = new BundleHandler(actionName, className); + String key = bundleHandler.parseKey(popupText); + if (bundleHandler.initBundle(commonBundleHandler)) { + commonBundleHandler = bundleHandler; + } + bundleHandler.verifyBundleKey(key); + popupText = bundleHandler.completeKey(key); + file.bundlevalue("popupText", popupText); + } else if (menuText.length() > 0) { // Use shortDesc (already verified) + popupText = menuText; + file.bundlevalue("popupText", popupText); + } + + file.methodvalue("instanceCreate", "org.openide.awt.Actions", "alwaysEnabled"); + if (methodName != null) { + file.methodvalue("delegate", className, methodName); + } else { + file.newvalue("delegate", className); + } + file.write(); + } + } + return true; + } + + + + private final class BundleHandler { + + String bundlePkg; + + String bundleName; + + ResourceBundle bundle; + + final String actionName; + + final String actionClassName; + + BundleHandler(String actionName, String actionClassName) { + this.actionName = actionName; + this.actionClassName = actionClassName; + } + + String parseKey(String keyDescription) throws LayerGenerationException { + String key; + if (keyDescription.startsWith("#")) { + // Leave bundlePkg and bundleName null + key = keyDescription.substring(1); + } else { // Full spec "bundle#key" + int hashIndex = keyDescription.indexOf('#'); + if (hashIndex == -1) { + throw new LayerGenerationException("Annotation \"" + actionName + // NOI18N + ", class=" + actionClassName + // NOI18N + ": bundle key description does not contain '#': " + keyDescription); + } + // Bundle-pkg.bundle-name format + bundlePkg = keyDescription.substring(0, hashIndex); + int lastDotIndex = bundlePkg.lastIndexOf('.'); + if (lastDotIndex == -1) { + lastDotIndex = 0; + } + bundleName = bundlePkg.substring(lastDotIndex + 1); + bundlePkg = bundlePkg.substring(0, lastDotIndex); + key = keyDescription.substring(hashIndex + 1); + } + return key; + } + + boolean initBundle(BundleHandler commonHandler) throws LayerGenerationException { + boolean useAsCommon = (commonHandler == null && bundlePkg == null); + if (commonHandler != null) { + if ((bundlePkg == null || bundlePkg.equals(commonHandler.bundlePkg)) && + (bundleName == null || bundleName.equals(commonHandler.bundleName))) + { + bundle = commonHandler.bundle; + bundlePkg = commonHandler.bundlePkg; + bundleName = commonHandler.bundleName; + + } + } + if (bundle == null) { + if (bundlePkg == null) { // Use common bundle in action's package + assert (bundleName == null); + int lastDotIndex = actionClassName.lastIndexOf('.'); + if (lastDotIndex == -1) // no dots + { + lastDotIndex = 0; + } + bundlePkg = actionClassName.substring(0, lastDotIndex); + bundleName = "Bundle"; + } + } + assert (bundlePkg != null && bundleName != null); + try { + String bundleNameSuffix = bundleName + ".properties"; + javax.tools.FileObject bundleFileObject = processingEnv.getFiler().getResource( + StandardLocation.SOURCE_PATH, bundlePkg, bundleNameSuffix); + bundle = new PropertyResourceBundle(bundleFileObject.openInputStream()); + } catch (IOException ex) { +// ex.printStackTrace(); // Print the queried file + throw new LayerGenerationException("Action annotation \"" + actionName + // NOI18N + "\", class=" + actionClassName + // NOI18N + ": Bundle \"" + bundlePkg + '.' + bundleName + // NOI18N + "\" not found."); // NOI18N + } + return useAsCommon; + } + + void verifyBundleKey(String key) throws LayerGenerationException { + try { + bundle.getString(key); // would throw MissingResourceException + } catch (MissingResourceException ex) { + throw new LayerGenerationException("Action annotation \"" + actionName + // NOI18N + "\", class=" + actionClassName + // NOI18N + ": Bundle \"" + bundlePkg + '.' + bundleName + // NOI18N + "\" does not contain key \"" + key + '"'); // NOI18N + } + } + + String completeKey(String key) { + return bundlePkg + '.' + bundleName + '#' + key; + } + + } + + private void checkArraySize(String[] actionNames, String[] array, String propertyName, + String actionClassName) throws LayerGenerationException + { + // If annotation's default value is used an array with one default item is passed + // so test checks for that case. + if (actionNames.length > 1 && array.length > 1 && actionNames.length != array.length) { + throw new LayerGenerationException("Action annotation \"" + actionNames[0] + // NOI18N + "\", class=" + actionClassName + ": annotation.name().length=" + actionNames.length + // NOI18N + " != " + propertyName + "().length=" + array.length); // NOI18N + } + } + +} diff --git a/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/testactionsregistration/Bundle.properties b/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/testactionsregistration/Bundle.properties new file mode 100644 --- /dev/null +++ b/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/testactionsregistration/Bundle.properties @@ -0,0 +1,46 @@ +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. +# +# The contents of this file are subject to the terms of either the GNU +# General Public License Version 2 only ("GPL") or the Common +# Development and Distribution License("CDDL") (collectively, the +# "License"). You may not use this file except in compliance with the +# License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the +# specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header +# Notice in each file and include the License file at +# nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the GPL Version 2 section of the License file that +# accompanied this code. If applicable, add the following below the +# License Header, with the fields enclosed by brackets [] replaced by +# your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# Contributor(s): +# +# The Original Software is NetBeans. The Initial Developer of the Original +# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun +# Microsystems, Inc. All Rights Reserved. +# +# If you wish your version of this file to be governed by only the CDDL +# or only the GPL Version 2, indicate your decision by adding +# "[Contributor] elects to include this software in this distribution +# under the [CDDL or GPL Version 2] license." If you do not indicate a +# single choice of license, a recipient has the option to distribute +# your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. +# However, if you add GPL Version 2 code and therefore, elected the GPL +# Version 2 license, then the option applies only if the new code is +# made subject to such option by the copyright holder. + +# Editor Testing Actions short descriptions +editor-test-action1=Short Desc1 +editor-test-action-explicit=Short Desc2 +editor-test-action3=Short Desc3 +editor-test-action2_menu_text=Menu Text2 +editor-test-action3_menu_text=Menu Text3 +editor-test-action3_popup_text=Popup Text3 diff --git a/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/testactionsregistration/EditorActionRegistrationTest.java b/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/testactionsregistration/EditorActionRegistrationTest.java new file mode 100644 --- /dev/null +++ b/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/testactionsregistration/EditorActionRegistrationTest.java @@ -0,0 +1,185 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ + +package org.netbeans.modules.editor.lib2.testactionsregistration; + +import java.awt.event.ActionEvent; +import java.io.ByteArrayOutputStream; +import javax.swing.AbstractAction; +import javax.swing.Action; +import org.netbeans.junit.NbTestCase; +import org.netbeans.api.editor.EditorActionRegistration; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.test.AnnotationProcessorTestUtils; + +/** + * Test registration of editor actions through an annotation. + * + * @author Miloslav Metelka + */ +public class EditorActionRegistrationTest extends NbTestCase { + + private static final String NAME1 = "editor-test-action1"; + private static final String NAME2 = "editor-test-action2"; + private static final String NAME3 = "editor-test-action3"; + private static final String NAME4 = "editor-test-action4"; + + private static final String bundleHash = "org.netbeans.modules.editor.lib2.testactionsregistration.Bundle#"; + + public EditorActionRegistrationTest(String name) { + super(name); + } + + public void testRegistration() throws Exception { + FileObject fo = FileUtil.getConfigFile("/Editors/Actions/" + NAME1 + ".instance"); + assertNotNull(fo); + assertEquals(NAME1, fo.getAttribute("displayName")); + assertEquals("Short Desc1", fo.getAttribute(Action.SHORT_DESCRIPTION)); + assertEquals("Short Desc1", fo.getAttribute("menuText")); + assertEquals("Short Desc1", fo.getAttribute("popupText")); + + fo = FileUtil.getConfigFile("/Editors/Actions/" + NAME2 + ".instance"); + assertNotNull(fo); + assertEquals(NAME2, fo.getAttribute("displayName")); + assertEquals("Short Desc2", fo.getAttribute(Action.SHORT_DESCRIPTION)); + assertEquals("Menu Text2", fo.getAttribute("menuText")); + assertEquals("Menu Text2", fo.getAttribute("popupText")); + + fo = FileUtil.getConfigFile("/Editors/Actions/" + NAME3 + ".instance"); + assertNotNull(fo); + assertEquals(NAME3, fo.getAttribute("displayName")); + assertEquals("Short Desc3", fo.getAttribute(Action.SHORT_DESCRIPTION)); + assertEquals("Menu Text3", fo.getAttribute("menuText")); + assertEquals("Popup Text3", fo.getAttribute("popupText")); + } + + public void testNonPublicClass() throws Exception { + String nonPublicClassSource = + "import org.netbeans.api.editor.EditorActionRegistration;\n" + + "import javax.swing.AbstractAction;\n" + + "import javax.swing.event.ActionEvent;\n" + + "@EditorActionRegistration(name = \"NonPublicClass\", shortDescription = \"\")\n" + + "static final class EditorTestActionNonPublic extends AbstractAction {\n" + + " public EditorTestActionNonPublic() {}\n" + + " @Override\n" + + " public void actionPerformed(ActionEvent evt) {}\n"+ + "}\n"; + checkCompilationFails(nonPublicClassSource); + } + + public void testNonPublicConstructor() throws Exception { + String nonPublicConstructorSource = + "import org.netbeans.api.editor.EditorActionRegistration;\n" + + "import javax.swing.AbstractAction;\n" + + "import javax.swing.event.ActionEvent;\n" + + "@EditorActionRegistration(name = \"NonPublicClass\", shortDescription = \"\")\n" + + "public static final class EditorTestActionNonPublic extends AbstractAction {\n" + + " EditorTestActionNonPublic() {}\n" + + " @Override\n" + + " public void actionPerformed(ActionEvent evt) {}\n"+ + "}\n"; + checkCompilationFails(nonPublicConstructorSource); + + } + + public void checkCompilationFails(String classSource) throws Exception { + AnnotationProcessorTestUtils.makeSource(getWorkDir(), "x.EditorTestActionNonPublic", classSource); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + boolean res = AnnotationProcessorTestUtils.runJavac(getWorkDir(), null, getWorkDir(), null, out); + assertFalse("Compilation failed", res); + if (!out.toString().contains("is not public")) { + fail(out.toString()); + } + } + + @EditorActionRegistration(name = NAME1) + public static final class EditorTestAction extends AbstractAction { + + public EditorTestAction() { + } + + @Override + public void actionPerformed(ActionEvent evt) { + } + + } + + @EditorActionRegistration( + name = NAME2, + shortDescription="#editor-test-action-explicit", + menuText = bundleHash + NAME2 + "_menu_text" + // popupText same like menuText + ) + public static EditorTestAction createAction2() { + return new EditorTestAction(); + } + + @EditorActionRegistration( + name = NAME3, + menuText = "#" + NAME3 + "_menu_text", + popupText = "#" + NAME3 + "_popup_text" + ) + public static EditorTestAction createAction3() { + return new EditorTestAction(); + } + + @EditorActionRegistration( + name = NAME4, + shortDescription = "" + ) + public static EditorTestAction createAction4() { + return new EditorTestAction(); + } + + @EditorActionRegistration(name = "NonPublicClass", shortDescription = "") + public static final class EditorTestActionNonPublic extends AbstractAction { + + public EditorTestActionNonPublic() { + } + + @Override + public void actionPerformed(ActionEvent evt) { + } + + } + +} diff --git a/editor/nbproject/project.xml b/editor/nbproject/project.xml --- a/editor/nbproject/project.xml +++ b/editor/nbproject/project.xml @@ -129,7 +129,7 @@ - 6.5 + 7.7
diff --git a/editor/src/org/netbeans/modules/editor/Bundle.properties b/editor/src/org/netbeans/modules/editor/Bundle.properties --- a/editor/src/org/netbeans/modules/editor/Bundle.properties +++ b/editor/src/org/netbeans/modules/editor/Bundle.properties @@ -59,6 +59,8 @@ CTL_Toolbar_hint=Toolbar contents customization PROP_addToolbarSeparator=Add Separator +build-popup-menu=Build Popup Menu +build-tool-tip=Build Tool Tip generate-goto-popup=Generate Goto Popup generate-fold-popup=Generate Fold Popup goto_source_main_menu_edit_item=Go to &Source @@ -69,6 +71,8 @@ jump_back_main_menu_item=&Back jump_forward_main_menu_item=For&ward toggle_comment_main_menu_item=Toggle Co&mment +toggle-line-numbers=Toggle Line Numbers +toggle-toolbar=Toggle Toolbar comment_main_menu_item=Co&mment uncomment_main_menu_item=&Uncomment shift_line_left_main_menu_item=Shift &Left diff --git a/editor/src/org/netbeans/modules/editor/NbEditorKit.java b/editor/src/org/netbeans/modules/editor/NbEditorKit.java --- a/editor/src/org/netbeans/modules/editor/NbEditorKit.java +++ b/editor/src/org/netbeans/modules/editor/NbEditorKit.java @@ -69,6 +69,7 @@ import javax.swing.text.JTextComponent; import javax.swing.text.TextAction; import javax.swing.text.Keymap; +import org.netbeans.api.editor.EditorActionRegistration; import org.netbeans.api.editor.mimelookup.MimeLookup; import org.netbeans.api.editor.mimelookup.MimePath; import org.netbeans.api.editor.settings.SimpleValueNames; @@ -185,16 +186,16 @@ protected @Override Action[] createActions() { Action[] nbEditorActions = new Action[] { - new NbBuildPopupMenuAction(), +// annotation-registration new NbBuildPopupMenuAction(), nbUndoActionDef, nbRedoActionDef, - new NbBuildToolTipAction(), - new NbToggleLineNumbersAction(), - new ToggleToolbarAction(), - new NbGenerateGoToPopupAction(), +// annotation-registration new NbBuildToolTipAction(), +// annotation-registration new NbToggleLineNumbersAction(), +// annotation-registration new ToggleToolbarAction(), +// annotation-registration new NbGenerateGoToPopupAction(), new GenerateFoldPopupAction(), - new NbGenerateCodeAction(), - new NavigationHistoryLastEditAction(), +// annotation-registration new NbGenerateCodeAction(), +// annotation-registration new NavigationHistoryLastEditAction(), new NavigationHistoryBackAction(), new NavigationHistoryForwardAction(), new SearchBar.IncrementalSearchForwardAction(), @@ -242,7 +243,7 @@ addSystemActionMapping(deleteNextCharAction, org.openide.actions.DeleteAction.class); addSystemActionMapping(showPopupMenuAction, org.openide.actions.PopupAction.class); - addSystemActionMapping(SearchBar.IncrementalSearchForwardAction.ACTION_NAME, org.openide.actions.FindAction.class); + addSystemActionMapping(SearchBar.INCREMENTAL_SEARCH_FORWARD, org.openide.actions.FindAction.class); addSystemActionMapping(replaceAction, org.openide.actions.ReplaceAction.class); addSystemActionMapping(gotoAction, org.openide.actions.GotoAction.class); @@ -280,11 +281,11 @@ return bundle; } - + @EditorActionRegistration(name = toggleToolbarAction) public static class ToggleToolbarAction extends BaseAction { public ToggleToolbarAction() { - super(ExtKit.toggleToolbarAction); + super(toggleToolbarAction); // Due to creation from MainMenuAction putValue ("helpID", ToggleToolbarAction.class.getName ()); // NOI18N } @@ -366,6 +367,7 @@ } } + @EditorActionRegistration(name = buildPopupMenuAction) public class NbBuildPopupMenuAction extends BuildPopupMenuAction { static final long serialVersionUID =-8623762627678464181L; @@ -567,6 +569,7 @@ } /** Switch visibility of line numbers in editor */ + @EditorActionRegistration(name = BaseKit.toggleLineNumbersAction) public static class NbToggleLineNumbersAction extends ActionFactory.ToggleLineNumbersAction { public NbToggleLineNumbersAction() { @@ -584,10 +587,11 @@ } } + @EditorActionRegistration(name = generateGoToPopupAction) public static class NbGenerateGoToPopupAction extends BaseAction { public NbGenerateGoToPopupAction() { - super(generateGoToPopupAction); + super(generateGoToPopupAction); // Because of action in Gsf putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE); } @@ -601,6 +605,7 @@ } + @EditorActionRegistration(name = buildToolTipAction) public static class NbBuildToolTipAction extends BuildToolTipAction { public @Override void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -610,7 +615,9 @@ } } - + +// No registration - NO_KEYBINDING property in constructor +// @EditorActionRegistration(name = generateFoldPopupAction) public static class GenerateFoldPopupAction extends BaseAction { private boolean addSeparatorBeforeNextAction; @@ -749,7 +756,7 @@ } public LayerSubFolderMenu(JTextComponent target, FileObject folder) { - this(target, getLocalizedName(folder), ActionsList.convert(sort(folder.getChildren()))); + this(target, getLocalizedName(folder), ActionsList.convert(sort(folder.getChildren()), false)); } private static List sort( FileObject[] children ) { diff --git a/editor/src/org/netbeans/modules/editor/NbEditorUI.java b/editor/src/org/netbeans/modules/editor/NbEditorUI.java --- a/editor/src/org/netbeans/modules/editor/NbEditorUI.java +++ b/editor/src/org/netbeans/modules/editor/NbEditorUI.java @@ -174,7 +174,7 @@ super.installUI(c); if (!attached){ - attachSystemActionPerformer(SearchBar.IncrementalSearchForwardAction.ACTION_NAME); + attachSystemActionPerformer(SearchBar.INCREMENTAL_SEARCH_FORWARD); attachSystemActionPerformer(ExtKit.replaceAction); attachSystemActionPerformer(ExtKit.gotoAction); attachSystemActionPerformer(ExtKit.showPopupMenuAction); diff --git a/editor/src/org/netbeans/modules/editor/codegen/NbGenerateCodeAction.java b/editor/src/org/netbeans/modules/editor/codegen/NbGenerateCodeAction.java --- a/editor/src/org/netbeans/modules/editor/codegen/NbGenerateCodeAction.java +++ b/editor/src/org/netbeans/modules/editor/codegen/NbGenerateCodeAction.java @@ -56,6 +56,7 @@ import javax.swing.SwingUtilities; import javax.swing.text.BadLocationException; import javax.swing.text.JTextComponent; +import org.netbeans.api.editor.EditorActionRegistration; import org.netbeans.api.editor.mimelookup.MimeLookup; import org.netbeans.editor.BaseAction; import org.netbeans.editor.ext.ExtKit; @@ -69,15 +70,17 @@ * * @author Dusan Balek, Jan Lahoda */ +@EditorActionRegistration( + name = "generate-code", + shortDescription = "#desc-generate-code", + popupText = "#popup-generate-code" +) // NOI18N public class NbGenerateCodeAction extends BaseAction { public static final String generateCode = "generate-code"; //NOI18N public NbGenerateCodeAction(){ - super(generateCode); putValue(ExtKit.TRIMMED_TEXT, NbBundle.getBundle(NbGenerateCodeAction.class).getString("generate-code-trimmed")); //NOI18N - putValue(SHORT_DESCRIPTION, NbBundle.getBundle(NbGenerateCodeAction.class).getString("desc-generate-code")); //NOI18N - putValue(POPUP_MENU_TEXT, NbBundle.getBundle(NbGenerateCodeAction.class).getString("popup-generate-code")); //NOI18N } public void actionPerformed(ActionEvent evt, final JTextComponent target) { diff --git a/editor/src/org/netbeans/modules/editor/impl/ActionsList.java b/editor/src/org/netbeans/modules/editor/impl/ActionsList.java --- a/editor/src/org/netbeans/modules/editor/impl/ActionsList.java +++ b/editor/src/org/netbeans/modules/editor/impl/ActionsList.java @@ -28,22 +28,14 @@ * @author Vita Stejskal */ public class ActionsList { - + + // -J-Dorg.netbeans.modules.editor.impl.ActionsList.level=FINE private static final Logger LOG = Logger.getLogger(ActionsList.class.getName()); private final List all; private final List actions; /** - * Create a new ActionList instance by callingthis(keys, false). - * - * @param keys The list of objects to convert to Actions - */ - protected ActionsList(List keys) { - this(keys, false); - } - - /** * Create a new ActionList instance. The ActionList * converts a list of objects (keys) to the list of Actions * or other instances that can potentially be used in actions based UI such @@ -53,9 +45,14 @@ * * @param keys The list of objects to convert to Actions * @param ignoreFolders true if the conversion should skipp folders + * @param prohibitSeparatorsAndActionNames Treat separators and references to actions + * by using their Action.NAME as errors. This is useful for */ - protected ActionsList(List keys, boolean ignoreFolders) { - Pair p = convertImpl(keys == null ? Collections.emptyList() : keys, ignoreFolders); + protected ActionsList(List keys, boolean ignoreFolders, + boolean prohibitSeparatorsAndActionNames) + { + Pair p = convertImpl(keys == null ? Collections.emptyList() : keys, ignoreFolders, + prohibitSeparatorsAndActionNames); this.all = p.all; this.actions = p.actions; } @@ -68,8 +65,8 @@ return actions; } - public static List convert(List keys) { - return convertImpl(keys, false).all; + public static List convert(List keys, boolean prohibitSeparatorsAndActionNames) { + return convertImpl(keys, false, prohibitSeparatorsAndActionNames).all; } private static class Pair { @@ -77,7 +74,9 @@ List actions; } - private static Pair convertImpl(List keys, boolean ignoreFolders) { + private static Pair convertImpl(List keys, boolean ignoreFolders, + boolean prohibitSeparatorsAndActionNames) + { List all = new ArrayList(); List actions = new ArrayList(); @@ -85,16 +84,42 @@ DataObject dob; try { dob = DataObject.find(item); + if (dob == null && prohibitSeparatorsAndActionNames) { + if (LOG.isLoggable(Level.WARNING)) { + LOG.warning("ActionsList: DataObject is null for item=" + item + "\n"); + } + } } catch (DataObjectNotFoundException dnfe) { + if (prohibitSeparatorsAndActionNames) { + if (LOG.isLoggable(Level.WARNING)) { + LOG.warning("ActionsList: DataObject not found for item=" + item + "\n"); + } + } else { + if (LOG.isLoggable(Level.FINE)) { + LOG.log(Level.FINE, "DataObject not found for action fileObject=" + item); + } + } continue; // ignore } Object toAdd = null; InstanceCookie ic = dob.getLookup().lookup(InstanceCookie.class); + if (prohibitSeparatorsAndActionNames && ic == null) { + if (LOG.isLoggable(Level.WARNING)) { + LOG.warning("ActionsList: InstanceCookie not found for item=" + item + "\n"); + } + continue; + } if (ic != null) { try { if (!isSeparator(ic)) { toAdd = ic.instanceCreate(); + if (toAdd == null && prohibitSeparatorsAndActionNames) { + if (LOG.isLoggable(Level.WARNING)) { + LOG.warning("ActionsList: InstanceCookie.instanceCreate() null for item=" + + item + "\n"); + } + } } } catch (Exception e) { LOG.log(Level.WARNING, "Can't instantiate object", e); //NOI18N @@ -120,6 +145,11 @@ if (toAdd instanceof Action) { actions.add((Action) toAdd); } else if (isSeparator(toAdd)) { + if (prohibitSeparatorsAndActionNames) { + if (LOG.isLoggable(Level.WARNING)) { + LOG.warning("ActionsList: Separator for item=" + item + "\n"); + } + } actions.add(null); } all.add(toAdd); diff --git a/editor/src/org/netbeans/modules/editor/impl/EditorActionsProvider.java b/editor/src/org/netbeans/modules/editor/impl/EditorActionsProvider.java --- a/editor/src/org/netbeans/modules/editor/impl/EditorActionsProvider.java +++ b/editor/src/org/netbeans/modules/editor/impl/EditorActionsProvider.java @@ -73,11 +73,11 @@ } public EditorActionsProvider() { - super(null); + this(null); } private EditorActionsProvider(List keys) { - super(keys); + super(keys, false, true); // prohibit separators and action-names } public Class getClazz(){ diff --git a/editor/src/org/netbeans/modules/editor/impl/GlyphGutterActionsProvider.java b/editor/src/org/netbeans/modules/editor/impl/GlyphGutterActionsProvider.java --- a/editor/src/org/netbeans/modules/editor/impl/GlyphGutterActionsProvider.java +++ b/editor/src/org/netbeans/modules/editor/impl/GlyphGutterActionsProvider.java @@ -65,11 +65,11 @@ } public GlyphGutterActionsProvider() { - super(null); + super(null, false, false); } private GlyphGutterActionsProvider(List keys) { - super(keys); + super(keys, false, false); } public Class getClazz() { diff --git a/editor/src/org/netbeans/modules/editor/impl/PopupMenuActionsProvider.java b/editor/src/org/netbeans/modules/editor/impl/PopupMenuActionsProvider.java --- a/editor/src/org/netbeans/modules/editor/impl/PopupMenuActionsProvider.java +++ b/editor/src/org/netbeans/modules/editor/impl/PopupMenuActionsProvider.java @@ -65,11 +65,11 @@ } public PopupMenuActionsProvider() { - super(null); + super(null, false, false); } private PopupMenuActionsProvider(List keys) { - super(keys); + super(keys, false, false); } public Class getClazz(){ diff --git a/editor/src/org/netbeans/modules/editor/impl/SearchBar.java b/editor/src/org/netbeans/modules/editor/impl/SearchBar.java --- a/editor/src/org/netbeans/modules/editor/impl/SearchBar.java +++ b/editor/src/org/netbeans/modules/editor/impl/SearchBar.java @@ -100,6 +100,7 @@ import javax.swing.event.PopupMenuListener; import javax.swing.text.JTextComponent; import javax.swing.text.Keymap; +import org.netbeans.api.editor.EditorActionRegistration; import org.netbeans.api.editor.EditorRegistry; import org.netbeans.modules.editor.lib2.search.EditorFindSupport; import org.openide.awt.Mnemonics; @@ -127,6 +128,9 @@ private static final int defaultIncremantalSearchComboWidth = 200; private static final int maxIncremantalSearchComboWidth = 350; + public static final String INCREMENTAL_SEARCH_FORWARD = "incremental-search-forward"; + public static final String INCREMENTAL_SEARCH_BACKWARD = "incremental-search-backward"; + /** Shared mouse listener used for setting the border painting property * of the toolbar buttons and for invoking the popup menu. */ @@ -213,16 +217,20 @@ Action[] actions = component.getActions(); for(Action action:actions) { // Discover the keyStrokes for incremental-search-forward - if (action.getValue(Action.NAME).equals(IncrementalSearchForwardAction.ACTION_NAME)) { + String actionName = (String) action.getValue(Action.NAME); + if (actionName == null) { + LOG.warning("SearchBar: Null Action.NAME property of action: " + action + "\n"); + } + if (actionName.equals(INCREMENTAL_SEARCH_FORWARD)) { Action incrementalSearchForwardAction = action; KeyStroke[] keyStrokes = multiKeymap.getKeyStrokesForAction(incrementalSearchForwardAction); if (keyStrokes != null) { InputMap inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); for(KeyStroke ks : keyStrokes) { LOG.fine("found IncrementalSearchForwardAction, " + ks); //NOI18N - inputMap.put(ks, IncrementalSearchForwardAction.ACTION_NAME); + inputMap.put(ks, INCREMENTAL_SEARCH_FORWARD); } - getActionMap().put(IncrementalSearchForwardAction.ACTION_NAME, + getActionMap().put(INCREMENTAL_SEARCH_FORWARD, new AbstractAction() { public void actionPerformed(ActionEvent e) { findNext(); @@ -230,16 +238,16 @@ }); } // Discover the keyStrokes for incremental-search-backward - } else if (action.getValue(Action.NAME).equals(IncrementalSearchBackwardAction.ACTION_NAME)) { + } else if (action.getValue(Action.NAME).equals(INCREMENTAL_SEARCH_BACKWARD)) { Action incrementalSearchBackwardAction = action; KeyStroke[] keyStrokes = multiKeymap.getKeyStrokesForAction(incrementalSearchBackwardAction); if (keyStrokes != null) { InputMap inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); for(KeyStroke ks : keyStrokes) { LOG.fine("found IncrementalSearchBackwardAction, " + ks); //NOI18N - inputMap.put(ks, IncrementalSearchBackwardAction.ACTION_NAME); + inputMap.put(ks, INCREMENTAL_SEARCH_BACKWARD); } - getActionMap().put(IncrementalSearchBackwardAction.ACTION_NAME, + getActionMap().put(INCREMENTAL_SEARCH_BACKWARD, new AbstractAction() { public void actionPerformed(ActionEvent e) { findPrevious(); @@ -871,13 +879,11 @@ public static class IncrementalSearchForwardAction extends BaseAction { - public static final String ACTION_NAME = "incremental-search-forward"; // NOI18N - static final long serialVersionUID = -1; public IncrementalSearchForwardAction() { - super(ACTION_NAME, CLEAR_STATUS_TEXT); - putValue(SHORT_DESCRIPTION, NbBundle.getMessage(IncrementalSearchForwardAction.class, ACTION_NAME)); + super(INCREMENTAL_SEARCH_FORWARD, CLEAR_STATUS_TEXT); + putValue(SHORT_DESCRIPTION, NbBundle.getMessage(IncrementalSearchForwardAction.class, INCREMENTAL_SEARCH_FORWARD)); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -895,16 +901,14 @@ } } } - + public static class IncrementalSearchBackwardAction extends BaseAction { - public static final String ACTION_NAME = "incremental-search-backward"; // NOI18N - static final long serialVersionUID = -1; public IncrementalSearchBackwardAction() { - super(ACTION_NAME, CLEAR_STATUS_TEXT); - putValue(SHORT_DESCRIPTION, NbBundle.getMessage(IncrementalSearchBackwardAction.class, ACTION_NAME)); + super(INCREMENTAL_SEARCH_BACKWARD, CLEAR_STATUS_TEXT); + putValue(SHORT_DESCRIPTION, NbBundle.getMessage(IncrementalSearchBackwardAction.class, INCREMENTAL_SEARCH_BACKWARD)); } public void actionPerformed(ActionEvent evt, JTextComponent target) { diff --git a/editor/src/org/netbeans/modules/editor/impl/ToolbarActionsProvider.java b/editor/src/org/netbeans/modules/editor/impl/ToolbarActionsProvider.java --- a/editor/src/org/netbeans/modules/editor/impl/ToolbarActionsProvider.java +++ b/editor/src/org/netbeans/modules/editor/impl/ToolbarActionsProvider.java @@ -77,11 +77,11 @@ } public ToolbarActionsProvider() { - super(null); + super(null, false, false); } private ToolbarActionsProvider(List keys) { - super(keys, true); + super(keys, true, false); } public Class getClazz(){ @@ -107,11 +107,11 @@ public static final class LegacyToolbarActionsProvider extends ActionsList implements Class2LayerFolder, InstanceProvider { public LegacyToolbarActionsProvider() { - super(null); + this(null); } private LegacyToolbarActionsProvider(List keys) { - super(keys); + super(keys, false, false); } public Class getClazz(){ diff --git a/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryBackAction.java b/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryBackAction.java --- a/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryBackAction.java +++ b/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryBackAction.java @@ -60,6 +60,7 @@ import javax.swing.text.Element; import javax.swing.text.JTextComponent; import javax.swing.text.TextAction; +import org.netbeans.api.editor.EditorActionRegistration; import org.netbeans.editor.BaseDocument; import org.netbeans.editor.BaseKit; import org.netbeans.modules.editor.lib.NavigationHistory; @@ -97,9 +98,9 @@ private NavigationHistoryBackAction(JTextComponent component, NavigationHistory.Waypoint waypoint, String actionName) { super(BaseKit.jumpListPrevAction); - this.component = component; this.waypoint = waypoint; + putValue(SMALL_ICON, ImageUtilities.loadImageIcon("org/netbeans/modules/editor/resources/navigate_back_16.png", false)); //NOI18N if (waypoint != null) { putValue(NAME, actionName); @@ -107,7 +108,6 @@ "NavigationHistoryBackAction_Tooltip", actionName)); //NOI18N this.popupMenu = null; } else if (component != null) { - putValue(SMALL_ICON, ImageUtilities.loadImageIcon("org/netbeans/modules/editor/resources/navigate_back_16.png", false)); //NOI18N this.popupMenu = new JPopupMenu(); update(); NavigationHistory nav = NavigationHistory.getNavigations(); diff --git a/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryForwardAction.java b/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryForwardAction.java --- a/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryForwardAction.java +++ b/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryForwardAction.java @@ -53,6 +53,7 @@ import javax.swing.JPopupMenu; import javax.swing.text.JTextComponent; import javax.swing.text.TextAction; +import org.netbeans.api.editor.EditorActionRegistration; import org.netbeans.editor.BaseKit; import org.netbeans.modules.editor.lib.NavigationHistory; import org.openide.awt.DropDownButtonFactory; @@ -82,9 +83,9 @@ private NavigationHistoryForwardAction(JTextComponent component, NavigationHistory.Waypoint waypoint, String actionName) { super(BaseKit.jumpListNextAction); - this.component = component; this.waypoint = waypoint; + putValue(SMALL_ICON, ImageUtilities.loadImageIcon("org/netbeans/modules/editor/resources/navigate_forward_16.png", false)); //NOI18N if (waypoint != null) { putValue(NAME, actionName); @@ -92,7 +93,6 @@ "NavigationHistoryForwardAction_Tooltip", actionName)); //NOI18N this.popupMenu = null; } else if (component != null) { - putValue(SMALL_ICON, ImageUtilities.loadImageIcon("org/netbeans/modules/editor/resources/navigate_forward_16.png", false)); //NOI18N this.popupMenu = new JPopupMenu(); update(); NavigationHistory nav = NavigationHistory.getNavigations(); diff --git a/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryLastEditAction.java b/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryLastEditAction.java --- a/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryLastEditAction.java +++ b/editor/src/org/netbeans/modules/editor/impl/actions/NavigationHistoryLastEditAction.java @@ -47,6 +47,7 @@ import java.util.logging.Logger; import javax.swing.JMenuItem; import javax.swing.text.JTextComponent; +import org.netbeans.api.editor.EditorActionRegistration; import org.netbeans.editor.BaseAction; import org.netbeans.modules.editor.MainMenuAction; import org.netbeans.modules.editor.lib.NavigationHistory; @@ -57,14 +58,16 @@ * * @author Vita Stejskal */ +@EditorActionRegistration( + name = "jump-list-last-edit", + iconResource = "org/netbeans/modules/editor/resources/last_edit_location_16.png", + shortDescription = "#NavigationHistoryLastEditAction_Tooltip_simple" +) public final class NavigationHistoryLastEditAction extends BaseAction implements PropertyChangeListener { private static final Logger LOG = Logger.getLogger(NavigationHistoryLastEditAction.class.getName()); public NavigationHistoryLastEditAction() { - super("jump-list-last-edit"); //NOI18N - putValue(ICON_RESOURCE_PROPERTY, "org/netbeans/modules/editor/resources/last_edit_location_16.png"); // NOI18N - update(); NavigationHistory nav = NavigationHistory.getEdits(); nav.addPropertyChangeListener(WeakListeners.propertyChange(this, nav)); @@ -97,8 +100,6 @@ private void update() { NavigationHistory nav = NavigationHistory.getEdits(); - putValue(SHORT_DESCRIPTION, NbBundle.getMessage(NavigationHistoryLastEditAction.class, - "NavigationHistoryLastEditAction_Tooltip_simple")); setEnabled(nav.hasNextWaypoints() || nav.hasPreviousWaypoints() || null != nav.getCurrentWaypoint()); } diff --git a/ide.kit/test/qa-functional/data/blacklist.txt b/ide.kit/test/qa-functional/data/blacklist.txt --- a/ide.kit/test/qa-functional/data/blacklist.txt +++ b/ide.kit/test/qa-functional/data/blacklist.txt @@ -281,6 +281,126 @@ #org.netbeans.modules.xml.text.syntax.DTDKit #org.netbeans.modules.xml.text.syntax.XMLKit +# Editor Actions - issue #150875 +org.netbeans.editor.DefaultKeyTypedAction +org.netbeans.editor.InsertContentAction +org.netbeans.editor.SplitLineAction +org.netbeans.editor.ReadOnlyAction +org.netbeans.editor.WritableAction +org.netbeans.editor.BeepAction +org.netbeans.editor.UpAction +org.netbeans.editor.UpAction +org.netbeans.editor.PageUpAction +org.netbeans.editor.PageUpAction +org.netbeans.editor.DownAction +org.netbeans.editor.DownAction +org.netbeans.editor.PageDownAction +org.netbeans.editor.PageDownAction +org.netbeans.editor.ForwardAction +org.netbeans.editor.ForwardAction +org.netbeans.editor.BackwardAction +org.netbeans.editor.BackwardAction +org.netbeans.editor.BeginLineAction +org.netbeans.editor.BeginLineAction +org.netbeans.editor.BeginLineAction +org.netbeans.editor.BeginLineAction +org.netbeans.editor.EndLineAction +org.netbeans.editor.EndLineAction +org.netbeans.editor.BeginAction +org.netbeans.editor.BeginAction +org.netbeans.editor.EndAction +org.netbeans.editor.EndAction +org.netbeans.editor.NextWordAction +org.netbeans.editor.NextWordAction +org.netbeans.editor.PreviousWordAction +org.netbeans.editor.PreviousWordAction +org.netbeans.editor.BeginWordAction +org.netbeans.editor.BeginWordAction +org.netbeans.editor.EndWordAction +org.netbeans.editor.EndWordAction +org.netbeans.editor.SelectWordAction +org.netbeans.editor.SelectLineAction +org.netbeans.editor.SelectAllAction +org.netbeans.editor.RemoveTrailingSpacesAction + +org.netbeans.editor.ActionFactory.RemoveWordPreviousAction +org.netbeans.editor.ActionFactory.RemoveWordNextAction +org.netbeans.editor.ActionFactory.RemoveLineBeginAction +org.netbeans.editor.ActionFactory.RemoveLineAction +org.netbeans.editor.ActionFactory.MoveSelectionElseLineUpAction +org.netbeans.editor.ActionFactory.MoveSelectionElseLineDownAction +org.netbeans.editor.ActionFactory.CopySelectionElseLineUpAction +org.netbeans.editor.ActionFactory.CopySelectionElseLineDownAction +org.netbeans.editor.ActionFactory.ToggleTypingModeAction +org.netbeans.editor.ActionFactory.ChangeCaseAction +org.netbeans.editor.ActionFactory.ChangeCaseAction +org.netbeans.editor.ActionFactory.ChangeCaseAction +org.netbeans.editor.ActionFactory.FindNextAction +org.netbeans.editor.ActionFactory.FindPreviousAction +org.netbeans.editor.ActionFactory.FindSelectionAction +org.netbeans.editor.ActionFactory.ToggleHighlightSearchAction +org.netbeans.editor.ActionFactory.WordMatchAction +org.netbeans.editor.ActionFactory.WordMatchAction +org.netbeans.editor.ActionFactory.ReindentLineAction +org.netbeans.editor.ActionFactory.ShiftLineAction +org.netbeans.editor.ActionFactory.ShiftLineAction +org.netbeans.editor.ActionFactory.AdjustWindowAction +org.netbeans.editor.ActionFactory.AdjustWindowAction +org.netbeans.editor.ActionFactory.AdjustWindowAction +org.netbeans.editor.ActionFactory.AdjustCaretAction +org.netbeans.editor.ActionFactory.AdjustCaretAction +org.netbeans.editor.ActionFactory.AdjustCaretAction +org.netbeans.editor.ActionFactory.FormatAction +org.netbeans.editor.ActionFactory.FirstNonWhiteAction +org.netbeans.editor.ActionFactory.FirstNonWhiteAction +org.netbeans.editor.ActionFactory.LastNonWhiteAction +org.netbeans.editor.ActionFactory.LastNonWhiteAction +org.netbeans.editor.ActionFactory.SelectIdentifierAction +org.netbeans.editor.ActionFactory.SelectNextParameterAction +org.netbeans.editor.ActionFactory.ScrollUpAction +org.netbeans.editor.ActionFactory.ScrollDownAction +org.netbeans.editor.ActionFactory.InsertDateTimeAction +org.netbeans.editor.ActionFactory.GenerateGutterPopupAction +org.netbeans.editor.ActionFactory.ToggleLineNumbersAction +org.netbeans.editor.ActionFactory.AnnotationsCyclingAction +org.netbeans.editor.ActionFactory.CollapseFold +org.netbeans.editor.ActionFactory.ExpandFold +org.netbeans.editor.ActionFactory.CollapseAllFolds +org.netbeans.editor.ActionFactory.ExpandAllFolds +org.netbeans.editor.ActionFactory.DumpViewHierarchyAction +org.netbeans.editor.ActionFactory.StartNewLine +org.netbeans.editor.ActionFactory.CutToLineBeginOrEndAction +org.netbeans.editor.ActionFactory.CutToLineBeginOrEndAction + +org.netbeans.editor.ext.ExtKit.BuildPopupMenuAction +org.netbeans.editor.ext.ExtKit.ShowPopupMenuAction +org.netbeans.editor.ext.ExtKit.BuildToolTipAction +org.netbeans.editor.ext.ExtKit.ToggleCaseIdentifierBeginAction +org.netbeans.editor.ext.ExtKit.ExtDefaultKeyTypedAction +org.netbeans.editor.ext.ExtKit.CompletionShowAction +org.netbeans.editor.ext.ExtKit.AllCompletionShowAction +org.netbeans.editor.ext.ExtKit.DocumentationShowAction +org.netbeans.editor.ext.ExtKit.CompletionTooltipShowAction + +org.netbeans.modules.editor.NbEditorKit.NbBuildPopupMenuAction +org.netbeans.modules.editor.NbEditorKit.NbBuildToolTipAction +org.netbeans.modules.editor.NbEditorKit.NbToggleLineNumbersAction +org.netbeans.modules.editor.NbEditorKit.ToggleToolbarAction +org.netbeans.modules.editor.NbEditorKit.NbGenerateGoToPopupAction +org.netbeans.modules.editor.NbEditorKit.NbGenerateCodeAction +org.netbeans.modules.editor.NbEditorKit.NavigationHistoryLastEditAction + +org.netbeans.modules.editor.java.JavaKit.AbbrevDebugLineAction +org.netbeans.modules.editor.java.JavaKit.JavaGenerateGoToPopupAction +org.netbeans.modules.editor.java.JavaKit.ExpandAllJavadocFolds +org.netbeans.modules.editor.java.JavaKit.CollapseAllJavadocFolds +org.netbeans.modules.editor.java.JavaKit.ExpandAllCodeBlockFolds +org.netbeans.modules.editor.java.JavaKit.CollapseAllCodeBlockFolds +org.netbeans.modules.editor.java.JavaKit.JavaGoToSourceAction +org.netbeans.modules.editor.java.JavaKit.JavaGotoHelpAction +org.netbeans.modules.editor.java.JavaKit.JavaFixImports + + # Mobility org.netbeans.modules.mobility.project.security.KeyStoreRepository org.netbeans.modules.mobility.project.security.KeyStoreRepositoryWarmUp diff --git a/java.editor/src/org/netbeans/modules/editor/java/Bundle.properties b/java.editor/src/org/netbeans/modules/editor/java/Bundle.properties --- a/java.editor/src/org/netbeans/modules/editor/java/Bundle.properties +++ b/java.editor/src/org/netbeans/modules/editor/java/Bundle.properties @@ -48,6 +48,7 @@ array_length_field_javadoc=Length of array. class_constant_javadoc=java.lang.Class constant. generate-goto-popup=Go To +goto-source=Go to Source goto_source_open_source_not_formatted=Go to Source goto_source_package_not_found=Package {0} not found. goto_source_source_not_found=Source file for {0} not found. diff --git a/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java b/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java --- a/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java +++ b/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java @@ -51,6 +51,7 @@ import javax.swing.JMenuItem; import javax.swing.KeyStroke; import javax.swing.text.*; +import org.netbeans.api.editor.EditorActionRegistration; import org.netbeans.api.editor.fold.FoldHierarchy; import org.netbeans.api.editor.fold.FoldUtilities; import org.netbeans.api.editor.mimelookup.MimeLookup; @@ -212,54 +213,56 @@ /* package */ static final String deleteNextCamelCasePosition = "delete-next-camel-case-position"; //NOI18N - public static Action create(FileObject file) { - initialize(); +// public static Action create(FileObject file) { +// initialize(); +// +// return name2Action.get(file.getName()); +// } +// +// private static Map name2Action; +// +// private static synchronized void initialize() { +// if (name2Action != null) { +// return ; +// } +// +// name2Action = new HashMap(); +// +// for (BaseAction a : createActionsForLayer()) { +// name2Action.put((String) a.getValue(Action.NAME), a); +// +//// System.err.println(""); +//// System.err.println(" "); +//// System.err.println(""); +// } +// } - return name2Action.get(file.getName()); - } - private static Map name2Action; + @Override + protected Action[] createActions() { + Action[] superActions = super.createActions(); - private static synchronized void initialize() { - if (name2Action != null) { - return ; - } - - name2Action = new HashMap(); - - for (BaseAction a : createActionsForLayer()) { - name2Action.put((String) a.getValue(Action.NAME), a); - -// System.err.println(""); -// System.err.println(" "); -// System.err.println(""); - } - } - - private static BaseAction[] createActionsForLayer() { - Action[] superActions = new NbEditorKit().getActions(); - - return new BaseAction[] { + Action[] actions = new BaseAction[] { new JavaDefaultKeyTypedAction(), new PrefixMakerAction(makeGetterAction, "get", getSetIsPrefixes), // NOI18N new PrefixMakerAction(makeSetterAction, "set", getSetIsPrefixes), // NOI18N new PrefixMakerAction(makeIsAction, "is", getSetIsPrefixes), // NOI18N - new AbbrevDebugLineAction(), +// annotation-registration new AbbrevDebugLineAction(), new ToggleCommentAction("//"), // NOI18N - new JavaGenerateGoToPopupAction(), +// annotation-registration new JavaGenerateGoToPopupAction(), new JavaInsertBreakAction(), new JavaDeleteCharAction(deletePrevCharAction, false), new JavaDeleteCharAction(deleteNextCharAction, true), - new ExpandAllJavadocFolds(), - new CollapseAllJavadocFolds(), - new ExpandAllCodeBlockFolds(), - new CollapseAllCodeBlockFolds(), - new JavaGenerateFoldPopupAction(), +// annotation-registration new ExpandAllJavadocFolds(), +// annotation-registration new CollapseAllJavadocFolds(), +// annotation-registration new ExpandAllCodeBlockFolds(), +// annotation-registration new CollapseAllCodeBlockFolds(), + new JavaGenerateFoldPopupAction(), // NO_KEYBINDING in super new JavaGoToDeclarationAction(), - new JavaGoToSourceAction(), - new JavaGotoHelpAction(), +// annotation-registration new JavaGoToSourceAction(), +// annotation-registration new JavaGotoHelpAction(), new InstantRenameAction(), - new JavaFixImports(), +// annotation-registration new JavaFixImports(), new InsertSemicolonAction(true), new InsertSemicolonAction(false), new SelectCodeElementAction(selectNextElementAction, true), @@ -278,6 +281,8 @@ new GoToMarkOccurrencesAction(false), new GoToMarkOccurrencesAction(true), }; + + return TextAction.augmentList(superActions, actions); } private static Action findAction(Action [] actions, String name) { @@ -354,7 +359,7 @@ } } - + @EditorActionRegistration(name = generateGoToPopupAction, mimeType = JAVA_MIME_TYPE) public static class JavaGenerateGoToPopupAction extends NbGenerateGoToPopupAction { public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -449,11 +454,14 @@ } - + @EditorActionRegistration( + name = abbrevDebugLineAction, + mimeType = JAVA_MIME_TYPE, + shortDescription = "" + ) public static class AbbrevDebugLineAction extends BaseAction { public AbbrevDebugLineAction() { - super(abbrevDebugLineAction); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -670,11 +678,14 @@ } } - public static class ExpandAllJavadocFolds extends BaseAction{ + @EditorActionRegistration( + name = expandAllJavadocFolds, + mimeType = JAVA_MIME_TYPE, + popupText = "#popup-expand-all-javadoc-folds" + ) + public static class ExpandAllJavadocFolds extends BaseAction { + public ExpandAllJavadocFolds(){ - super(expandAllJavadocFolds); - putValue(SHORT_DESCRIPTION, NbBundle.getBundle(JavaKit.class).getString("expand-all-javadoc-folds")); - putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(JavaKit.class).getString("popup-expand-all-javadoc-folds")); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -684,11 +695,14 @@ } } + @EditorActionRegistration( + name = collapseAllJavadocFolds, + mimeType = JAVA_MIME_TYPE, + shortDescription = "#popup-collapse-all-javadoc-folds" + ) public static class CollapseAllJavadocFolds extends BaseAction{ + public CollapseAllJavadocFolds(){ - super(collapseAllJavadocFolds); - putValue(SHORT_DESCRIPTION, NbBundle.getBundle(JavaKit.class).getString("collapse-all-javadoc-folds")); - putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(JavaKit.class).getString("popup-collapse-all-javadoc-folds")); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -698,11 +712,15 @@ } } + @EditorActionRegistration( + name = expandAllCodeBlockFolds, + mimeType = JAVA_MIME_TYPE, + popupText = "#popup-expand-all-code-block-folds" + + ) public static class ExpandAllCodeBlockFolds extends BaseAction{ + public ExpandAllCodeBlockFolds(){ - super(expandAllCodeBlockFolds); - putValue(SHORT_DESCRIPTION, NbBundle.getBundle(JavaKit.class).getString("expand-all-code-block-folds")); - putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(JavaKit.class).getString("popup-expand-all-code-block-folds")); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -715,11 +733,14 @@ } } - public static class CollapseAllCodeBlockFolds extends BaseAction{ + @EditorActionRegistration( + name = collapseAllCodeBlockFolds, + mimeType = JAVA_MIME_TYPE, + shortDescription = "#popup-collapse-all-code-block-folds" + ) + public static class CollapseAllCodeBlockFolds extends BaseAction { + public CollapseAllCodeBlockFolds(){ - super(collapseAllCodeBlockFolds); - putValue(SHORT_DESCRIPTION, NbBundle.getBundle(JavaKit.class).getString("collapse-all-code-block-folds")); - putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(JavaKit.class).getString("popup-collapse-all-code-block-folds")); } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -732,7 +753,9 @@ } } - public static class JavaGenerateFoldPopupAction extends GenerateFoldPopupAction{ +// extends from NbEditorKit +// @EditorActionRegistration(name = generateFoldPopupAction, mimeType = JAVA_MIME_TYPE) + public static class JavaGenerateFoldPopupAction extends GenerateFoldPopupAction { protected void addAdditionalItems(JTextComponent target, JMenu menu){ addAction(target, menu, collapseAllJavadocFolds); @@ -744,7 +767,13 @@ } - private static class JavaGoToDeclarationAction extends GotoDeclarationAction { +// extends from NbEditorKit +// @EditorActionRegistration(name = gotoDeclarationAction, mimeType = JAVA_MIME_TYPE) + public static class JavaGoToDeclarationAction extends GotoDeclarationAction { + + public JavaGoToDeclarationAction() { + } + public @Override boolean gotoDeclaration(JTextComponent target) { if (!(target.getDocument() instanceof BaseDocument)) // Fixed #113062 return false; @@ -753,16 +782,18 @@ } } - private static class JavaGoToSourceAction extends BaseAction { + @EditorActionRegistration( + name = gotoSourceAction, + mimeType = JAVA_MIME_TYPE + ) + public static class JavaGoToSourceAction extends BaseAction { static final long serialVersionUID =-6440495023918097760L; public JavaGoToSourceAction() { - super(gotoSourceAction, - ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET | SAVE_POSITION ); - putValue(TRIMMED_TEXT, LocaleSupport.getString("goto-source-trimmed")); //NOI18N } public void actionPerformed(ActionEvent evt, JTextComponent target) { @@ -780,12 +811,14 @@ } } - private static class JavaFixImports extends BaseAction { + @EditorActionRegistration( + name = fixImportsAction, + mimeType = JAVA_MIME_TYPE + ) + public static class JavaFixImports extends BaseAction { public JavaFixImports() { - super(fixImportsAction, - ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET - ); + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET); putValue(TRIMMED_TEXT, NbBundle.getBundle(JavaKit.class).getString("fix-imports-trimmed")); putValue(SHORT_DESCRIPTION, NbBundle.getBundle(JavaKit.class).getString("desc-fix-imports")); // NOI18N putValue(POPUP_MENU_TEXT, NbBundle.getBundle(JavaKit.class).getString("popup-fix-imports")); // NOI18N @@ -827,14 +860,16 @@ } } // End of JavaFixImports action - private static class JavaGotoHelpAction extends BaseAction { + @EditorActionRegistration( + name = gotoHelpAction, + mimeType = JAVA_MIME_TYPE, + shortDescription = "#java-desc-goto-help" + ) + public static class JavaGotoHelpAction extends BaseAction { public JavaGotoHelpAction() { - super(gotoHelpAction, ABBREV_RESET | MAGIC_POSITION_RESET - | UNDO_MERGE_RESET |SAVE_POSITION); + super(ABBREV_RESET | MAGIC_POSITION_RESET | UNDO_MERGE_RESET |SAVE_POSITION); putValue ("helpID", JavaGotoHelpAction.class.getName ()); // NOI18N - // fix of #25090; [PENDING] there should be more systematic solution for this problem - putValue(SHORT_DESCRIPTION, NbBundle.getBundle(JavaKit.class).getString("java-desc-goto-help")); } public void actionPerformed(ActionEvent evt, JTextComponent target) { diff --git a/java.editor/src/org/netbeans/modules/java/editor/resources/layer.xml b/java.editor/src/org/netbeans/modules/java/editor/resources/layer.xml --- a/java.editor/src/org/netbeans/modules/java/editor/resources/layer.xml +++ b/java.editor/src/org/netbeans/modules/java/editor/resources/layer.xml @@ -182,7 +182,7 @@ - + diff --git a/openide.awt/apichanges.xml b/openide.awt/apichanges.xml --- a/openide.awt/apichanges.xml +++ b/openide.awt/apichanges.xml @@ -47,6 +47,23 @@ AWT API + + + AlwaysEnabledAction extra properties and Action.NAME synchronization + + + + + + Actions.alwaysEnabled() now checks whether Action.NAME property value + of the delegate action (if defined) matches to the one in the declared + for the action in the xml-layer. + The AlwaysEnabledAction.getValue() now resolves all the keys + in Acxtion.getValue() against the defined attributes in the xml-layer. + + + + Support for showing of notification-like messages in the main status line. diff --git a/openide.awt/nbproject/project.properties b/openide.awt/nbproject/project.properties --- a/openide.awt/nbproject/project.properties +++ b/openide.awt/nbproject/project.properties @@ -44,4 +44,4 @@ javadoc.arch=${basedir}/arch.xml javadoc.apichanges=${basedir}/apichanges.xml -spec.version.base=7.6.0 +spec.version.base=7.7.0 diff --git a/openide.awt/src/org/openide/awt/AlwaysEnabledAction.java b/openide.awt/src/org/openide/awt/AlwaysEnabledAction.java --- a/openide.awt/src/org/openide/awt/AlwaysEnabledAction.java +++ b/openide.awt/src/org/openide/awt/AlwaysEnabledAction.java @@ -9,6 +9,8 @@ import java.beans.PropertyChangeListener; import java.net.URL; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; @@ -24,6 +26,10 @@ */ final class AlwaysEnabledAction extends AbstractAction implements PropertyChangeListener, ContextAwareAction { + + // -J-Dorg.openide.awt.AlwaysEnabledAction.level=FINE + private static final Logger LOG = Logger.getLogger(AlwaysEnabledAction.class.getName()); + private final Map map; private ActionListener delegate; private final Lookup context; @@ -61,15 +67,36 @@ } delegate = bindToContext((ActionListener)listener, context); if (delegate instanceof Action) { - ((Action)delegate).addPropertyChangeListener(this); + Action actionDelegate = (Action) delegate; + actionDelegate.addPropertyChangeListener(this); + // Ensure display names and other properties are in sync or propagate them + syncActionDelegateProperty(Action.NAME, actionDelegate); } } return delegate; } + private void syncActionDelegateProperty(String propertyName, Action actionDelegate) { + Object value = extractCommonAttribute(map, this, propertyName); + Object delegateValue = actionDelegate.getValue(propertyName); + if (value != null) { + if (delegateValue == null) { + actionDelegate.putValue(propertyName, value); + } else { + if (!delegateValue.equals(value)) { // Values differ + LOG.warning("Value of property \"" + propertyName + + "\" of AlwaysEnabledAction is \"" + + value + "\" but delegate has \"" + delegateValue + + "\"\ndelegate:" + delegate + '\n'); + } + } + } // else either both values are null or + // this has null and delegate has non-null which is probably fine (declarer does not care) + } + @Override public boolean isEnabled() { - assert EventQueue.isDispatchThread(); +// assert EventQueue.isDispatchThread(); if (delegate instanceof Action) { return ((Action)delegate).isEnabled(); } @@ -143,6 +170,10 @@ return arr.length > 0 ? arr[0] : null; } } + // Delegate query to other properties to "fo" ignoring special properties + if (!"delegate".equals(name) && !"instanceCreate".equals(name)) { + return fo.get(name); + } return null; } diff --git a/openide.awt/test/unit/src/org/openide/awt/ActionsTest.java b/openide.awt/test/unit/src/org/openide/awt/ActionsTest.java --- a/openide.awt/test/unit/src/org/openide/awt/ActionsTest.java +++ b/openide.awt/test/unit/src/org/openide/awt/ActionsTest.java @@ -63,6 +63,7 @@ import org.netbeans.junit.NbTestCase; import org.openide.util.HelpCtx; import org.openide.util.Lookup; +import org.openide.util.Utilities; import org.openide.util.actions.SystemAction; /** @@ -345,12 +346,13 @@ assertTrue(button.getToolTipText().equals(TestActionWithTooltip.TOOLTIP)); action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK)); - - assertTrue(button.getToolTipText().indexOf("Ctrl+C") != (-1)); + + String ctrlMod = Utilities.isMac() ? "\u2303" : "Ctrl"; + assertTrue(button.getToolTipText().indexOf(ctrlMod + "+C") != (-1)); action.putValue(Action.SHORT_DESCRIPTION, null); - assertTrue(button.getToolTipText().indexOf("Ctrl+C") != (-1)); + assertTrue(button.getToolTipText().indexOf(ctrlMod + "+C") != (-1)); f.setVisible(false); } @@ -394,7 +396,7 @@ Actions.connect(item, action, true); - assertEquals('A', item.getMnemonic()); + assertEquals(Utilities.isMac() ? 0 : 'A', item.getMnemonic()); assertEquals("Ahoj", item.getText()); } @@ -413,7 +415,7 @@ Actions.connect(item, action, true); - assertEquals('B', item.getMnemonic()); + assertEquals(Utilities.isMac() ? 0 : 'B', item.getMnemonic()); assertEquals("Ble", item.getText()); } @@ -432,7 +434,7 @@ Actions.connect(item, action, true); - assertEquals('M', item.getMnemonic()); + assertEquals(Utilities.isMac() ? 0 : 'M', item.getMnemonic()); assertEquals("Mle", item.getText()); } diff --git a/openide.awt/test/unit/src/org/openide/awt/AlwaysEnabledActionTest.java b/openide.awt/test/unit/src/org/openide/awt/AlwaysEnabledActionTest.java --- a/openide.awt/test/unit/src/org/openide/awt/AlwaysEnabledActionTest.java +++ b/openide.awt/test/unit/src/org/openide/awt/AlwaysEnabledActionTest.java @@ -47,6 +47,7 @@ import java.beans.PropertyChangeListener; import java.net.URL; import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; @@ -287,6 +288,33 @@ assertTrue("Actions expected to be equal", a1.equals(a11)); } + public void testExtraPropertiesAndNamePropagation() throws Exception { + Action a = readAction("testExtraProperties.instance"); + assertNull(MyAction.last); + assertNotNull("Action created", a); + a.actionPerformed(new ActionEvent(this, 0, "")); + assertNotNull(MyAction.last); + assertPropertyPropagated(Action.NAME, "Name1", a, MyAction.last); + assertEquals("Short Desc1", a.getValue(Action.SHORT_DESCRIPTION)); + assertEquals("Menu Text1", a.getValue("menuText")); + assertEquals("Popup Text1", a.getValue("popupText")); + } + + public void testDisplayNameDiffer() throws Exception { + Action a = readAction("testDisplayNameDiffer.instance"); + assertNull(MyAction.last); + assertNotNull("Action created", a); + a.actionPerformed(new ActionEvent(this, 0, "")); + // Check LOG for warning + assertEquals("MyNamedAction", a.getValue(Action.NAME)); // Queries the delegate + assertEquals("MyNamedAction", MyAction.last.getValue(Action.NAME)); + } + + private static void assertPropertyPropagated(String propertyName, Object value, Action a, Action delegate) { + assertEquals("Action's property \"" + propertyName + "\"", value, a.getValue(propertyName)); + assertEquals("Delegate's property \"" + propertyName + "\"", value, delegate.getValue(propertyName)); + } + private static int myListenerCounter; private static int myListenerCalled; private static ActionListener myListener() { @@ -297,6 +325,11 @@ myListenerCounter++; return new MyAction(); } + private static Action myNamedAction() { + MyAction a = new MyAction(); + a.putValue(Action.NAME, "MyNamedAction"); + return a; + } private static ActionListener myContextAction() { myListenerCounter++; return new MyContextAction(); diff --git a/openide.awt/test/unit/src/org/openide/awt/MnemonicsTest.java b/openide.awt/test/unit/src/org/openide/awt/MnemonicsTest.java --- a/openide.awt/test/unit/src/org/openide/awt/MnemonicsTest.java +++ b/openide.awt/test/unit/src/org/openide/awt/MnemonicsTest.java @@ -79,8 +79,10 @@ assertEquals("R&D department", b.getText()); assertEquals(0, b.getMnemonic()); assertEquals(-1, b.getDisplayedMnemonicIndex()); + String underStart = Utilities.isMac() ? "" : ""; + String underEnd = Utilities.isMac() ? "" : ""; Mnemonics.setLocalizedText(b, "R&D departmen&t"); - assertEquals("R&D department", b.getText()); + assertEquals("R&D departmen" + underStart + "t" + underEnd, b.getText()); if (Utilities.getOperatingSystem() == Utilities.OS_MAC) { assertEquals(0, b.getMnemonic()); assertEquals(-1, b.getDisplayedMnemonicIndex()); @@ -89,7 +91,7 @@ } Mnemonics.setLocalizedText(b, "Smith & &Wesson"); - assertEquals("Smith & Wesson", b.getText()); + assertEquals("Smith & " + underStart + "W" + underEnd + "esson", b.getText()); if (Utilities.getOperatingSystem() == Utilities.OS_MAC) { assertEquals(0, b.getMnemonic()); assertEquals(-1, b.getDisplayedMnemonicIndex()); @@ -97,7 +99,7 @@ assertEquals(KeyEvent.VK_W, b.getMnemonic()); } Mnemonics.setLocalizedText(b, "&Advanced Mode (experimental)"); - assertEquals("Advanced Mode (experimental)", b.getText()); + assertEquals("" + underStart + "A" + underEnd + "dvanced Mode (experimental)", b.getText()); if (Utilities.getOperatingSystem() == Utilities.OS_MAC) { assertEquals(0, b.getMnemonic()); assertEquals(-1, b.getDisplayedMnemonicIndex()); diff --git a/openide.awt/test/unit/src/org/openide/awt/test-layer.xml b/openide.awt/test/unit/src/org/openide/awt/test-layer.xml --- a/openide.awt/test/unit/src/org/openide/awt/test-layer.xml +++ b/openide.awt/test/unit/src/org/openide/awt/test-layer.xml @@ -79,6 +79,19 @@ + + + + + + + + + + + + +