KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > editor > BaseKit


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 Picrosystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.editor;
21
22 import java.awt.Point JavaDoc;
23 import java.awt.Rectangle JavaDoc;
24 import java.awt.event.ActionEvent JavaDoc;
25 import java.io.Reader JavaDoc;
26 import java.io.Writer JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Collections JavaDoc;
34 import javax.swing.Action JavaDoc;
35 import javax.swing.JEditorPane JavaDoc;
36 import javax.swing.SwingConstants JavaDoc;
37 import javax.swing.SwingUtilities JavaDoc;
38 import javax.swing.text.Document JavaDoc;
39 import javax.swing.text.DefaultEditorKit JavaDoc;
40 import javax.swing.text.BadLocationException JavaDoc;
41 import javax.swing.text.Element JavaDoc;
42 import javax.swing.text.ViewFactory JavaDoc;
43 import javax.swing.text.Caret JavaDoc;
44 import javax.swing.text.JTextComponent JavaDoc;
45 import java.io.CharArrayWriter JavaDoc;
46 import java.lang.reflect.Method JavaDoc;
47 import java.util.Vector JavaDoc;
48 import java.util.logging.Level JavaDoc;
49 import java.util.logging.Logger JavaDoc;
50 import javax.swing.text.EditorKit JavaDoc;
51 import javax.swing.text.Position JavaDoc;
52 import org.netbeans.api.editor.mimelookup.MimeLookup;
53 import org.netbeans.api.editor.mimelookup.MimePath;
54 import org.netbeans.lib.editor.util.swing.DocumentUtilities;
55 import org.openide.awt.StatusDisplayer;
56 import org.openide.util.Lookup;
57 import org.openide.util.NbBundle;
58
59 /**
60 * Editor kit implementation for base document
61 *
62 * @author Miloslav Metelka
63 * @version 1.00
64 */

