KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > editor > bookmarks > actions > ToggleBookmarkAction


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.lib.editor.bookmarks.actions;
21
22 import java.awt.Component JavaDoc;
23 import java.awt.event.ActionEvent JavaDoc;
24 import java.beans.PropertyChangeEvent JavaDoc;
25 import java.beans.PropertyChangeListener JavaDoc;
26 import javax.swing.AbstractAction JavaDoc;
27 import javax.swing.AbstractButton JavaDoc;
28 import javax.swing.Action JavaDoc;
29 import javax.swing.ButtonModel JavaDoc;
30 import javax.swing.ImageIcon JavaDoc;
31 import javax.swing.JButton JavaDoc;
32 import javax.swing.JEditorPane JavaDoc;
33 import javax.swing.JToggleButton JavaDoc;
34 import javax.swing.event.ChangeEvent JavaDoc;
35 import javax.swing.event.ChangeListener JavaDoc;
36 import javax.swing.text.BadLocationException JavaDoc;
37 import javax.swing.text.Caret JavaDoc;
38 import javax.swing.text.Document JavaDoc;
39 import javax.swing.text.JTextComponent JavaDoc;
40 import org.netbeans.editor.BaseDocument;
41 import org.netbeans.lib.editor.bookmarks.BookmarksApiPackageAccessor;
42 import org.netbeans.lib.editor.bookmarks.api.Bookmark;
43 import org.netbeans.lib.editor.bookmarks.api.BookmarkList;
44 import org.openide.cookies.EditorCookie;
45 import org.openide.util.ContextAwareAction;
46 import org.openide.util.Lookup;
47 import org.openide.util.NbBundle;
48 import org.openide.util.Utilities;
49 import org.openide.util.WeakListeners;
50 import org.openide.util.actions.Presenter;
51
52
53 /**
54  * Toggles a bookmark in a line in an opened document.
55  *
56  * @author Vita Stejskal
57  */

