KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > gjt > sp > jedit > ActionSet


1 /*
2  * ActionSet.java - A set of actions
3  * :tabSize=8:indentSize=8:noTabs=false:
4  * :folding=explicit:collapseFolds=1:
5  *
6  * Copyright (C) 2001, 2003 Slava Pestov
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */

22
23 package org.gjt.sp.jedit;
24
25 import java.io.*;
26 import java.net.URL JavaDoc;
27 import java.util.*;
28
29 import org.gjt.sp.jedit.gui.InputHandler;
30 import org.gjt.sp.util.Log;
31 import org.gjt.sp.util.XMLUtilities;
32
33 /**
34  * A set of actions, either loaded from an XML file, or constructed at runtime
35  * by a plugin. <p>
36  *
37  * <h3>Action sets loaded from XML files</h3>
38  *
39  * Action sets are read from these files inside the plugin JAR:
40  * <ul>
41  * <li><code>actions.xml</code> - actions made available for use in jEdit views,
42  * including the view's <b>Plugins</b> menu, the tool bar, etc.</li>
43  * <li><code>browser.actions.xml</code> - actions for the file system browser's
44  * <b>Plugins</b> menu.</li>
45  * </ul>
46  *
47  * An action definition file has the following form:
48  *
49  * <pre>&lt;?xml version="1.0"?&gt;
50  *&lt;!DOCTYPE ACTIONS SYSTEM "actions.dtd"&gt;
51  *&lt;ACTIONS&gt;
52  * &lt;ACTION NAME="some-action"&gt;
53  * &lt;CODE&gt;
54  * // BeanShell code evaluated when the action is invoked
55  * &lt;/CODE&gt;
56  * &lt;/ACTION&gt;
57  * &lt;ACTION NAME="some-toggle-action"&gt;
58  * &lt;CODE&gt;
59  * // BeanShell code evaluated when the action is invoked
60  * &lt;/CODE&gt;
61  * &lt;IS_SELECTED&gt;
62  * // BeanShell code that should evaluate to true or false
63  * &lt;/IS_SELECTED&gt;
64  * &lt;/ACTION&gt;
65  *&lt;/ACTIONS&gt;</pre>
66  *
67  * The following elements are valid:
68  *
69  * <ul>
70  * <li>
71  * <code>ACTIONS</code> is the top-level element and refers
72  * to the set of actions used by the plugin.
73  * </li>
74  * <li>
75  * An <code>ACTION</code> contains the data for a particular action.
76  * It has three attributes: a required <code>NAME</code>;
77  * an optional <code>NO_REPEAT</code>, which is a flag
78  * indicating whether the action should not be repeated with the
79  * <b>C+ENTER</b> command; and an optional
80  * <code>NO_RECORD</code> which is a a flag indicating whether the
81  * action should be recorded if it is invoked while the user is recording a
82  * macro. The two flag attributes
83  * can have two possible values, "TRUE" or
84  * "FALSE". In both cases, "FALSE" is the
85  * default if the attribute is not specified.
86  * </li>
87  * <li>
88  * An <code>ACTION</code> can have two child elements
89  * within it: a required <code>CODE</code> element which
90  * specifies the
91  * BeanShell code that will be executed when the action is invoked,
92  * and an optional <code>IS_SELECTED</code> element, used for
93  * checkbox
94  * menu items. The <code>IS_SELECTED</code> element contains
95  * BeanShell code that returns a boolean flag that will
96  * determine the state of the checkbox.
97  * </li>
98  * </ul>
99  *
100  * Each action must have a property <code><i>name</i>.label</code> containing
101  * the action's menu item label.
102  *
103  * <h3>View actions</h3>
104  *
105  * Actions defined in <code>actions.xml</code> can be added to the view's
106  * <b>Plugins</b> menu; see {@link EditPlugin}.
107  * The action code may use any standard predefined
108  * BeanShell variable; see {@link BeanShell}.
109  *
110  * <h3>File system browser actions</h3>
111  *
112  * Actions defined in <code>actions.xml</code> can be added to the file
113  * system browser's <b>Plugins</b> menu; see {@link EditPlugin}.
114  * The action code may use any standard predefined
115  * BeanShell variable, in addition to a variable <code>browser</code> which
116  * contains a reference to the current
117  * {@link org.gjt.sp.jedit.browser.VFSBrowser} instance.<p>
118  *
119  * File system browser actions should not define
120  * <code>&lt;IS_SELECTED&gt;</code> blocks.
121  *
122  * <h3>Custom action sets</h3>
123  *
124  * Call {@link jEdit#addActionSet(ActionSet)} to add a custom action set to
125  * jEdit's action context. You must also call {@link #initKeyBindings()} for new
126  * action sets. Don't forget to call {@link jEdit#removeActionSet(ActionSet)}
127  * before your plugin is unloaded, too.
128  *
129  * @see jEdit#getActionContext()
130  * @see org.gjt.sp.jedit.browser.VFSBrowser#getActionContext()
131  * @see ActionContext#getActionNames()
132  * @see ActionContext#getAction(String)
133  * @see jEdit#addActionSet(ActionSet)
134  * @see jEdit#removeActionSet(ActionSet)
135  * @see PluginJAR#getActionSet()
136  * @see BeanShell
137  * @see View
138  *
139  * @author Slava Pestov
140  * @author John Gellene (API documentation)
141  * @version $Id: ActionSet.java 6884 2006-09-06 02:38:55Z ezust $
142  * @since jEdit 4.0pre1
143  */