65
66 public class BaseKit extends DefaultEditorKit JavaDoc {
67
68     private static final Logger JavaDoc LOG = Logger.getLogger(BaseKit.class.getName());
69     
70     /** split the current line at cursor position */
71     public static final String JavaDoc splitLineAction = "split-line"; // NOI18N
72

73     /** Cycle through annotations on the current line */
74     public static final String JavaDoc annotationsCyclingAction = "annotations-cycling"; // NOI18N
75

76     /** Collapse a fold. Depends on the current caret position. */
77     public static final String JavaDoc collapseFoldAction = "collapse-fold"; //NOI18N
78

79     /** Expand a fold. Depends on the current caret position. */
80     public static final String JavaDoc expandFoldAction = "expand-fold"; //NOI18N
81

82     /** Collapse all existing folds in the document. */
83     public static final String JavaDoc collapseAllFoldsAction = "collapse-all-folds"; //NOI18N
84

85     /** Expand all existing folds in the document. */
86     public static final String JavaDoc expandAllFoldsAction = "expand-all-folds"; //NOI18N
87

88     /** Move one page up and make or extend selection */
89     public static final String JavaDoc selectionPageUpAction = "selection-page-up"; // NOI18N
90

91     /** Move one page down and make or extend selection */
92     public static final String JavaDoc selectionPageDownAction = "selection-page-down"; // NOI18N
93

94     /** Remove indentation */
95     public static final String JavaDoc removeTabAction = "remove-tab"; // NOI18N
96

97     /** Remove selected block or do nothing - useful for popup menu */
98     public static final String JavaDoc removeSelectionAction = "remove-selection"; // NOI18N
99

100     /** Expand the abbreviation */
101     public static final String JavaDoc abbrevExpandAction = "abbrev-expand"; // NOI18N
102

103     /** Reset the abbreviation accounting string */
104     public static final String JavaDoc abbrevResetAction = "abbrev-reset"; // NOI18N
105

106     /** Remove the word */
107     //public static final String removeWordAction = "remove-word"; #47709
108

109     /** Remove characters to the begining of the word or
110      * the previous word if caret is not directly at word */

111     public static final String JavaDoc removePreviousWordAction = "remove-word-previous"; // NOI18N
112

113     /** Remove characters to the end of the word or
114      * the next word if caret is not directly at word */

115     public static final String JavaDoc removeNextWordAction = "remove-word-next"; // NOI18N
116

117     /** Remove to the begining of the line */
118     public static final String JavaDoc removeLineBeginAction = "remove-line-begin"; // NOI18N
119

120     /** Remove line */
121     public static final String JavaDoc removeLineAction = "remove-line"; // NOI18N
122

123     /** Toggle the typing mode to overwrite mode or back to insert mode */
124     public static final String JavaDoc toggleTypingModeAction = "toggle-typing-mode"; // NOI18N
125

126     /** Change the selected text or current character to uppercase */
127     public static final String JavaDoc toUpperCaseAction = "to-upper-case"; // NOI18N
128

129     /** Change the selected text or current character to lowercase */
130     public static final String JavaDoc toLowerCaseAction = "to-lower-case"; // NOI18N
131

132     /** Switch the case of the selected text or current character */
133     public static final String JavaDoc switchCaseAction = "switch-case"; // NOI18N
134

135     /** Find next occurence action */
136     public static final String JavaDoc findNextAction = "find-next"; // NOI18N
137

138     /** Find previous occurence action */
139     public static final String JavaDoc findPreviousAction = "find-previous"; // NOI18N
140

141     /** Toggle highlight search action */
142     public static final String JavaDoc toggleHighlightSearchAction = "toggle-highlight-search"; // NOI18N
143

144     /** Find current word */
145     public static final String JavaDoc findSelectionAction = "find-selection"; // NOI18N
146

147     /** Undo action */
148     public static final String JavaDoc undoAction = "undo"; // NOI18N
149

150     /** Redo action */
151     public static final String JavaDoc redoAction = "redo"; // NOI18N
152

153     /** Word match next */
154     public static final String JavaDoc wordMatchNextAction = "word-match-next"; // NOI18N
155

156     /** Word match prev */
157     public static final String JavaDoc wordMatchPrevAction = "word-match-prev"; // NOI18N
158

159     /** Reindent Line action */
160     public static final String JavaDoc reindentLineAction = "reindent-line"; // NOI18N
161

162     /** Shift line right action */
163     public static final String JavaDoc shiftLineRightAction = "shift-line-right"; // NOI18N
164

165     /** Shift line left action */
166     public static final String JavaDoc shiftLineLeftAction = "shift-line-left"; // NOI18N
167

168     /** Action that scrolls the window so that caret is at the center of the window */
169     public static final String JavaDoc adjustWindowCenterAction = "adjust-window-center"; // NOI18N
170

171     /** Action that scrolls the window so that caret is at the top of the window */
172     public static final String JavaDoc adjustWindowTopAction = "adjust-window-top"; // NOI18N
173

174     /** Action that scrolls the window so that caret is at the bottom of the window */
175     public static final String JavaDoc adjustWindowBottomAction = "adjust-window-bottom"; // NOI18N
176

177     /** Action that moves the caret so that caret is at the center of the window */
178     public static final String JavaDoc adjustCaretCenterAction = "adjust-caret-center"; // NOI18N
179

180     /** Action that moves the caret so that caret is at the top of the window */
181     public static final String JavaDoc adjustCaretTopAction = "adjust-caret-top"; // NOI18N
182

183     /** Action that moves the caret so that caret is at the bottom of the window */
184     public static final String JavaDoc adjustCaretBottomAction = "adjust-caret-bottom"; // NOI18N
185

186     /** Format part of the document text using Indent */
187     public static final String JavaDoc formatAction = "format"; // NOI18N
188

189     /** First non-white character on the line */
190     public static final String JavaDoc firstNonWhiteAction = "first-non-white"; // NOI18N
191

192     /** Last non-white character on the line */
193     public static final String JavaDoc lastNonWhiteAction = "last-non-white"; // NOI18N
194

195     /** First non-white character on the line */
196     public static final String JavaDoc selectionFirstNonWhiteAction = "selection-first-non-white"; // NOI18N
197

198     /** Last non-white character on the line */
199     public static final String JavaDoc selectionLastNonWhiteAction = "selection-last-non-white"; // NOI18N
200

201     /** Select the nearest identifier around caret */
202     public static final String JavaDoc selectIdentifierAction = "select-identifier"; // NOI18N
203

204     /** Select the next parameter (after the comma) in the given context */
205     public static final String JavaDoc selectNextParameterAction = "select-next-parameter"; // NOI18N
206

207     /** Go to the previous position stored in the jump-list */
208     public static final String JavaDoc jumpListNextAction = "jump-list-next"; // NOI18N
209

210     /** Go to the next position stored in the jump-list */
211     public static final String JavaDoc jumpListPrevAction = "jump-list-prev"; // NOI18N
212

213     /** Go to the last position in the previous component stored in the jump-list */
214     public static final String JavaDoc jumpListNextComponentAction = "jump-list-next-component"; // NOI18N
215

216     /** Go to the next position in the previous component stored in the jump-list */
217     public static final String JavaDoc jumpListPrevComponentAction = "jump-list-prev-component"; // NOI18N
218

219     /** Scroll window one line up */
220     public static final String JavaDoc scrollUpAction = "scroll-up"; // NOI18N
221

222     /** Scroll window one line down */
223     public static final String JavaDoc scrollDownAction = "scroll-down"; // NOI18N
224

225     /** Prefix of all macro-based actions */
226     public static final String JavaDoc macroActionPrefix = "macro-"; // NOI18N
227

228     /** Start recording of macro. Only one macro recording can be active at the time */
229     public static final String JavaDoc startMacroRecordingAction = "start-macro-recording"; //NOI18N
230

231     /** Stop the active recording */
232     public static final String JavaDoc stopMacroRecordingAction = "stop-macro-recording"; //NOI18N
233

234     /** Name of the action moving caret to the first column on the line */
235     public static final String JavaDoc lineFirstColumnAction = "caret-line-first-column"; // NOI18N
236

237     /** Insert the current Date and Time */
238     public static final String JavaDoc insertDateTimeAction = "insert-date-time"; // NOI18N
239

240     /** Name of the action moving caret to the first
241      * column on the line and extending the selection
242      */

243     public static final String JavaDoc selectionLineFirstColumnAction = "selection-line-first-column"; // NOI18N
244

245     /** Name of the action for generating of Glyph Gutter popup menu*/
246     public static final String JavaDoc generateGutterPopupAction = "generate-gutter-popup"; // NOI18N
247

248     /** Toggle visibility of line numbers*/
249     public static final String JavaDoc toggleLineNumbersAction = "toggle-line-numbers"; // NOI18N
250

251     /** Paste and reformat code */
252     public static final String JavaDoc pasteFormatedAction = "paste-formated"; // NOI18N
253

254     /** Starts a new line in code */
255     public static final String JavaDoc startNewLineAction = "start-new-line"; // NOI18N
256

257     /** Cut text from caret position to line begining action. */
258     public static final String JavaDoc cutToLineBeginAction = "cut-to-line-begin"; // NOI18N
259

260     /** Cut text from caret position to line end action. */
261     public static final String JavaDoc cutToLineEndAction = "cut-to-line-end"; // NOI18N
262

263     /** Remove all trailing spaces in the document. */
264     public static final String JavaDoc removeTrailingSpacesAction = "remove-trailing-spaces"; //NOI18N
265

266     public static final String JavaDoc DOC_REPLACE_SELECTION_PROPERTY = "doc-replace-selection-property"; //NOI18N
267

268     private static final int KIT_CNT_PREALLOC = 7;
269
270     static final long serialVersionUID = -8570495408376659348L;
271
272     /** [kit-class, kit-instance] pairs are stored here */
273     private static final Map JavaDoc kits = new HashMap JavaDoc(KIT_CNT_PREALLOC);
274
275     /** [kit-class, keymap] pairs */
276     private static final Map JavaDoc kitKeymaps = new HashMap JavaDoc(KIT_CNT_PREALLOC);
277
278     /** [kit, action[]] pairs */
279     private static final Map JavaDoc kitActions = new HashMap JavaDoc(KIT_CNT_PREALLOC);
280
281     /** [kit, action-map] pairs */
282     private static final Map JavaDoc kitActionMaps = new HashMap JavaDoc(KIT_CNT_PREALLOC);
283     
284     private static CopyAction copyActionDef = new CopyAction();
285     private static CutAction cutActionDef = new CutAction();
286     private static PasteAction pasteActionDef = new PasteAction(false);
287     private static DeleteCharAction deletePrevCharActionDef = new DeleteCharAction(deletePrevCharAction, false);
288     private static DeleteCharAction deleteNextCharActionDef = new DeleteCharAction(deleteNextCharAction, true);
289     private static ActionFactory.RemoveSelectionAction removeSelectionActionDef = new ActionFactory.RemoveSelectionAction();
290
291     private static ActionFactory.UndoAction undoActionDef = new ActionFactory.UndoAction();
292     private static ActionFactory.RedoAction redoActionDef = new ActionFactory.RedoAction();
293     
294     public static final int MAGIC_POSITION_MAX = Integer.MAX_VALUE - 1;
295
296     static SettingsChangeListener settingsListener = new SettingsChangeListener() {
297         public void settingsChange(SettingsChangeEvent evt) {
298             String JavaDoc settingName = (evt != null) ? evt.getSettingName() : null;
299
300             boolean clearActions = (settingName == null
301                     || SettingsNames.CUSTOM_ACTION_LIST.equals(settingName)
302                     || SettingsNames.MACRO_MAP.equals(settingName));
303
304             if (clearActions || SettingsNames.KEY_BINDING_LIST.equals(settingName)) {
305                 kitKeymaps.clear();
306             }
307
308             if (clearActions) {
309                 kitActions.clear();
310                 kitActionMaps.clear();
311             } else { // only refresh action settings
312
Iterator JavaDoc i = kitActions.entrySet().iterator();
313                 while (i.hasNext()) {
314                     Map.Entry JavaDoc me = (Map.Entry JavaDoc)i.next();
315                     updateActionSettings((Action JavaDoc[])me.getValue(), evt, (Class JavaDoc)me.getKey());
316                 }
317             }
318         }
319     };
320
321     static {
322         Settings.addSettingsChangeListener(settingsListener);
323     }
324     
325     private static void updateActionSettings(Action JavaDoc[] actions,
326             SettingsChangeEvent evt, Class JavaDoc kitClass) {
327         for (int i = 0; i < actions.length; i++) {
328             if (actions[i] instanceof BaseAction) {
329                 ((BaseAction)actions[i]).settingsChange(evt, kitClass);
330             }
331         }
332     }
333
334     /**
335      * Gets an editor kit from its implemetation class.
336      *
337      * <p>Please be careful when using this method and make sure that you understand
338      * how it works and what the deference is from using <code>MimeLookup</code>.
339      * This method simply creates an instance of <code>BaseKit</code> from
340      * its implementation class passed in as a parameter. It completely ignores
341      * the registry of editor kits in <code>MimeLookup</code>, which has severe
342      * consequences.
343      *
344      * <div class="nonnormative">
345      * <p>The usuall pattern for using editor kits is to start with a mime type
346      * of a document (ie. file) that you want to edit, then use some registry
347      * for editor kits to look up the kit for your mime type and finally set the
348      * kit in a <code>JTextComponent</code>, let it create a <code>Document</code>
349      * and load it with data. The registry can generally be anything, but in Netbeans
350      * we use <code>MimeLookup</code> (JDK for example uses
351      * <code>JEditorPane.createEditorKitForContentType</code>).
352      *
353      * <p>The editor kits are registered in <code>MimeLookup</code> for each
354      * particular mime type and the registry itself does not impose any rules on
355      * the editor kit implementations other than extending the <code>EditorKit</code>
356      * class. This for example means that the same implemantation of <code>EditorKit</code>
357      * can be used for multiple mime types. This is exactly how XML editor kit
358      * is reused for various flavors of XML documents (e.g. ant build scripts,
359      * web app descriptors, etc).
360      *
361      * <p>Netbeans did not always have <code>MimeLookup</code>
362      * and it also used a different approach for registering and retrieving
363      * editor kits. This old approach was based on implemetation classes rather than on mime
364      * types and while it is still more or less functional for the old kit
365      * implementations, it is fundamentally broken and should not be used any more.
366      * The code below demonstrates probably the biggest mistake when thinking
367      * in the old ways.
368      *
369      * <pre>
370      * // WARNING: The code below is a demonstration of a common mistake that
371      * // people do when using <code>BaseKit.getKit</code>.
372      *
373      * JTextComponent component = ...; // Let's say we have a component
374      * Class kitClass = Utilities.getKitClass(component);
375      * String mimeType = BaseKit.getKit(kitClass).getContentType();
376      * </pre>
377      *
378      * <p>The problem with the above code is that it blindely assumes that each
379      * kit class can be uniquely mapped to a mime type. This is not true! The
380      * same can be achieved in much easier way, which always works.
381      *
382      * <pre>
383      * JTextComponent component = ...; // Let's say we have a component
384      * String mimeType = component.getUI().getEditorKit(component).getContentType();
385      * </pre>
386      * </div>
387      *
388      * @param kitClass An implementation class of the editor kit that should
389      * be returned. If the <code>kitClass</code> is not <code>BaseKit</code> or
390      * its subclass the instance of bare <code>BaseKit</code> will be returned.
391      *
392      * @return An instance of the <code>kitClass</code> or <code>BaseKit</code>.
393      * @deprecated Use <code>CloneableEditorSupport.getEditorKit</code> or
394      * <code>MimeLookup</code> instead to find <code>EditorKit</code> for a mime
395      * type.
396      */

397     public static BaseKit getKit(Class JavaDoc kitClass) {
398         if (kitClass != null && BaseKit.class.isAssignableFrom(kitClass) && BaseKit.class != kitClass) {
399             if (!noKitsTracker) {
400                 String JavaDoc mimeType = kitsTracker_FindMimeType(kitClass);
401                 if (mimeType != null) {
402                     EditorKit JavaDoc kit = MimeLookup.getLookup(MimePath.parse(mimeType)).lookup(EditorKit JavaDoc.class);
403                     if (kit instanceof BaseKit) {
404                         return (BaseKit) kit;
405                     }
406                 }
407             }
408         } else {
409             kitClass = BaseKit.class;
410         }
411         
412         synchronized (kits) {
413             BaseKit kit = (BaseKit)kits.get(kitClass);
414             if (kit == null) {
415                 try {
416                     kit = (BaseKit)kitClass.newInstance();
417                 } catch (IllegalAccessException JavaDoc e) {
418                     LOG.log(Level.WARNING, null, e);
419                 } catch (InstantiationException JavaDoc e) {
420                     LOG.log(Level.WARNING, null, e);
421                 }
422                 kits.put(kitClass, kit);
423             }
424             return kit;
425         }
426     }
427
428     private static volatile boolean noKitsTracker = false;
429     private static String JavaDoc kitsTracker_FindMimeType(Class JavaDoc kitClass) {
430         String JavaDoc mimeType = null;
431         
432         if (!noKitsTracker) {
433             try {
434                 ClassLoader JavaDoc cl = Lookup.getDefault().lookup(ClassLoader JavaDoc.class);
435                 Class JavaDoc clazz = cl.loadClass("org.netbeans.modules.editor.impl.KitsTracker"); //NOI18N
436
Method JavaDoc getInstanceMethod = clazz.getDeclaredMethod("getInstance"); //NOI18N
437
Method JavaDoc findMimeTypeMethod = clazz.getDeclaredMethod("findMimeType", Class JavaDoc.class); //NOI18N
438
Object JavaDoc kitsTracker = getInstanceMethod.invoke(null);
439                 mimeType = (String JavaDoc) findMimeTypeMethod.invoke(kitsTracker, kitClass);
440             } catch (Exception JavaDoc e) {
441                 // ignore
442
noKitsTracker = true;
443             }
444         }
445         
446         return mimeType;
447     }
448     
449     /**
450      * Creates a new instance of <code>BaseKit</code>.
451      *
452      * <div class="nonnormative">
453      * <p>You should not need to instantiate editor kits
454      * directly under normal circumstances. There is a few ways how you can get
455      * instance of <code>EditorKit</code> depending on what you already have
456      * available:
457      *
458      * <ul>
459      * <li><b>mime type</b> - Use <code>CloneableEditorSupport.getEditorKit(yourMimeType)</code>
460      * to get the <code>EditorKit</code> registered for your mime type or use
461      * the following code <code>MimeLookup.getLookup(MimePath.parse(yourMimeType)).lookup(EditorKit.class)</code>
462      * and check for <code>null</code>.
463      * <li><b>JTextComponent</b> - Simply call
464      * <code>JTextComponent.getUI().getEditorKit(JTextComponent)</code> passing
465      * in the same component.
466      * </ul>
467      * </div>
468      */

469     public BaseKit() {
470         // possibly register
471
synchronized (kits) {
472             if (kits.get(this.getClass()) == null) {
473                 kits.put(this.getClass(), this); // register itself
474
}
475         }
476     }
477
478     /** Clone this editor kit */
479     public Object JavaDoc clone() {
480         return this; // no need to create another instance
481
}
482
483     /** Fetches a factory that is suitable for producing
484      * views of any models that are produced by this
485      * kit. The default is to have the UI produce the
486      * factory, so this method has no implementation.
487      *
488      * @return the view factory
489      */

490     public ViewFactory JavaDoc getViewFactory() {
491         return null;
492     }
493
494     /** Create caret to navigate through document */
495     public Caret JavaDoc createCaret() {
496         return new BaseCaret();
497     }
498
499     /** Create empty document */
500     public Document JavaDoc createDefaultDocument() {
501         return new BaseDocument(this.getClass(), true);
502     }
503
504     /** Create new instance of syntax coloring scanner
505     * @param doc document to operate on. It can be null in the cases the syntax
506     * creation is not related to the particular document
507     */

508     public Syntax createSyntax(Document JavaDoc doc) {
509         return new DefaultSyntax();
510     }
511
512     /** Create the syntax used for formatting */
513     public Syntax createFormatSyntax(Document JavaDoc doc) {
514         return createSyntax(doc);
515     }
516
517     /** Create syntax support */
518     public SyntaxSupport createSyntaxSupport(BaseDocument doc) {
519         return new SyntaxSupport(doc);
520     }
521
522     /** Create the formatter appropriate for this kit */
523     public Formatter createFormatter() {
524         return new Formatter(this.getClass());
525     }
526
527     /** Create text UI */
528     protected BaseTextUI createTextUI() {
529         return new BaseTextUI();
530     }
531
532     /** Create extended UI */
533     protected EditorUI createEditorUI() {
534         return new EditorUI();
535     }
536
537     /**
538      * Create extended UI for printing a document.
539      * @deprecated this method is no longer being called by {@link EditorUI}.
540      * {@link #createPrintEditorUI(BaseDocument, boolean, boolean)} is being
541      * called instead.
542      */

543     protected EditorUI createPrintEditorUI(BaseDocument doc) {
544         return new EditorUI(doc);
545     }
546     
547     /**
548      * Create extended UI for printing a document.
549      *
550      * @param doc document for which the extended UI is being created.
551      * @param usePrintColoringMap use printing coloring settings instead
552      * of the regular ones.
553      * @param lineNumberEnabled if set to false the line numbers will not be printed.
554      * If set to true the visibility of line numbers depends on the settings
555      * for the line number visibility.
556      */

557     protected EditorUI createPrintEditorUI(BaseDocument doc,
558     boolean usePrintColoringMap, boolean lineNumberEnabled) {
559         
560         return new EditorUI(doc, usePrintColoringMap, lineNumberEnabled);
561     }
562
563     public MultiKeymap getKeymap() {
564         synchronized (Settings.class) {
565             MultiKeymap km = (MultiKeymap)kitKeymaps.get(this.getClass());
566             if (km == null) { // keymap not yet constructed
567
// construct new keymap
568
km = new MultiKeymap("Keymap for " + this.getClass()); // NOI18N
569
// retrieve key bindings for this kit and super kits
570
Settings.KitAndValue kv[] = Settings.getValueHierarchy(
571                                                 this.getClass(), SettingsNames.KEY_BINDING_LIST);
572                 // go through all levels and collect key bindings
573
for (int i = kv.length - 1; i >= 0; i--) {
574                     List JavaDoc keyList = (List JavaDoc)kv[i].value;
575                     JTextComponent.KeyBinding JavaDoc[] keys = new JTextComponent.KeyBinding JavaDoc[keyList.size()];
576                     keyList.toArray(keys);
577                     km.load(keys, getActionMap());
578                 }
579                 
580                 km.setDefaultAction((Action JavaDoc)getActionMap().get(defaultKeyTypedAction));
581
582                 kitKeymaps.put(this.getClass(), km);
583             }
584             return km;
585         }
586     }
587
588     /** Inserts content from the given stream. */
589     public void read(Reader JavaDoc in, Document JavaDoc doc, int pos)
590     throws IOException JavaDoc, BadLocationException JavaDoc {
591         if (doc instanceof BaseDocument) {
592             ((BaseDocument)doc).read(in, pos); // delegate it to document
593
} else {
594             super.read(in, doc, pos);
595         }
596     }
597
598     /** Writes content from a document to the given stream */
599     public void write(Writer JavaDoc out, Document JavaDoc doc, int pos, int len)
600     throws IOException JavaDoc, BadLocationException JavaDoc {
601         if (doc instanceof BaseDocument) {
602             ((BaseDocument)doc).write(out, pos, len);
603         } else {
604             super.write(out, doc, pos, len);
605         }
606     }
607
608     /** Creates map with [name, action] pairs from the given
609     * array of actions.
610     */

611     public static Map JavaDoc actionsToMap(Action JavaDoc[] actions) {
612         Map JavaDoc map = new HashMap JavaDoc();
613         for (int i = 0; i < actions.length; i++) {
614             Action JavaDoc a = actions[i];
615             String JavaDoc name = (String JavaDoc)a.getValue(Action.NAME);
616             map.put(((name != null) ? name : ""), a); // NOI18N
617
}
618         return map;
619     }
620
621     /** Converts map with [name, action] back
622     * to array of actions.
623     */

624     public static Action JavaDoc[] mapToActions(Map JavaDoc map) {
625         Action JavaDoc[] actions = new Action JavaDoc[map.size()];
626         int i = 0;
627         for (Iterator JavaDoc iter = map.values().iterator() ; iter.hasNext() ;) {
628             actions[i++] = (Action JavaDoc)iter.next();
629         }
630         return actions;
631     }
632
633     /** Called after the kit is installed into JEditorPane */
634     public void install(JEditorPane JavaDoc c) {
635         
636         assert (SwingUtilities.isEventDispatchThread()) // expected in AWT only
637
: "BaseKit.install() incorrectly called from non-AWT thread."; // NOI18N
638

639         BaseTextUI ui = createTextUI();
640         c.setUI(ui);
641
642         String JavaDoc propName = "netbeans.editor.noinputmethods"; // NOI18N
643
Object JavaDoc noInputMethods = System.getProperty(propName);
644         boolean enableIM;
645         if (noInputMethods != null) {
646             enableIM = !Boolean.getBoolean(propName);
647         } else {
648             enableIM = SettingsUtil.getBoolean(this.getClass(),
649                                                SettingsNames.INPUT_METHODS_ENABLED, true);
650         }
651
652         c.enableInputMethods(enableIM);
653         executeInstallActions(c);
654         
655         c.putClientProperty("hyperlink-operation", // NOI18N
656
org.netbeans.lib.editor.hyperlink.HyperlinkOperation.create(c, getContentType()));
657
658         // Mark that the editor's multi keymap adheres to context API in status displayer
659
c.putClientProperty("context-api-aware", Boolean.TRUE); // NOI18N
660
}
661
662     protected void executeInstallActions(JEditorPane JavaDoc c) {
663         Settings.KitAndValue[] kv = Settings.getValueHierarchy(this.getClass(),
664                                     SettingsNames.KIT_INSTALL_ACTION_NAME_LIST);
665         for (int i = kv.length - 1; i >= 0; i--) {
666             List JavaDoc actList = (List JavaDoc)kv[i].value;
667             actList = translateActionNameList(actList); // translate names to actions
668
if (actList != null) {
669                 for (Iterator JavaDoc iter = actList.iterator(); iter.hasNext();) {
670                     Action JavaDoc a = (Action JavaDoc)iter.next();
671                     a.actionPerformed(new ActionEvent JavaDoc(c, ActionEvent.ACTION_PERFORMED, "")); // NOI18N
672
}
673             }
674         }
675     }
676
677     public void deinstall(JEditorPane JavaDoc c) {
678         
679         assert (SwingUtilities.isEventDispatchThread()); // expected in AWT only
680

681         BaseTextUI.uninstallUIWatcher(c);
682         executeDeinstallActions(c);
683         c.updateUI();
684         
685         // #41209: reset ancestor override flag if previously set
686
if (c.getClientProperty("ancestorOverride") != null) { // NOI18N
687
c.putClientProperty("ancestorOverride", Boolean.FALSE); // NOI18N
688
}
689     }
690
691     protected void executeDeinstallActions(JEditorPane JavaDoc c) {
692         Settings.KitAndValue[] kv = Settings.getValueHierarchy(this.getClass(),
693                                     SettingsNames.KIT_DEINSTALL_ACTION_NAME_LIST);
694         for (int i = kv.length - 1; i >= 0; i--) {
695             List JavaDoc actList = (List JavaDoc)kv[i].value;
696             actList = translateActionNameList(actList); // translate names to actions
697
if (actList != null) {
698                 for (Iterator JavaDoc iter = actList.iterator(); iter.hasNext();) {
699                     Action JavaDoc a = (Action JavaDoc)iter.next();
700                     a.actionPerformed(new ActionEvent JavaDoc(c, ActionEvent.ACTION_PERFORMED, "")); // NOI18N
701
}
702             }
703         }
704     }
705
706     /** Initialize document by adding the draw-layers for example. */
707     protected void initDocument(BaseDocument doc) {
708     }
709
710     /** Create actions that this kit supports. To use the actions of the parent kit
711     * it's better instead of using super.createActions() to use
712     * getKit(super.getClass()).getActions() because it can reuse existing
713     * parent actions.
714     */

715     protected Action JavaDoc[] createActions() {
716         return new Action JavaDoc[] {
717                    new DefaultKeyTypedAction(),
718                    new InsertContentAction(),
719                    new InsertBreakAction(),
720            new SplitLineAction(),
721                    new InsertTabAction(),
722                    deletePrevCharActionDef,
723                    deleteNextCharActionDef,
724                    new ReadOnlyAction(),
725                    new WritableAction(),
726                    cutActionDef,
727                    copyActionDef,
728                    pasteActionDef,
729                    new PasteAction(true),
730                    new BeepAction(),
731                    new UpAction(upAction, false),
732                    new UpAction(selectionUpAction, true),
733                    new PageUpAction(pageUpAction, false),
734                    new PageUpAction(selectionPageUpAction, true),
735                    new DownAction(downAction, false),
736                    new DownAction(selectionDownAction, true),
737                    new PageDownAction(selectionPageDownAction, true),
738                    new PageDownAction(pageDownAction, false),
739                    new ForwardAction(forwardAction, false),
740                    new ForwardAction(selectionForwardAction, true),
741                    new BackwardAction(backwardAction, false),
742                    new BackwardAction(selectionBackwardAction, true),
743                    new BeginLineAction(lineFirstColumnAction, false, true),
744                    new BeginLineAction(selectionLineFirstColumnAction, true, true),
745                    new BeginLineAction(beginLineAction, false),
746                    new BeginLineAction(selectionBeginLineAction, true),
747                    new EndLineAction(endLineAction, false),
748                    new EndLineAction(selectionEndLineAction, true),
749                    new BeginAction(beginAction, false),
750                    new BeginAction(selectionBeginAction, true),
751                    new EndAction(endAction, false),
752                    new EndAction(selectionEndAction, true),
753                    new NextWordAction(nextWordAction, false),
754                    new NextWordAction(selectionNextWordAction, true),
755                    new PreviousWordAction(previousWordAction, false),
756                    new PreviousWordAction(selectionPreviousWordAction, true),
757                    new BeginWordAction(beginWordAction, false),
758                    new BeginWordAction(selectionBeginWordAction, true),
759                    new EndWordAction(endWordAction, false),
760                    new EndWordAction(selectionEndWordAction, true),
761                    new SelectWordAction(),
762                    new SelectLineAction(),
763                    new SelectAllAction(),
764                    new RemoveTrailingSpacesAction(),
765                    new ActionFactory.RemoveTabAction(),
766                    //new ActionFactory.RemoveWordAction(), #47709
767
new ActionFactory.RemoveWordPreviousAction(),
768                    new ActionFactory.RemoveWordNextAction(),
769                    new ActionFactory.RemoveLineBeginAction(),
770                    new ActionFactory.RemoveLineAction(),
771                    removeSelectionActionDef,
772                    new ActionFactory.ToggleTypingModeAction(),
773                    new ActionFactory.AbbrevExpandAction(),
774                    new ActionFactory.AbbrevResetAction(),
775                    new ActionFactory.ChangeCaseAction(toUpperCaseAction, Utilities.CASE_UPPER),
776                    new ActionFactory.ChangeCaseAction(toLowerCaseAction, Utilities.CASE_LOWER),
777                    new ActionFactory.ChangeCaseAction(switchCaseAction, Utilities.CASE_SWITCH),
778                    new ActionFactory.FindNextAction(),
779                    new ActionFactory.FindPreviousAction(),
780                    new ActionFactory.FindSelectionAction(),
781                    new ActionFactory.ToggleHighlightSearchAction(),
782                    undoActionDef,
783                    redoActionDef,
784                    new ActionFactory.WordMatchAction(wordMatchNextAction, true),
785                    new ActionFactory.WordMatchAction(wordMatchPrevAction, false),
786                    new ActionFactory.ReindentLineAction(),
787                    new ActionFactory.ShiftLineAction(shiftLineLeftAction, false),
788                    new ActionFactory.ShiftLineAction(shiftLineRightAction, true),
789                    new ActionFactory.AdjustWindowAction(adjustWindowTopAction, 0),
790                    new ActionFactory.AdjustWindowAction(adjustWindowCenterAction, 50),
791                    new ActionFactory.AdjustWindowAction(adjustWindowBottomAction, 100),
792                    new ActionFactory.AdjustCaretAction(adjustCaretTopAction, 0),
793                    new ActionFactory.AdjustCaretAction(adjustCaretCenterAction, 50),
794                    new ActionFactory.AdjustCaretAction(adjustCaretBottomAction, 100),
795                    new ActionFactory.FormatAction(),
796                    new ActionFactory.FirstNonWhiteAction(firstNonWhiteAction, false),
797                    new ActionFactory.FirstNonWhiteAction(selectionFirstNonWhiteAction, true),
798                    new ActionFactory.LastNonWhiteAction(lastNonWhiteAction, false),
799                    new ActionFactory.LastNonWhiteAction(selectionLastNonWhiteAction, true),
800                    new ActionFactory.SelectIdentifierAction(),
801                    new ActionFactory.SelectNextParameterAction(),
802                    new ActionFactory.JumpListPrevAction(),
803                    new ActionFactory.JumpListNextAction(),
804                    new ActionFactory.JumpListPrevComponentAction(),
805                    new ActionFactory.JumpListNextComponentAction(),
806                    new ActionFactory.ScrollUpAction(),
807                    new ActionFactory.ScrollDownAction(),
808                    new ActionFactory.StartMacroRecordingAction(),
809                    new ActionFactory.StopMacroRecordingAction(),
810                    new ActionFactory.InsertDateTimeAction(),
811                    new ActionFactory.GenerateGutterPopupAction(),
812                    new ActionFactory.ToggleLineNumbersAction(),
813                    new ActionFactory.AnnotationsCyclingAction(),
814                    new ActionFactory.CollapseFold(),
815                    new ActionFactory.ExpandFold(),
816                    new ActionFactory.CollapseAllFolds(),
817                    new ActionFactory.ExpandAllFolds(),
818                    new ActionFactory.DumpViewHierarchyAction(),
819                    new ActionFactory.StartNewLine(),
820                    new ActionFactory.CutToLineBeginOrEndAction(false),
821                    new ActionFactory.CutToLineBeginOrEndAction(true),
822
823                    // Self test actions
824
// new EditorDebug.SelfTestAction(),
825
// new EditorDebug.DumpPlanesAction(),
826
// new EditorDebug.DumpSyntaxMarksAction()
827
};
828     }
829
830     protected Action JavaDoc[] getCustomActions() {
831         Settings.KitAndValue kv[] = Settings.getValueHierarchy(
832                                           this.getClass(), SettingsNames.CUSTOM_ACTION_LIST);
833         if (kv.length == 0) {
834             return null;
835         }
836         if (kv.length == 1) {
837             List JavaDoc l = (List JavaDoc)kv[0].value;
838             return (Action JavaDoc[])l.toArray(new Action JavaDoc[l.size()]);
839         }
840         // more than one list of actions
841
List JavaDoc l = new ArrayList JavaDoc();
842         for (int i = kv.length - 1; i >= 0; i--) { // from BaseKit down
843
l.addAll((List JavaDoc)kv[i].value);
844         }
845         return (Action JavaDoc[])l.toArray(new Action JavaDoc[l.size()]);
846     }
847     
848     protected Action JavaDoc[] getMacroActions() {
849         Class JavaDoc kitClass = this.getClass();
850         Map JavaDoc macroMap = (Map JavaDoc)Settings.getValue( kitClass, SettingsNames.MACRO_MAP);
851         if( macroMap == null ) return null;
852         List JavaDoc actions = new ArrayList JavaDoc();
853         for( Iterator JavaDoc it = macroMap.keySet().iterator(); it.hasNext(); ) {
854             String JavaDoc macroName = (String JavaDoc)it.next();
855             actions.add( new ActionFactory.RunMacroAction( macroName ) );
856         }
857         return (Action JavaDoc[])actions.toArray( new Action JavaDoc[ actions.size() ] );
858     }
859
860     /** Get actions associated with this kit. createActions() is called
861     * to get basic list and then customActions are added.
862     */

863     public final Action JavaDoc[] getActions() {
864         synchronized (Settings.class) { // possibly long running code follows
865
Class JavaDoc thisClass = this.getClass();
866             Action JavaDoc[] actions = (Action JavaDoc[])kitActions.get(thisClass);
867             if (actions == null) {
868                 // create map of actions
869
Action JavaDoc[] createdActions = createActions();
870                 updateActionSettings(createdActions, null, thisClass);
871                 Map JavaDoc actionMap = actionsToMap(createdActions);
872                 // add custom actions
873
Action JavaDoc[] customActions = getCustomActions();
874                 if (customActions != null) {
875                     updateActionSettings(customActions, null, thisClass);
876                     actionMap.putAll(actionsToMap(customActions));
877                 }
878                 Action JavaDoc[] macroActions = getMacroActions();
879                 if (macroActions != null) {
880                     updateActionSettings(macroActions, null, thisClass);
881                     actionMap.putAll(actionsToMap(macroActions));
882                 }
883
884                 // store for later use
885
kitActionMaps.put(thisClass, actionMap);
886                 // create action array and store for later use
887
actions = mapToActions(actionMap);
888                 kitActions.put(thisClass, actions);
889
890                 // At this moment the actions are constructed completely
891
// The actions will be updated now if necessary
892
updateActions();
893             }
894             return actions;
895         }
896     }
897
898     Map JavaDoc getActionMap() {
899         Map JavaDoc actionMap = (Map JavaDoc)kitActionMaps.get(this.getClass());
900         if (actionMap == null) {
901             getActions(); // init action map
902
actionMap = (Map JavaDoc)kitActionMaps.get(this.getClass());
903
904             // Fix of #27418
905
if (actionMap == null) {
906                 actionMap = Collections.EMPTY_MAP;
907             }
908         }
909         return actionMap;
910     }
911
912     /** Update the actions right after their creation was finished.
913      * The <code>getActions()</code> and <code>getActionByName()</code>
914      * can be used safely in this method.
915      * The implementation must call <code>super.updateActions()</code> so that
916      * the updating in parent is performed too.
917      */

918     protected void updateActions() {
919     }
920
921     /** Get action from its name. */
922     public Action JavaDoc getActionByName(String JavaDoc name) {
923         return (name != null) ? (Action JavaDoc)getActionMap().get(name) : null;
924     }
925
926     public List JavaDoc translateActionNameList(List JavaDoc actionNameList) {
927         List JavaDoc ret = new ArrayList JavaDoc();
928         if (actionNameList != null) {
929             Iterator JavaDoc i = actionNameList.iterator();
930             while (i.hasNext()) {
931                 Action JavaDoc a = getActionByName((String JavaDoc)i.next());
932                 if (a != null) {
933                     ret.add(a);
934                 }
935             }
936         }
937         return ret;
938     }
939
940
941
942     /** Default typed action */
943     public static class DefaultKeyTypedAction extends LocalBaseAction {
944
945         static final long serialVersionUID =3069164318144463899L;
946
947         public DefaultKeyTypedAction() {
948             super(defaultKeyTypedAction, MAGIC_POSITION_RESET | SAVE_POSITION
949                 | CLEAR_STATUS_TEXT);
950             putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE);
951         }
952
953         private static final boolean isMac = System.getProperty("mrj.version") != null; //NOI18N
954
public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
955             if ((target != null) && (evt != null)) {
956
957                 // Check whether the modifiers are OK
958
int mod = evt.getModifiers();
959                 boolean ctrl = ((mod & ActionEvent.CTRL_MASK) != 0);
960                 // On the mac, norwegian and french keyboards use Alt to do bracket characters.
961
// This replicates Apple's modification DefaultEditorKit.DefaultKeyTypedAction
962
boolean alt = isMac ? ((mod & ActionEvent.META_MASK) != 0) :
963                     ((mod & ActionEvent.ALT_MASK) != 0);
964                 
965                 
966                 if (alt || ctrl) {
967                     return;
968                 }
969                 
970                 // Check whether the target is enabled and editable
971
if (!target.isEditable() || !target.isEnabled()) {
972                     target.getToolkit().beep();
973                     return;
974                 }
975
976                 Caret JavaDoc caret = target.getCaret();
977                 BaseDocument doc = (BaseDocument)target.getDocument();
978                 EditorUI editorUI = Utilities.getEditorUI(target);
979                 // determine if typed char is valid
980
String JavaDoc cmd = evt.getActionCommand();
981                 if ((cmd != null) && (cmd.length() == 1)) {
982                     // Utilities.clearStatusText(target);
983

984                     doc.atomicLock();
985                     DocumentUtilities.setTypingModification(doc, true);
986                     try {
987                         char ch = cmd.charAt(0);
988                         if ((ch >= 0x20) && (ch != 0x7F)) { // valid character
989
editorUI.getWordMatch().clear(); // reset word matching
990
Boolean JavaDoc overwriteMode = (Boolean JavaDoc)editorUI.getProperty(
991                                                         EditorUI.OVERWRITE_MODE_PROPERTY);
992                             try {
993                                 boolean doInsert = true; // editorUI.getAbbrev().checkAndExpand(ch, evt);
994
if (doInsert) {
995                                     if (caret.isSelectionVisible()) { // valid selection
996
boolean ovr = (overwriteMode != null && overwriteMode.booleanValue());
997                                         try {
998                                             doc.putProperty(DOC_REPLACE_SELECTION_PROPERTY, true);
999                                             replaceSelection(target, caret.getDot(), caret, cmd, ovr);
1000                                        } finally {
1001                                            doc.putProperty(DOC_REPLACE_SELECTION_PROPERTY, null);
1002                                        }
1003                                    } else { // no selection
1004
int dotPos = caret.getDot();
1005                                        if (overwriteMode != null && overwriteMode.booleanValue()
1006                                                && dotPos < doc.getLength() && doc.getChars(dotPos, 1)[0] != '\n'
1007                                           ) { // overwrite current char
1008
doc.atomicLock();
1009                                            try {
1010                                              insertString(doc, dotPos, caret, cmd, true);
1011                                            } finally {
1012                                              doc.atomicUnlock();
1013                                            }
1014                                        } else { // insert mode
1015
doc.atomicLock();
1016                                            try {
1017                                              insertString(doc, dotPos, caret, cmd, false);
1018                                            } finally {
1019                                                doc.atomicUnlock();
1020                                            }
1021                                        }
1022                                    }
1023                                }
1024                            } catch (BadLocationException JavaDoc e) {
1025                                target.getToolkit().beep();
1026                            }
1027                        }
1028
1029                        checkIndent(target, cmd);
1030                    } finally {
1031                        DocumentUtilities.setTypingModification(doc, false);
1032                        doc.atomicUnlock();
1033                    }
1034                }
1035
1036            }
1037        }
1038
1039      /**
1040       * Hook to insert the given string at the given position into
1041       * the given document in insert-mode, no selection, writeable
1042       * document. Designed to be overridden by subclasses that want
1043       * to intercept inserted characters.
1044       */