58 public final class ToggleBookmarkAction extends AbstractAction JavaDoc implements ContextAwareAction, Presenter.Toolbar {
59
60     private static final String JavaDoc ACTION_NAME = "bookmark-toggle"; // NOI18N
61
private static final String JavaDoc ACTION_ICON = "org/netbeans/modules/editor/bookmarks/resources/toggle_bookmark.png"; // NOI18N
62

63     private final JTextComponent JavaDoc component;
64     
65     public ToggleBookmarkAction() {
66         this(null);
67     }
68     
69     public ToggleBookmarkAction(JTextComponent JavaDoc component) {
70         super(
71             NbBundle.getMessage(ToggleBookmarkAction.class, ACTION_NAME),
72             new ImageIcon JavaDoc(Utilities.loadImage(ACTION_ICON))
73         );
74         putValue(SHORT_DESCRIPTION, getValue(NAME));
75         putValue("noIconInMenu", Boolean.TRUE); // NOI18N
76

77         this.component = component;
78     }
79
80     public Action JavaDoc createContextAwareInstance(Lookup actionContext) {
81         JTextComponent JavaDoc jtc = findComponent(actionContext);
82         return new ToggleBookmarkAction(jtc);
83     }
84
85     public void actionPerformed(ActionEvent JavaDoc arg0) {
86         if (component != null) {
87             // cloned action with context
88
actionPerformed(component);
89         } else {
90             // global action, will have to find the current component
91
JTextComponent JavaDoc jtc = findComponent(Utilities.actionsGlobalContext());
92             if (jtc != null) {
93                 actionPerformed(jtc);
94             }
95         }
96     }
97
98     public Component JavaDoc getToolbarPresenter() {
99         AbstractButton JavaDoc b;
100         
101         if (component != null) {
102             b = new MyGaGaButton();
103             b.setModel(new BookmarkButtonModel(component));
104         } else {
105             b = new JButton JavaDoc();
106         }
107         
108         b.putClientProperty("hideActionText", Boolean.TRUE); //NOI18N
109
b.setAction(this);
110         
111         return b;
112     }
113
114     private static JTextComponent JavaDoc findComponent(Lookup lookup) {
115         EditorCookie ec = (EditorCookie) lookup.lookup(EditorCookie.class);
116         if (ec != null) {
117             JEditorPane JavaDoc panes[] = ec.getOpenedPanes();
118             if (panes != null && panes.length > 0) {
119                 return panes[0];
120             }
121         }
122         return null;
123     }
124     
125     private static void actionPerformed(JTextComponent JavaDoc target) {
126         if (target != null) {
127             if (org.netbeans.editor.Utilities.getEditorUI(target).isGlyphGutterVisible()) {
128                 Caret JavaDoc caret = target.getCaret();
129                 BookmarkList bookmarkList = BookmarkList.get(target.getDocument());
130                 bookmarkList.toggleLineBookmark(caret.getDot());
131
132             } else { // Glyph gutter not visible -> just beep
133
target.getToolkit().beep();
134             }
135         }
136     }
137     
138     private static final class BookmarkButtonModel extends JToggleButton.ToggleButtonModel JavaDoc implements PropertyChangeListener JavaDoc, ChangeListener JavaDoc {
139         
140         private final JTextComponent JavaDoc component;
141         private Caret JavaDoc caret;
142         private BookmarkList bookmarks;
143         private int lastCurrentLineStartOffset = -1;
144         
145         private PropertyChangeListener JavaDoc bookmarksListener = null;
146         private ChangeListener JavaDoc caretListener = null;
147         
148         public BookmarkButtonModel(JTextComponent JavaDoc component) {
149             this.component = component;
150             this.component.addPropertyChangeListener(WeakListeners.propertyChange(this, this.component));
151             rebuild();
152         }
153
154         public void propertyChange(PropertyChangeEvent JavaDoc evt) {
155             if (evt.getPropertyName() == null ||
156                 "document".equals(evt.getPropertyName()) || //NOI18N
157
"caret".equals(evt.getPropertyName()) //NOI18N
158
) {
159                 rebuild();
160             } else if ("bookmarks".equals(evt.getPropertyName())) { //NOI18N
161
lastCurrentLineStartOffset = -1;
162                 updateState();
163             }
164         }
165
166         public void stateChanged(ChangeEvent JavaDoc evt) {
167             updateState();
168         }
169
170         private static boolean isBookmarkOnTheLine(BookmarkList bookmarks, int lineStartOffset) {
171             Bookmark bm = bookmarks.getNextBookmark(lineStartOffset - 1, false);
172 // System.out.println("offset: " + lineStartOffset + " -> " + bm + (bm == null ? "" : "; bm.getOffset() = " + bm.getOffset()));
173
return bm == null ? false : lineStartOffset == bm.getOffset();
174         }
175         
176         private void rebuild() {
177             // Hookup the bookmark list
178
BookmarkList newBookmarks = BookmarkList.get(component.getDocument());
179             if (newBookmarks != bookmarks) {
180                 if (bookmarksListener != null) {
181                     BookmarksApiPackageAccessor.get().removeBookmarkListPcl(bookmarks, bookmarksListener);
182                     bookmarksListener = null;
183                 }
184
185                 bookmarks = newBookmarks;
186
187                 if (bookmarks != null) {
188                     bookmarksListener = WeakListeners.propertyChange(this, bookmarks);
189                     BookmarksApiPackageAccessor.get().addBookmarkListPcl(bookmarks, bookmarksListener);
190                 }
191             }
192             
193             // Hookup the caret
194
Caret JavaDoc newCaret = component.getCaret();
195             if (newCaret != caret) {
196                 if (caretListener != null) {
197                     caret.removeChangeListener(caretListener);
198                     caretListener = null;
199                 }
200
201                 caret = newCaret;
202
203                 if (caret != null) {
204                     caretListener = WeakListeners.change(this, caret);
205                     caret.addChangeListener(caretListener);
206                 }
207             }
208             
209             lastCurrentLineStartOffset = -1;
210             updateState();
211         }
212         
213         private void updateState() {
214             Document JavaDoc doc = component.getDocument();
215             if (caret != null && bookmarks != null && doc instanceof BaseDocument) {
216                 try {
217                     int currentLineStartOffset = org.netbeans.editor.Utilities.getRowStart((BaseDocument) doc, caret.getDot());
218                     if (currentLineStartOffset != lastCurrentLineStartOffset) {
219                         lastCurrentLineStartOffset = currentLineStartOffset;
220                         boolean selected = isBookmarkOnTheLine(bookmarks, currentLineStartOffset);
221                         
222 // System.out.println("updateState: offset=" + currentLineStartOffset + ", hasBookmark=" + selected);
223

224                         setSelected(selected);
225                     }
226                 } catch (BadLocationException JavaDoc e) {
227                     // ignore
228
lastCurrentLineStartOffset = -1;
229                 }
230             }
231         }
232     } // End of BookmarkButtonModel class
233

234     private static final class MyGaGaButton extends JToggleButton JavaDoc implements ChangeListener JavaDoc {
235
236         public MyGaGaButton() {
237
238         }
239
240         public void setModel(ButtonModel JavaDoc model) {
241             ButtonModel JavaDoc oldModel = getModel();
242             if (oldModel != null) {
243                 oldModel.removeChangeListener(this);
244             }
245
246             super.setModel(model);
247
248             ButtonModel JavaDoc newModel = getModel();
249             if (newModel != null) {
250                 newModel.addChangeListener(this);
251             }
252
253             stateChanged(null);
254         }
255
256         public void stateChanged(ChangeEvent JavaDoc evt) {
257             boolean selected = isSelected();
258             super.setContentAreaFilled(selected);
259             super.setBorderPainted(selected);
260         }
261
262         public void setBorderPainted(boolean arg0) {
263             if (!isSelected()) {
264                 super.setBorderPainted(arg0);
265             }
266         }
267
268         public void setContentAreaFilled(boolean arg0) {
269             if (!isSelected()) {
270                 super.setContentAreaFilled(arg0);
271             }
272         }
273     } // End of MyGaGaButton class
274

275 }
276
277
Popular Tags