144 public class ActionSet
145 {
146     //{{{ ActionSet constructor
147
/**
148      * Creates a new action set.
149      * @since jEdit 4.0pre1
150      */

151     public ActionSet()
152     {
153         actions = new Hashtable();
154         loaded = true;
155         label = "<no label set; plugin bug>";
156     } //}}}
157

158     //{{{ ActionSet constructor
159
/**
160      * Creates a new action set.
161      * @param plugin The plugin
162      * @param cachedActionNames The list of cached action names
163      * @param cachedActionToggleFlags The list of cached action toggle flags
164      * @param uri The actions.xml URI
165      * @since jEdit 4.2pre2
166      */

167     public ActionSet(PluginJAR plugin, String JavaDoc[] cachedActionNames,
168         boolean[] cachedActionToggleFlags, URL JavaDoc uri)
169     {
170         this();
171         this.plugin = plugin;
172         this.uri = uri;
173         if(cachedActionNames != null)
174         {
175             for(int i = 0; i < cachedActionNames.length; i++)
176             {
177                 actions.put(cachedActionNames[i],placeholder);
178                 jEdit.setTemporaryProperty(cachedActionNames[i]
179                     + ".toggle",cachedActionToggleFlags[i]
180                     ? "true" : "false");
181             }
182         }
183         loaded = false;
184     } //}}}
185

186     //{{{ ActionSet constructor
187
/**
188      * Creates a new action set.
189      * @param label The label, shown in the shortcuts option pane
190      * @since jEdit 4.0pre1
191      */

192     public ActionSet(String JavaDoc label)
193     {
194         this();
195         setLabel(label);
196     } //}}}
197

198     //{{{ getLabel() method
199
/**
200      * Return the action source label.
201      * @since jEdit 4.0pre1
202      */

203     public String JavaDoc getLabel()
204     {
205         return label;
206     } //}}}
207

208     //{{{ setLabel() method
209
/**
210      * Sets the action source label.
211      * @param label The label
212      * @since jEdit 4.0pre1
213      */

214     public void setLabel(String JavaDoc label)
215     {
216         if(label == null)
217             throw new NullPointerException JavaDoc();
218         this.label = label;
219     } //}}}
220

221     //{{{ getPluginJAR() method
222
/**
223      * Return the plugin this action set was loaded from, or null.
224      * @since jEdit 4.2pre13
225      */

226     public PluginJAR getPluginJAR()
227     {
228         return plugin;
229     } //}}}
230

231     //{{{ addAction() method
232
/**
233      * Adds an action to the action set.
234      * @param action The action
235      * @since jEdit 4.0pre1
236      */

237     public void addAction(EditAction action)
238     {
239         actions.put(action.getName(),action);
240         if(context != null)
241         {
242             context.actionNames = null;
243             context.actionHash.put(action.getName(),this);
244         }
245     } //}}}
246

247     //{{{ removeAction() method
248
/**
249      * Removes an action from the action set.
250      * @param name The action name
251      * @since jEdit 4.0pre1
252      */

253     public void removeAction(String JavaDoc name)
254     {
255         actions.remove(name);
256         if(context != null)
257         {
258             context.actionNames = null;
259             context.actionHash.remove(name);
260         }
261     } //}}}
262

263     //{{{ removeAllActions() method
264
/**
265      * Removes all actions from the action set.
266      * @since jEdit 4.0pre1
267      */

268     public void removeAllActions()
269     {
270         if(context != null)
271         {
272             context.actionNames = null;
273             String JavaDoc[] actions = getActionNames();
274             for(int i = 0; i < actions.length; i++)
275             {
276                 context.actionHash.remove(actions[i]);
277             }
278         }
279         this.actions.clear();
280     } //}}}
281

282     //{{{ getAction() method
283
/**
284      * Returns an action with the specified name.<p>
285      *
286      * <b>Deferred loading:</b> this will load the action set if necessary.
287      *
288      * @param name The action name
289      * @since jEdit 4.0pre1
290      */

291     public EditAction getAction(String JavaDoc name)
292     {
293         Object JavaDoc obj = actions.get(name);
294         if(obj == placeholder)
295         {
296             load();
297             obj = actions.get(name);
298             if(obj == placeholder)
299             {
300                 Log.log(Log.WARNING,this,"Outdated cache");
301                 obj = null;
302             }
303         }
304
305         return (EditAction)obj;
306     } //}}}
307

308     //{{{ getActionCount() method
309
/**
310      * Returns the number of actions in the set.
311      * @since jEdit 4.0pre1
312      */

313     public int getActionCount()
314     {
315         return actions.size();
316     } //}}}
317

318     //{{{ getActionNames() method
319
/**
320      * Returns an array of all action names in this action set.
321      * @since jEdit 4.2pre1
322      */

323     public String JavaDoc[] getActionNames()
324     {
325         String JavaDoc[] retVal = new String JavaDoc[actions.size()];
326         Enumeration e = actions.keys();
327         int i = 0;
328         while(e.hasMoreElements())
329         {
330             retVal[i++] = (String JavaDoc)e.nextElement();
331         }
332         return retVal;
333     } //}}}
334

335     //{{{ getCacheableActionNames() method
336
/**
337      * Returns an array of all action names in this action set that should
338      * be cached; namely, <code>BeanShellAction</code>s.
339      * @since jEdit 4.2pre1
340      */

341     public String JavaDoc[] getCacheableActionNames()
342     {
343         LinkedList retVal = new LinkedList();
344         Enumeration e = actions.elements();
345         while(e.hasMoreElements())
346         {
347             Object JavaDoc obj = e.nextElement();
348             if(obj == placeholder)
349             {
350                 // ??? this should only be called with
351
// fully loaded action set
352
Log.log(Log.WARNING,this,"Action set not up "
353                     + "to date");
354             }
355             else if(obj instanceof BeanShellAction)
356                 retVal.add(((BeanShellAction)obj).getName());
357         }
358         return (String JavaDoc[])retVal.toArray(new String JavaDoc[retVal.size()]);
359     } //}}}
360

361     //{{{ getActions() method
362
/**
363      * Returns an array of all actions in this action set.<p>
364      *
365      * <b>Deferred loading:</b> this will load the action set if necessary.
366      *
367      * @since jEdit 4.0pre1
368      */

369     public EditAction[] getActions()
370     {
371         load();
372
373         EditAction[] retVal = new EditAction[actions.size()];
374         Enumeration e = actions.elements();
375         int i = 0;
376         while(e.hasMoreElements())
377         {
378             retVal[i++] = (EditAction)e.nextElement();
379         }
380         return retVal;
381     } //}}}
382

383     //{{{ contains() method
384
/**
385      * Returns if this action set contains the specified action.
386      * @param action The action
387      * @since jEdit 4.2pre1
388      */

389     public boolean contains(String JavaDoc action)
390     {
391         boolean retval = actions.containsKey(action);
392         return retval;
393 // return actions.containsKey(action);
394
} //}}}
395

396     //{{{ size() method
397
/**
398      * Returns the number of actions in this action set.
399      * @since jEdit 4.2pre2
400      */

401     public int size()
402     {
403         return actions.size();
404     } //}}}
405

406     //{{{ toString() method
407
public String JavaDoc toString()
408     {
409         return label;
410     } //}}}
411

412     //{{{ initKeyBindings() method
413
/**
414      * Initializes the action set's key bindings.
415      * jEdit calls this method for all registered action sets when the
416      * user changes key bindings in the <b>Global Options</b> dialog box.<p>
417      *
418      * Note if your plugin adds a custom action set to jEdit's collection,
419      * it must also call this method on the action set after adding it.
420      *
421      * @since jEdit 4.2pre1
422      */

423     public void initKeyBindings()
424     {
425         InputHandler inputHandler = jEdit.getInputHandler();
426
427         Iterator iter = actions.entrySet().iterator();
428         while(iter.hasNext())
429         {
430             Map.Entry entry = (Map.Entry)iter.next();
431             String JavaDoc name = (String JavaDoc)entry.getKey();
432
433             String JavaDoc shortcut1 = jEdit.getProperty(name + ".shortcut");
434             if(shortcut1 != null)
435                 inputHandler.addKeyBinding(shortcut1,name);
436
437             String JavaDoc shortcut2 = jEdit.getProperty(name + ".shortcut2");
438             if(shortcut2 != null)
439                 inputHandler.addKeyBinding(shortcut2,name);
440         }
441     } //}}}
442

443     //{{{ load() method
444
/**
445      * Forces the action set to be loaded. Plugins and macros should not
446      * call this method.
447      * @since jEdit 4.2pre1
448      */

449     public void load()
450     {
451         if(loaded)
452             return;
453
454         loaded = true;
455         //actions.clear();
456

457         Reader stream = null;
458
459         try
460         {
461             Log.log(Log.DEBUG,this,"Loading actions from " + uri);
462             ActionListHandler ah = new ActionListHandler(uri.toString(),this);
463             XMLUtilities.parseXML(uri.openStream(), ah);
464         }
465         catch(IOException e)
466         {
467             Log.log(Log.ERROR,uri,e);
468         }
469     } //}}}
470

471     //{{{ Package-private members
472
ActionContext context;
473
474     //{{{ getActionNames() method
475
void getActionNames(List vec)
476     {
477         Enumeration e = actions.keys();
478         while(e.hasMoreElements())
479             vec.add(e.nextElement());
480     } //}}}
481

482     //}}}
483

484     //{{{ Private members
485
private String JavaDoc label;
486     private Hashtable actions;
487     private PluginJAR plugin;
488     private URL JavaDoc uri;
489     private boolean loaded;
490
491     private static final Object JavaDoc placeholder = new Object JavaDoc();
492
493     //}}}
494
}
495
Popular Tags