1045      protected void insertString(BaseDocument doc,
1046                  int dotPos,
1047                  Caret JavaDoc caret,
1048                  String JavaDoc str,
1049                  boolean overwrite)
1050    throws BadLocationException JavaDoc
1051      {
1052    if (overwrite) doc.remove(dotPos, 1);
1053    doc.insertString(dotPos, str, null);
1054      }
1055
1056      /**
1057       * Hook to insert the given string at the given position into
1058       * the given document in insert-mode with selection visible
1059       * Designed to be overridden by subclasses that want
1060       * to intercept inserted characters.
1061       */

1062      protected void replaceSelection(JTextComponent JavaDoc target,
1063                  int dotPos,
1064                  Caret JavaDoc caret,
1065                  String JavaDoc str,
1066                  boolean overwrite)
1067    throws BadLocationException JavaDoc
1068      {
1069          target.replaceSelection(str);
1070      }
1071
1072
1073        /** Check whether there was any important character typed
1074        * so that the line should be possibly reformatted.
1075        */

1076        protected void checkIndent(JTextComponent JavaDoc target, String JavaDoc typedText) {
1077        }
1078
1079    }
1080
1081    public static class InsertBreakAction extends LocalBaseAction {
1082
1083        static final long serialVersionUID =7966576342334158659L;
1084
1085        public InsertBreakAction() {
1086            super(insertBreakAction, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET);
1087        }
1088
1089        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1090            if (target != null) {
1091                if (!target.isEditable() || !target.isEnabled()) {
1092                    target.getToolkit().beep();
1093                    return;
1094                }
1095
1096                BaseDocument doc = (BaseDocument)target.getDocument();
1097                doc.atomicLock();
1098                DocumentUtilities.setTypingModification(doc, true);
1099                try{
1100                    target.replaceSelection("");
1101                    Caret JavaDoc caret = target.getCaret();
1102                    Object JavaDoc cookie = beforeBreak(target, doc, caret);
1103
1104                    int dotPos = caret.getDot();
1105                    int newDotPos = doc.getFormatter().indentNewLine(doc, dotPos);
1106                    caret.setDot(newDotPos);
1107
1108                    afterBreak(target, doc, caret, cookie);
1109                } finally {
1110                    DocumentUtilities.setTypingModification(doc, false);
1111                    doc.atomicUnlock();
1112                }
1113            }
1114        }
1115
1116      /**
1117       * Hook called before any changes to the document. The value
1118       * returned is passed intact to the other hook.
1119       */

1120      protected Object JavaDoc beforeBreak(JTextComponent JavaDoc target, BaseDocument doc, Caret JavaDoc caret) {
1121    return null;
1122      }
1123
1124      /**
1125       * Hook called after the enter was inserted and cursor
1126       * repositioned. *data* is the object returned previously by
1127       * *beforeBreak* hook. By default null.
1128       */

1129      protected void afterBreak(JTextComponent JavaDoc target, BaseDocument doc, Caret JavaDoc caret, Object JavaDoc data) {
1130      }
1131    }
1132
1133    public static class SplitLineAction extends LocalBaseAction {
1134
1135        static final long serialVersionUID =7966576342334158659L;
1136
1137        public SplitLineAction() {
1138      super(splitLineAction, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET);
1139        }
1140
1141        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1142            if (target != null) {
1143                if (!target.isEditable() || !target.isEnabled()) {
1144                    target.getToolkit().beep();
1145                    return;
1146                }
1147
1148                BaseDocument doc = (BaseDocument)target.getDocument();
1149                Caret JavaDoc caret = target.getCaret();
1150                int dotPos = caret.getDot();
1151        
1152                doc.atomicLock();
1153                DocumentUtilities.setTypingModification(doc, true);
1154                try{
1155                    target.replaceSelection("");
1156                    int newDotPos = dotPos; // dot stays where it was
1157
doc.getFormatter().indentNewLine(doc, dotPos); // newline
1158
caret.setDot(newDotPos);
1159                } finally {
1160                    DocumentUtilities.setTypingModification(doc, false);
1161                    doc.atomicUnlock();
1162                }
1163            }
1164        }
1165
1166    }
1167
1168
1169    public static class InsertTabAction extends LocalBaseAction {
1170
1171        static final long serialVersionUID =-3379768531715989243L;
1172
1173        public InsertTabAction() {
1174            super(insertTabAction, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET);
1175        }
1176
1177        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1178            if (target != null) {
1179                if (!target.isEditable() || !target.isEnabled()) {
1180                    target.getToolkit().beep();
1181                    return;
1182                }
1183
1184                Caret JavaDoc caret = target.getCaret();
1185                BaseDocument doc = (BaseDocument)target.getDocument();
1186                doc.atomicLock();
1187                DocumentUtilities.setTypingModification(doc, true);
1188                try {
1189                if (caret.isSelectionVisible()) { // block selected
1190
try {
1191                        doc.getFormatter().changeBlockIndent(doc,
1192                                target.getSelectionStart(), target.getSelectionEnd(), +1);
1193                    } catch (GuardedException e) {
1194                        target.getToolkit().beep();
1195                    } catch (BadLocationException JavaDoc e) {
1196                        e.printStackTrace();
1197                    }
1198                } else { // no selected text
1199
int dotPos = caret.getDot();
1200                    int caretCol;
1201                    // find caret column
1202
try {
1203                        caretCol = doc.getVisColFromPos(dotPos);
1204                    } catch (BadLocationException JavaDoc e) {
1205                        LOG.log(Level.WARNING, null, e);
1206                        caretCol = 0;
1207                    }
1208
1209                    try {
1210                        // find indent of the first previous non-white row
1211
int upperCol = Utilities.getRowIndent(doc, dotPos, false);
1212                        if (upperCol == -1) { // no prev line with indent
1213
upperCol = 0;
1214                        }
1215                        // is there any char on this line before cursor?
1216
int indent = Utilities.getRowIndent(doc, dotPos);
1217                        // test whether we should indent
1218
if (indent == -1) {
1219                            if (upperCol > caretCol) { // upper indent is greater
1220
indent = upperCol;
1221                            } else { // simulate insert tab by changing indent
1222
indent = Utilities.getNextTabColumn(doc, dotPos);
1223                            }
1224
1225                            // Fix of #32240 - #1 of 2
1226
int rowStart = Utilities.getRowStart(doc, dotPos);
1227
1228                            doc.getFormatter().changeRowIndent(doc, dotPos, indent);
1229
1230                            // Fix of #32240 - #2 of 2
1231
int newDotPos = doc.getOffsetFromVisCol(indent, rowStart);
1232                            if (newDotPos >= 0) {
1233                                caret.setDot(newDotPos);
1234                            }
1235                            
1236                        } else { // already chars on the line
1237
doc.getFormatter().insertTabString(doc, dotPos);
1238
1239                        }
1240                    } catch (BadLocationException JavaDoc e) {
1241                        // use the same pos
1242
}
1243                }
1244                } finally {
1245                    DocumentUtilities.setTypingModification(doc, false);
1246                    doc.atomicUnlock();
1247                }
1248            }
1249
1250        }
1251
1252    }
1253
1254    /** Compound action that encapsulates several actions */
1255    public static class CompoundAction extends LocalBaseAction {
1256
1257        Action JavaDoc[] actions;
1258
1259        static final long serialVersionUID =1649688300969753758L;
1260
1261        public CompoundAction(String JavaDoc nm, Action JavaDoc actions[]) {
1262            this(nm, 0, actions);
1263        }
1264
1265        public CompoundAction(String JavaDoc nm, int resetMask, Action JavaDoc actions[]) {
1266            super(nm, resetMask);
1267            this.actions = actions;
1268        }
1269
1270        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1271            if (target != null) {
1272                for (int i = 0; i < actions.length; i++) {
1273                    Action JavaDoc a = actions[i];
1274                    if (a instanceof BaseAction) {
1275                        ((BaseAction)a).actionPerformed(evt, target);
1276                    } else {
1277                        a.actionPerformed(evt);
1278                    }
1279                }
1280            }
1281        }
1282    }
1283
1284    /** Compound action that gets and executes its actions
1285    * depending on the kit of the component.
1286    * The other advantage is that it doesn't create additional
1287    * instances of compound actions.
1288    */

1289    public static class KitCompoundAction extends LocalBaseAction {
1290
1291        private String JavaDoc[] actionNames;
1292
1293        static final long serialVersionUID =8415246475764264835L;
1294
1295        public KitCompoundAction(String JavaDoc nm, String JavaDoc actionNames[]) {
1296            this(nm, 0, actionNames);
1297        }
1298
1299        public KitCompoundAction(String JavaDoc nm, int resetMask, String JavaDoc actionNames[]) {
1300            super(nm, resetMask);
1301            this.actionNames = actionNames;
1302        }
1303
1304        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1305            if (target != null) {
1306                BaseKit kit = Utilities.getKit(target);
1307                if (kit != null) {
1308                    for (int i = 0; i < actionNames.length; i++) {
1309                        Action JavaDoc a = kit.getActionByName(actionNames[i]);
1310                        if (a != null) {
1311                            if (a instanceof BaseAction) {
1312                                ((BaseAction)a).actionPerformed(evt, target);
1313                            } else {
1314                                a.actionPerformed(evt);
1315                            }
1316                        }
1317                    }
1318                }
1319            }
1320        }
1321    }
1322
1323    public static class InsertContentAction extends LocalBaseAction {
1324
1325        static final long serialVersionUID =5647751370952797218L;
1326
1327        public InsertContentAction() {
1328            super(insertContentAction, MAGIC_POSITION_RESET | ABBREV_RESET
1329                  | WORD_MATCH_RESET);
1330            putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE);
1331        }
1332
1333        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1334            if ((target != null) && (evt != null)) {
1335                if (!target.isEditable() || !target.isEnabled()) {
1336                    target.getToolkit().beep();
1337                    return;
1338                }
1339
1340                String JavaDoc content = evt.getActionCommand();
1341                if (content != null) {
1342                    target.replaceSelection(content);
1343                } else {
1344                    target.getToolkit().beep();
1345                }
1346            }
1347        }
1348    }
1349
1350    /** Insert text specified in constructor */
1351    public static class InsertStringAction extends LocalBaseAction {
1352
1353        String JavaDoc text;
1354
1355        static final long serialVersionUID =-2755852016584693328L;
1356
1357        public InsertStringAction(String JavaDoc nm, String JavaDoc text) {
1358            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET);
1359            this.text = text;
1360        }
1361
1362        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1363            if (target != null) {
1364                if (!target.isEditable() || !target.isEnabled()) {
1365                    target.getToolkit().beep();
1366                    return;
1367                }
1368
1369                target.replaceSelection(text);
1370            }
1371        }
1372    }
1373
1374    /** Remove previous or next character */
1375    public static class DeleteCharAction extends LocalBaseAction {
1376
1377        protected boolean nextChar;
1378
1379        static final long serialVersionUID =-4321971925753148556L;
1380
1381        public DeleteCharAction(String JavaDoc nm, boolean nextChar) {
1382            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | WORD_MATCH_RESET);
1383            this.nextChar = nextChar;
1384        }
1385
1386        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1387            if (target != null) {
1388                if (!target.isEditable() || !target.isEnabled()) {
1389                    target.getToolkit().beep();
1390                    return;
1391                }
1392
1393        BaseDocument doc = (BaseDocument)target.getDocument();
1394        Caret JavaDoc caret = target.getCaret();
1395        int dot = caret.getDot();
1396        int mark = caret.getMark();
1397
1398                doc.atomicLock();
1399                DocumentUtilities.setTypingModification(doc, true);
1400
1401                try {
1402                    if (dot != mark) { // remove selection
1403
doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
1404                    } else {
1405                        if (nextChar) { // remove next char
1406
doc.remove(dot, 1);
1407                        } else { // remove previous char
1408
char ch = doc.getChars(dot-1, 1)[0];
1409                            doc.remove(dot - 1, 1);
1410                            charBackspaced(doc, dot-1, caret, ch);
1411                        }
1412                    }
1413                } catch (BadLocationException JavaDoc e) {
1414                    target.getToolkit().beep();
1415                } finally {
1416                    DocumentUtilities.setTypingModification(doc, false);
1417                    doc.atomicUnlock();
1418                }
1419
1420            }
1421        }
1422
1423      protected void charBackspaced(BaseDocument doc, int dotPos, Caret JavaDoc caret, char ch)
1424    throws BadLocationException JavaDoc
1425      {
1426      }
1427    }
1428
1429    public static class ReadOnlyAction extends LocalBaseAction {
1430
1431        static final long serialVersionUID =9204335480208463193L;
1432
1433        public ReadOnlyAction() {
1434            super(readOnlyAction);
1435            putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE);
1436        }
1437
1438        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1439            if (target != null) {
1440                target.setEditable(false);
1441            }
1442        }
1443    }
1444
1445    public static class WritableAction extends LocalBaseAction {
1446
1447        static final long serialVersionUID =-5982547952800937954L;
1448
1449        public WritableAction() {
1450            super(writableAction);
1451            putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE);
1452        }
1453
1454        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1455            if (target != null) {
1456                target.setEditable(true);
1457            }
1458        }
1459    }
1460
1461    public static class CutAction extends LocalBaseAction {
1462
1463        static final long serialVersionUID =6377157040901778853L;
1464
1465        public CutAction() {
1466            super(cutAction, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET);
1467            setEnabled(false);
1468            //#54893 putValue ("helpID", CutAction.class.getName ()); // NOI18N
1469
}
1470
1471        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1472            if (target != null) {
1473                if (!target.isEditable() || !target.isEnabled()) {
1474                    target.getToolkit().beep();
1475                    return;
1476                }
1477
1478                BaseDocument doc = (BaseDocument)target.getDocument();
1479                doc.atomicLock();
1480                DocumentUtilities.setTypingModification(doc, true);
1481                try {
1482                    target.cut();
1483                } finally {
1484                    DocumentUtilities.setTypingModification(doc, false);
1485                    doc.atomicUnlock();
1486                }
1487            }
1488        }
1489    }
1490
1491    public static class CopyAction extends LocalBaseAction {
1492
1493        static final long serialVersionUID =-5119779005431986964L;
1494
1495        public CopyAction() {
1496            super(copyAction, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET);
1497            setEnabled(false);
1498            //#54893 putValue ("helpID", CopyAction.class.getName ()); // NOI18N
1499
}
1500
1501        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1502            if (target != null) {
1503                target.copy();
1504            }
1505        }
1506    }
1507
1508    public static class PasteAction extends LocalBaseAction {
1509
1510        static final long serialVersionUID =5839791453996432149L;
1511        private boolean formated;
1512
1513        public PasteAction(boolean formated) {
1514            super(formated ? pasteFormatedAction : pasteAction, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET);
1515            //#54893 putValue ("helpID", PasteAction.class.getName ()); // NOI18N
1516
this.formated = formated;
1517        }
1518
1519        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1520            if (target != null) {
1521                if (!target.isEditable() || !target.isEnabled()) {
1522                    target.getToolkit().beep();
1523                    return;
1524                }
1525                
1526                
1527                BaseDocument doc = Utilities.getDocument(target);
1528                if (doc==null) return;
1529                
1530                doc.atomicLock();
1531                DocumentUtilities.setTypingModification(doc, true);
1532                try{
1533                    if (formated) {
1534                        Caret JavaDoc caret = target.getCaret();
1535                        int prevPos = target.getSelectionStart();
1536                        target.paste();
1537                        int postPos = caret.getDot();
1538                        indentBlock(doc, prevPos, postPos);
1539                    } else {
1540                        target.paste();
1541                    }
1542                }catch(Exception JavaDoc e){
1543                    target.getToolkit().beep();
1544            // ErrorManager.getDefault().notify(e);
1545
} finally {
1546                    DocumentUtilities.setTypingModification(doc, false);
1547                    doc.atomicUnlock();
1548                }
1549            }
1550        }
1551
1552      public static void indentBlock(BaseDocument doc, int startOffset, int endOffset)
1553    throws BadLocationException JavaDoc
1554      {
1555    char [] text = doc.getChars(startOffset, endOffset-startOffset);
1556    String JavaDoc [] lines = toLines(new String JavaDoc(text));
1557
1558    doc.remove(startOffset, endOffset - startOffset);
1559    // System.out.println("Lines:\n"); // NOI18N
1560
// for (int j = 0 ; j < lines.length; j++) System.out.println(lines[j] + "<"); // NOI18N
1561

1562    int offset = startOffset;
1563    // handle the full lines
1564
for (int i = 0; i < lines.length - 1; i++) {
1565      String JavaDoc indent = getIndentString(doc, offset, lines[i]);
1566      String JavaDoc fragment = indent + lines[i].trim() + '\n';
1567      // System.out.println(fragment + "|"); // NOI18N
1568
doc.insertString(offset, fragment, null);
1569      offset += fragment.length();
1570    }
1571
1572    // the rest just paste without indenting
1573
doc.insertString(offset, lines[lines.length-1], null);
1574
1575      }
1576
1577      /** Break string to lines */
1578      private static String JavaDoc [] toLines(String JavaDoc str) {
1579    Vector JavaDoc v = new Vector JavaDoc();
1580    int p=0 , p0=0;
1581    for (; p < str.length() ; p++) {
1582      if (str.charAt(p) == '\n') {
1583        v.add(str.substring(p0, p+1));
1584        p0 = p+1;
1585      }
1586    }
1587    if (p0 < str.length()) v.add(str.substring(p0, str.length())); else v.add("");
1588
1589    return (String JavaDoc [])v.toArray(new String JavaDoc [0]);
1590      }
1591
1592      private static String JavaDoc getIndentString(BaseDocument doc, int startOffset, String JavaDoc str) {
1593    try {
1594      Formatter f = doc.getFormatter();
1595      CharArrayWriter JavaDoc cw = new CharArrayWriter JavaDoc();
1596      Writer JavaDoc w = f.createWriter(doc, startOffset, cw);
1597      w.write(str, 0, str.length());
1598      w.close();
1599      String JavaDoc out = new String JavaDoc(cw.toCharArray());
1600      int i = 0;
1601      for (; i < out.length(); i++) {
1602        if (out.charAt(i) != ' ' && out.charAt(i) != '\t') break;
1603      }
1604      // System.out.println(out+"|"); // NOI18N
1605
// System.out.println(out.substring(0,i)+"^"); // NOI18N
1606

1607      return out.substring(0, i);
1608    } catch (java.io.IOException JavaDoc e) {
1609      return "";
1610    }
1611      }
1612    }
1613
1614
1615
1616    public static class BeepAction extends LocalBaseAction {
1617
1618        static final long serialVersionUID =-4474054576633223968L;
1619
1620        public BeepAction() {
1621            super(beepAction);
1622            putValue(BaseAction.NO_KEYBINDING, Boolean.TRUE);
1623        }
1624
1625        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1626            if (target != null) {
1627                target.getToolkit().beep();
1628            }
1629        }
1630    }
1631
1632
1633    public static class UpAction extends LocalBaseAction {
1634
1635        boolean select;
1636
1637        static final long serialVersionUID =4621760742646981563L;
1638
1639        public UpAction(String JavaDoc nm, boolean select) {
1640            super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET
1641            | CLEAR_STATUS_TEXT);
1642            this.select = select;
1643        }
1644
1645        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1646            if (target != null) {
1647                try {
1648                    Caret JavaDoc caret = target.getCaret();
1649                    int dot = caret.getDot();
1650                    Point JavaDoc p = caret.getMagicCaretPosition();
1651                    if (p == null) {
1652                        Rectangle JavaDoc r = target.modelToView(dot);
1653                        if (r!=null){
1654                            p = new Point JavaDoc(r.x, r.y);
1655                            caret.setMagicCaretPosition(p);
1656                        }else{
1657                            return; // model to view failed
1658
}
1659                    }
1660                    try {
1661                        dot = Utilities.getPositionAbove(target, dot, p.x);
1662                        if (select) {
1663                            caret.moveDot(dot);
1664                        } else {
1665                            caret.setDot(dot);
1666                        }
1667                    } catch (BadLocationException JavaDoc e) {
1668                        // the position stays the same
1669
}
1670                } catch (BadLocationException JavaDoc ex) {
1671                    target.getToolkit().beep();
1672                }
1673            }
1674        }
1675    }
1676
1677    public static class DownAction extends LocalBaseAction {
1678
1679        boolean select;
1680
1681        static final long serialVersionUID =-5635702355125266822L;
1682
1683        public DownAction(String JavaDoc nm, boolean select) {
1684            super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET
1685            | CLEAR_STATUS_TEXT);
1686            this.select = select;
1687        }
1688
1689        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1690            if (target != null) {
1691                try {
1692                    Caret JavaDoc caret = target.getCaret();
1693                    int dot = caret.getDot();
1694                    Point JavaDoc p = caret.getMagicCaretPosition();
1695                    if (p == null) {
1696                        Rectangle JavaDoc r = target.modelToView(dot);
1697                        if (r!=null){
1698                            p = new Point JavaDoc(r.x, r.y);
1699                            caret.setMagicCaretPosition(p);
1700                        }else{
1701                            return; // model to view failed
1702
}
1703                    }
1704                    try {
1705                        dot = Utilities.getPositionBelow(target, dot, p.x);
1706                        if (select) {
1707                            caret.moveDot(dot);
1708                        } else {
1709                            caret.setDot(dot);
1710                        }
1711                    } catch (BadLocationException JavaDoc e) {
1712                        // position stays the same
1713
}
1714                } catch (BadLocationException JavaDoc ex) {
1715                    target.getToolkit().beep();
1716                }
1717            }
1718        }
1719    }
1720
1721    /** Go one page up */
1722    public static class PageUpAction extends LocalBaseAction {
1723
1724        boolean select;
1725
1726        static final long serialVersionUID =-3107382148581661079L;
1727
1728        public PageUpAction(String JavaDoc nm, boolean select) {
1729            super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET
1730            | CLEAR_STATUS_TEXT);
1731            this.select = select;
1732        }
1733
1734        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1735            if (target != null) {
1736                try {
1737                    Caret JavaDoc caret = target.getCaret();
1738                    BaseDocument doc = (BaseDocument)target.getDocument();
1739                    int caretOffset = caret.getDot();
1740                    Rectangle JavaDoc caretBounds = ((BaseTextUI)target.getUI()).modelToView(target, caretOffset);
1741                    if (caretBounds == null) {
1742                        return; // Cannot continue reasonably
1743
}
1744
1745                    // Retrieve caret magic position and attempt to retain
1746
// the x-coordinate information and use it
1747
// for setting of the new caret position
1748
Point JavaDoc magicCaretPosition = caret.getMagicCaretPosition();
1749                    if (magicCaretPosition == null) {
1750                        magicCaretPosition = new Point JavaDoc(caretBounds.x, caretBounds.y);
1751                    }
1752                    
1753                    Rectangle JavaDoc visibleBounds = target.getVisibleRect();
1754                    int newCaretOffset;
1755                    Rectangle JavaDoc newCaretBounds;
1756
1757                    // Check whether caret was contained in the original visible window
1758
if (visibleBounds.contains(caretBounds)) {
1759                        // Clone present view bounds
1760
Rectangle JavaDoc newVisibleBounds = new Rectangle JavaDoc(visibleBounds);
1761                        // Do viewToModel() and modelToView() with the left top corner
1762
// of the currently visible view. If that line is not fully visible
1763
// then it should be the bottom line of the previous page
1764
// (if it's fully visible then the line above it).
1765
int topLeftOffset = target.viewToModel(new Point JavaDoc(
1766                                visibleBounds.x, visibleBounds.y));
1767                        Rectangle JavaDoc topLeftLineBounds = target.modelToView(topLeftOffset);
1768
1769                        // newVisibleBounds.y will hold bottom of new view
1770
if (topLeftLineBounds.y != visibleBounds.y) {
1771                            newVisibleBounds.y = topLeftLineBounds.y + topLeftLineBounds.height;
1772                        } // Component view starts right at the line boundary
1773
// Go back by the view height
1774
newVisibleBounds.y -= visibleBounds.height;
1775
1776                        // Find the new caret bounds by using relative y position
1777
// on the original caret bounds. If the caret's new relative bounds
1778
// would be visually above the old bounds
1779
// the view should be shifted so that the relative bounds
1780
// are the same (user's eyes do not need to move).
1781
int caretRelY = caretBounds.y - visibleBounds.y;
1782                        int caretNewY = newVisibleBounds.y + caretRelY;
1783                        newCaretOffset = target.viewToModel(new Point JavaDoc(magicCaretPosition.x, caretNewY));
1784                        newCaretBounds = target.modelToView(newCaretOffset);
1785                        if (newCaretBounds.y < caretNewY) {
1786                            // Need to go one line down to retain the top line
1787
// of the present newVisibleBounds to be fully visible.
1788
// Attempt to go forward by height of caret
1789
newCaretOffset = target.viewToModel(new Point JavaDoc(magicCaretPosition.x,
1790                                    newCaretBounds.y + newCaretBounds.height));
1791                            newCaretBounds = target.modelToView(newCaretOffset);
1792                        }
1793
1794                        // Shift the new visible bounds so that the caret
1795
// does not visually move
1796
newVisibleBounds.y = newCaretBounds.y - caretRelY;
1797
1798                        // Scroll the window to the requested rectangle
1799
target.scrollRectToVisible(newVisibleBounds);
1800                        
1801                    } else { // Caret outside of originally visible window
1802
// Shift the dot by the visible bounds height
1803
Point JavaDoc newCaretPoint = new Point JavaDoc(magicCaretPosition.x,
1804                                caretBounds.y - visibleBounds.height);
1805                        newCaretOffset = target.viewToModel(newCaretPoint);
1806                        newCaretBounds = target.modelToView(newCaretOffset);
1807                    }
1808                    
1809                    if (select) {
1810                        caret.moveDot(newCaretOffset);
1811                    } else {
1812                        caret.setDot(newCaretOffset);
1813                    }
1814                    
1815                    // Update magic caret position
1816
magicCaretPosition.y = newCaretBounds.y;
1817                    caret.setMagicCaretPosition(magicCaretPosition);
1818                    
1819                } catch (BadLocationException JavaDoc ex) {
1820                    target.getToolkit().beep();
1821                }
1822            }
1823        }
1824    }
1825
1826    public static class ForwardAction extends LocalBaseAction {
1827
1828        boolean select;
1829
1830        static final long serialVersionUID =8007293230193334414L;
1831
1832        public ForwardAction(String JavaDoc nm, boolean select) {
1833            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
1834            | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
1835            this.select = select;
1836        }
1837
1838        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1839            if (target != null) {
1840                Caret JavaDoc caret = target.getCaret();
1841                try {
1842                    int pos;
1843                    if (!select && caret.isSelectionVisible())
1844                    {
1845                        pos = target.getSelectionEnd();
1846                        if (pos != caret.getDot())
1847                            pos--;
1848                    }
1849                    else
1850                        pos = caret.getDot();
1851                    int dot = target.getUI().getNextVisualPositionFrom(target,
1852                              pos, Position.Bias.Forward, SwingConstants.EAST, null);
1853                    if (select) {
1854                        caret.moveDot(dot);
1855                    } else {
1856                        caret.setDot(dot);
1857                    }
1858                } catch (BadLocationException JavaDoc ex) {
1859                    target.getToolkit().beep();
1860                }
1861            }
1862        }
1863    }
1864
1865    /** Go one page down */
1866    public static class PageDownAction extends LocalBaseAction {
1867
1868        boolean select;
1869
1870        static final long serialVersionUID =8942534850985048862L;
1871
1872        public PageDownAction(String JavaDoc nm, boolean select) {
1873            super(nm, ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET
1874            | CLEAR_STATUS_TEXT);
1875            this.select = select;
1876        }
1877
1878        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1879            if (target != null) {
1880                try {
1881                    Caret JavaDoc caret = target.getCaret();
1882                    BaseDocument doc = (BaseDocument)target.getDocument();
1883                    int caretOffset = caret.getDot();
1884                    Rectangle JavaDoc caretBounds = ((BaseTextUI)target.getUI()).modelToView(target, caretOffset);
1885                    if (caretBounds == null) {
1886                        return; // Cannot continue reasonably
1887
}
1888
1889                    // Retrieve caret magic position and attempt to retain
1890
// the x-coordinate information and use it
1891
// for setting of the new caret position
1892
Point JavaDoc magicCaretPosition = caret.getMagicCaretPosition();
1893                    if (magicCaretPosition == null) {
1894                        magicCaretPosition = new Point JavaDoc(caretBounds.x, caretBounds.y);
1895                    }
1896                    
1897                    Rectangle JavaDoc visibleBounds = target.getVisibleRect();
1898                    int newCaretOffset;
1899                    Rectangle JavaDoc newCaretBounds;
1900
1901                    // Check whether caret was contained in the original visible window
1902
if (visibleBounds.contains(caretBounds)) {
1903                        // Clone present view bounds
1904
Rectangle JavaDoc newVisibleBounds = new Rectangle JavaDoc(visibleBounds);
1905                        // Do viewToModel() and modelToView() with the left bottom corner
1906
// of the currently visible view.
1907
// That line should be the top line of the next page.
1908
int bottomLeftOffset = target.viewToModel(new Point JavaDoc(
1909                                visibleBounds.x, visibleBounds.y + visibleBounds.height));
1910                        Rectangle JavaDoc bottomLeftLineBounds = target.modelToView(bottomLeftOffset);
1911
1912                        // newVisibleBounds.y will hold bottom of new view
1913
newVisibleBounds.y = bottomLeftLineBounds.y;
1914
1915                        // Find the new caret bounds by using relative y position
1916
// on the original caret bounds. If the caret's new relative bounds
1917
// would be visually below the old bounds
1918
// the view should be shifted so that the relative bounds
1919
// are the same (user's eyes do not need to move).
1920
int caretRelY = caretBounds.y - visibleBounds.y;
1921                        int caretNewY = newVisibleBounds.y + caretRelY;
1922                        newCaretOffset = target.viewToModel(new Point JavaDoc(magicCaretPosition.x, caretNewY));
1923                        newCaretBounds = target.modelToView(newCaretOffset);
1924                        if (newCaretBounds.y > caretNewY) {
1925                            // Need to go one line above to retain the top line
1926
// of the present newVisibleBounds to be fully visible.
1927
// Attempt to go up by height of caret.
1928
newCaretOffset = target.viewToModel(new Point JavaDoc(magicCaretPosition.x,
1929                                    newCaretBounds.y - newCaretBounds.height));
1930                            newCaretBounds = target.modelToView(newCaretOffset);
1931                        }
1932
1933                        // Shift the new visible bounds so that the caret
1934
// does not visually move
1935
newVisibleBounds.y = newCaretBounds.y - caretRelY;
1936
1937                        // Scroll the window to the requested rectangle
1938
target.scrollRectToVisible(newVisibleBounds);
1939                        
1940                    } else { // Caret outside of originally visible window
1941
// Shift the dot by the visible bounds height
1942
Point JavaDoc newCaretPoint = new Point JavaDoc(magicCaretPosition.x,
1943                                caretBounds.y + visibleBounds.height);
1944                        newCaretOffset = target.viewToModel(newCaretPoint);
1945                        newCaretBounds = target.modelToView(newCaretOffset);
1946                    }
1947                    
1948                    if (select) {
1949                        caret.moveDot(newCaretOffset);
1950                    } else {
1951                        caret.setDot(newCaretOffset);
1952                    }
1953                    
1954                    // Update magic caret position
1955
magicCaretPosition.y = newCaretBounds.y;
1956                    caret.setMagicCaretPosition(magicCaretPosition);
1957                    
1958                } catch (BadLocationException JavaDoc ex) {
1959                    target.getToolkit().beep();
1960                }
1961            }
1962        }
1963    }
1964
1965    public static class BackwardAction extends LocalBaseAction {
1966
1967        boolean select;
1968
1969        static final long serialVersionUID =-3048379822817847356L;
1970
1971        public BackwardAction(String JavaDoc nm, boolean select) {
1972            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
1973                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
1974            this.select = select;
1975        }
1976
1977        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
1978            if (target != null) {
1979                Caret JavaDoc caret = target.getCaret();
1980                try {
1981                    int pos;
1982                    if (!select && caret.isSelectionVisible())
1983                    {
1984                        pos = target.getSelectionStart();
1985                        if (pos != caret.getDot())
1986                            pos++;
1987                    }
1988                    else
1989                        pos = caret.getDot();
1990                    int dot = target.getUI().getNextVisualPositionFrom(target,
1991                              pos, Position.Bias.Backward, SwingConstants.WEST, null);
1992                    if (select) {
1993                        caret.moveDot(dot);
1994                    } else {
1995                        caret.setDot(dot);
1996                    }
1997                } catch (BadLocationException JavaDoc ex) {
1998                    target.getToolkit().beep();
1999                }
2000            }
2001        }
2002    }
2003
2004    public static class BeginLineAction extends LocalBaseAction {
2005
2006        protected boolean select;
2007
2008        /** Whether the action should go to the begining of
2009         * the text on the line or to the first column on the line*/

2010        boolean homeKeyColumnOne;
2011
2012        static final long serialVersionUID =3269462923524077779L;
2013
2014        public BeginLineAction(String JavaDoc nm, boolean select) {
2015            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
2016                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
2017            this.select = select;
2018            homeKeyColumnOne = false;
2019        }
2020
2021        public BeginLineAction(String JavaDoc nm, boolean select, boolean columnOne) {
2022            this(nm, select);
2023            homeKeyColumnOne = columnOne;
2024        }
2025
2026        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
2027            if (target != null) {
2028                Caret JavaDoc caret = target.getCaret();
2029                BaseDocument doc = (BaseDocument)target.getDocument();
2030                try {
2031                    int dot = caret.getDot();
2032                    int lineStartPos = Utilities.getRowStart(target, dot);
2033                    if (homeKeyColumnOne) { // to first column
2034
dot = lineStartPos;
2035                    } else { // either to line start or text start
2036
int textStartPos = Utilities.getRowFirstNonWhite(doc, lineStartPos);
2037                        if (textStartPos < 0) { // no text on the line
2038
textStartPos = Utilities.getRowEnd(target, lineStartPos);
2039                        }
2040                        if (dot == lineStartPos) { // go to the text start pos
2041
dot = textStartPos;
2042                        } else if (dot <= textStartPos) {
2043                            dot = lineStartPos;
2044                        } else {
2045                            dot = textStartPos;
2046                        }
2047                    }
2048                    if (select) {
2049                        caret.moveDot(dot);
2050                    } else {
2051                        caret.setDot(dot);
2052                    }
2053                } catch (BadLocationException JavaDoc e) {
2054                    target.getToolkit().beep();
2055                }
2056            }
2057        }
2058    }
2059
2060    public static class EndLineAction extends LocalBaseAction {
2061
2062        protected boolean select;
2063
2064        static final long serialVersionUID =5216077634055190170L;
2065
2066        public EndLineAction(String JavaDoc nm, boolean select) {
2067            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
2068                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
2069            this.select = select;
2070        }
2071
2072        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
2073            if (target != null) {
2074                Caret JavaDoc caret = target.getCaret();
2075                try {
2076                    int dot = Utilities.getRowEnd(target, caret.getDot());
2077                    if (select) {
2078                        caret.moveDot(dot);
2079                    } else {
2080                        caret.setDot(dot);
2081                    }
2082                    // now move the magic caret position far to the right
2083
Rectangle JavaDoc r = target.modelToView(dot);
2084                    if (r!=null){
2085                        Point JavaDoc p = new Point JavaDoc(MAGIC_POSITION_MAX, r.y);
2086                        caret.setMagicCaretPosition(p);
2087                    }
2088                } catch (BadLocationException JavaDoc e) {
2089                    e.printStackTrace();
2090                    target.getToolkit().beep();
2091                }
2092            }
2093        }
2094    }
2095
2096    public static class BeginAction extends LocalBaseAction {
2097
2098        boolean select;
2099
2100        static final long serialVersionUID =3463563396210234361L;
2101
2102        public BeginAction(String JavaDoc nm, boolean select) {
2103            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
2104                  | WORD_MATCH_RESET | SAVE_POSITION | CLEAR_STATUS_TEXT);
2105            this.select = select;
2106        }
2107
2108        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
2109            if (target != null) {
2110                Caret JavaDoc caret = target.getCaret();
2111                int dot = 0; // begin of document
2112
if (select) {
2113                    caret.moveDot(dot);
2114                } else {
2115                    caret.setDot(dot);
2116                }
2117            }
2118        }
2119    }
2120
2121    public static class EndAction extends LocalBaseAction {
2122
2123        boolean select;
2124
2125        static final long serialVersionUID =8547506353130203657L;
2126
2127        public EndAction(String JavaDoc nm, boolean select) {
2128            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
2129                  | WORD_MATCH_RESET | SAVE_POSITION | CLEAR_STATUS_TEXT);
2130            this.select = select;
2131        }
2132
2133        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
2134            if (target != null) {
2135                Caret JavaDoc caret = target.getCaret();
2136                int dot = target.getDocument().getLength(); // end of document
2137
if (select) {
2138                    caret.moveDot(dot);
2139                } else {
2140                    caret.setDot(dot);
2141                }
2142            }
2143        }
2144    }
2145
2146    public static class NextWordAction extends LocalBaseAction {
2147
2148        boolean select;
2149
2150        static final long serialVersionUID =-5909906947175434032L;
2151
2152        public NextWordAction(String JavaDoc nm, boolean select) {
2153            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
2154                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
2155            this.select = select;
2156        }
2157
2158        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
2159            if (target != null) {
2160                Caret JavaDoc caret = target.getCaret();
2161                try {
2162                    int dotPos = caret.getDot();
2163                    dotPos = Utilities.getNextWord(target, dotPos);
2164                    if (caret instanceof BaseCaret){
2165                        BaseCaret bCaret = (BaseCaret) caret;
2166                        if (select) {
2167                            bCaret.moveDot(dotPos);
2168                        } else {
2169                            bCaret.setDot(dotPos, false);
2170                        }
2171                    }else {
2172                        if (select) {
2173                            caret.moveDot(dotPos);
2174                        } else {
2175                            caret.setDot(dotPos);
2176                        }
2177                    }
2178                } catch (BadLocationException JavaDoc ex) {
2179                    target.getToolkit().beep();
2180                }
2181            }
2182        }
2183    }
2184
2185    public static class PreviousWordAction extends LocalBaseAction {
2186
2187        boolean select;
2188
2189        static final long serialVersionUID =-5465143382669785799L;
2190
2191        public PreviousWordAction(String JavaDoc nm, boolean select) {
2192            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
2193                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
2194            this.select = select;
2195        }
2196
2197        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
2198            if (target != null) {
2199                Caret JavaDoc caret = target.getCaret();
2200                try {
2201                    int dot = Utilities.getPreviousWord(target, caret.getDot());
2202                    if (caret instanceof BaseCaret){
2203                        BaseCaret bCaret = (BaseCaret) caret;
2204                        if (select) {
2205                            bCaret.moveDot(dot);
2206                        } else {
2207                            bCaret.setDot(dot, false);
2208                        }
2209                    }else {
2210                        if (select) {
2211                            caret.moveDot(dot);
2212                        } else {
2213                            caret.setDot(dot);
2214                        }
2215                    }
2216                } catch (BadLocationException JavaDoc ex) {
2217                    target.getToolkit().beep();
2218                }
2219            }
2220        }
2221    }
2222
2223    public static class BeginWordAction extends LocalBaseAction {
2224
2225        boolean select;
2226
2227        static final long serialVersionUID =3991338381212491110L;
2228
2229        public BeginWordAction(String JavaDoc nm, boolean select) {
2230            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
2231                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
2232            this.select = select;
2233        }
2234
2235        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
2236            if (target != null) {
2237                Caret JavaDoc caret = target.getCaret();
2238                try {
2239                    int dot = Utilities.getWordStart(target, caret.getDot());
2240                    if (select) {
2241                        caret.moveDot(dot);
2242                    } else {
2243                        caret.setDot(dot);
2244                    }
2245                } catch (BadLocationException JavaDoc ex) {
2246                    target.getToolkit().beep();
2247                }
2248            }
2249        }
2250    }
2251
2252    public static class EndWordAction extends LocalBaseAction {
2253
2254        boolean select;
2255
2256        static final long serialVersionUID =3812523676620144633L;
2257
2258        public EndWordAction(String JavaDoc nm, boolean select) {
2259            super(nm, MAGIC_POSITION_RESET | ABBREV_RESET | UNDO_MERGE_RESET
2260                  | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
2261            this.select = select;
2262        }
2263
2264        public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
2265            if (target != null) {
2266                Caret JavaDoc caret = target.getCaret();
2267                try {
2268                    int dot = Utilities.getWordEnd(target, caret.getDot());
2269                    if (select) {
2270                        caret.moveDot(dot);
2271                    } else {
2272                        caret.setDot(dot);
2273                    }
2274                } catch (BadLocationException JavaDoc ex) {
2275                    target.getToolkit().beep();
2276                }
2277            }
2278        }
2279    }
2280
2281    /** Select word around caret */
2282    public static class SelectWordAction extends KitCompoundAction {
2283
2284        static final long serialVersionUID =7678848538073016357L;
2285
2286        public SelectWordAction() {
2287            super(selectWordAction,
2288                  new String JavaDoc[] {
2289                      beginWordAction,
2290                      selectionEndWordAction
2291                  }
2292                 );
2293        }
2294
2295    }
2296
2297    /** Select line around caret */
2298    public static class SelectLineAction extends KitCompoundAction {
2299
2300        static final long serialVersionUID =-7407681863035740281L;
2301
2302        public SelectLineAction() {
2303            super(selectLineAction,
2304                  new String JavaDoc[] {
2305                      lineFirstColumnAction,
2306                      selectionEndLineAction
2307                      //selectionForwardAction //#41371
2308
}
2309                 );
2310        }
2311
2312    }
2313
2314    /** Select text of whole document */
2315    public static class SelectAllAction extends KitCompoundAction {
2316
2317        static final long serialVersionUID =-3502499718130556524L;
2318
2319        public SelectAllAction() {
2320            super(selectAllAction,
2321                  new String JavaDoc[] {
2322                      beginAction,
2323                      selectionEndAction
2324                  }
2325                 );
2326        }
2327
2328    }
2329    
2330    public static class RemoveTrailingSpacesAction extends LocalBaseAction {
2331        
2332        public RemoveTrailingSpacesAction() {
2333            super(removeTrailingSpacesAction);
2334        }
2335
2336        protected boolean asynchonous() {
2337            return true;
2338        }
2339        
2340        public void actionPerformed(ActionEvent JavaDoc evt, final JTextComponent JavaDoc target) {
2341            if (target != null) {
2342                final BaseDocument doc = (BaseDocument)target.getDocument();
2343                doc.runAtomic(new Runnable JavaDoc() {
2344                    public void run() {
2345                        try {
2346                            Element JavaDoc lineRootElem = doc.getDefaultRootElement();
2347                            int count = lineRootElem.getElementCount();
2348                            for (int x = 0; x < count; x++) {
2349                                Element JavaDoc elem = lineRootElem.getElement(x);
2350                                int start = elem.getStartOffset();
2351                                int end = elem.getEndOffset();
2352                                CharSequence JavaDoc line = DocumentUtilities.getText(doc, start, end - start);
2353                                int endIndex = line.length() - 1;
2354                                if (endIndex >= 0 && line.charAt(endIndex) == '\n') {
2355                                    endIndex--;
2356                                    if (endIndex >= 0 && line.charAt(endIndex) == '\r') {
2357                                        endIndex--;
2358                                    }
2359                                }
2360                                int index = endIndex;
2361                                while (index >= 0 && Character.isWhitespace(line.charAt(index)) && line.charAt(index) != '\n') {
2362                                    index--;
2363                                }
2364                                if (index < endIndex) {
2365                                    doc.remove(start + index + 1, endIndex - index);
2366                                }
2367                            } // for
2368
StatusDisplayer.getDefault().setStatusText(NbBundle.getMessage(BaseKit.class, "TrailingSpacesWereRemoved_Lbl")); // NOI18N
2369
} catch (BadLocationException JavaDoc e) {
2370                            e.printStackTrace();
2371                            target.getToolkit().beep();
2372                        }
2373                    }
2374                });
2375            }
2376        }
2377    }
2378
2379    private static final class DefaultSyntax extends Syntax {
2380
2381        private static final int ISI_TEXT = 0;
2382
2383        public DefaultSyntax() {
2384            tokenContextPath = DefaultSyntaxTokenContext.CONTEXT.getContextPath();
2385        }
2386
2387        protected TokenID parseToken() {
2388            // The main loop that reads characters one by one follows
2389
while (offset < stopOffset) {
2390                char ch = buffer[offset]; // get the current character
2391

2392                switch (state) { // switch by the current internal state
2393
case INIT:
2394                    switch (ch) {
2395                    case '\n':
2396                        offset++;
2397                        return DefaultSyntaxTokenContext.EOL;
2398                    default:
2399                        state = ISI_TEXT;
2400                        break;
2401                    }
2402                    break;
2403
2404                case ISI_TEXT:
2405                    switch (ch) {
2406                    case '\n':
2407                        state = INIT;
2408                        return DefaultSyntaxTokenContext.TEXT;
2409                    }
2410                    break;
2411
2412                } // end of switch(state)
2413

2414                offset++; // move to the next char
2415
}
2416
2417            switch (state) {
2418            case ISI_TEXT:
2419                state = INIT;
2420                return DefaultSyntaxTokenContext.TEXT;
2421            }
2422
2423            // need to continue on another buffer
2424
return null;
2425        }
2426    } // End of DefaultSyntax class
2427

2428    private static final class DefaultSyntaxTokenContext extends TokenContext {
2429
2430        // Numeric-ids for token-ids
2431
public static final int TEXT_ID = 1;
2432        public static final int EOL_ID = 2;
2433
2434        public static final BaseTokenID TEXT = new BaseTokenID("text", TEXT_ID); // NOI18N
2435
public static final BaseImageTokenID EOL = new BaseImageTokenID("EOL", EOL_ID, "\n"); // NOI18N
2436

2437        // Context declaration
2438
public static final DefaultSyntaxTokenContext CONTEXT = new DefaultSyntaxTokenContext();
2439
2440        private DefaultSyntaxTokenContext() {
2441            super("defaultSyntax-token-"); // NOI18N
2442

2443            try {
2444                addDeclaredTokenIDs();
2445            } catch (Exception JavaDoc e) {
2446                LOG.log(Level.WARNING, "Can't load token IDs", e); //NOI18N
2447
}
2448        }
2449    } // End of DefaultSyntaxTokenContext class
2450
}
2451
Popular Tags