1 /**
  2  * Create an Action instance.
  3  * @class
  4  * An action encapsulates the functionality of a menu item, by making it
  5  * possible to register an event listener on the <code>action</code> event
  6  * which is triggered when the menu item is clicked.
  7  * Actions are typically created by invoking <code>actions.createAction()</code>-
  8  * @constructor
  9  * @param {String} name name of the action.
 10  * @param {String} accelerator the keyboard shortcut of the action.
 11  * @example
 12  * var hello = actions.createAction('Hello World', 'shortcut shift F5');
 13  * actions.addAction(hello,'file');
 14  * hello.once('action', function() {
 15  *   actions.removeAction(hello, 'file');
 16  * });
 17  */
 18 
 19 function Action(name, accelerator) {
 20   // invoke the superclass constructor
 21   EventEmitter.call(this);
 22   /**
 23    * Name of the action.
 24    * @ignore
 25    * @type String
 26    */
 27   this.name = name;
 28 
 29   this.emitterAction = new com.escenic.studio.core.script.EmitterAction(this);
 30 
 31   /**
 32    * Holds the action instance of <code>com.escenic.studio.core.script.ScriptAction</code>.
 33    * @ignore
 34    */
 35   var action = new com.escenic.studio.core.script.ScriptAction(this.emitterAction);
 36 
 37   /**
 38    * Sets the name of the action.
 39    * @param {String} name name of the action.
 40    * @ignore
 41    */
 42   action.setName(this.name);
 43   if (accelerator != undefined) {
 44     action.setAccelerator(accelerator);
 45   }
 46 
 47   var instance = this;
 48 
 49   /**
 50    * Returns the <code>com.escenic.studio.core.script.ScriptAction</code> instance.
 51    * @returns the swing <code>com.escenic.studio.core.script.ScriptAction<code>.
 52    * @ignore
 53    */
 54   this.getSwingAction = function() {
 55     return action;
 56     // todo: get rid of this method in the public facing API!
 57   };
 58 
 59   /** 
 60    * Returns the name of the action.
 61    */
 62   this.getName = function() {
 63     return action.getName();
 64   };
 65 
 66   /**
 67    * Changes the name of the action. This will result in the UI changing
 68    * to reflect the new name of the action.
 69    */
 70   this.setName = function(newName) {
 71     action.setName(newName);
 72   }
 73 
 74   /**
 75    * Returns the desired accelerator for the action, or
 76    * <code>undefined</code> if none has been defined.
 77    * Please note that if the existing accelerator is invalid
 78    * this method will still return the "invalid" accelerator
 79    * even though it's not used in the actual user interface.
 80    */
 81   this.getAccelerator = function() {
 82     return accelerator;
 83   }
 84 
 85   /**
 86    * Changes the accelerator for an action.  If an invalid (or empty)
 87    * accelerator is specified, the action will have no accelerator.
 88    * @param {String} accelerator the new accelerator, e.g. "shortcut F11"
 89    */
 90   this.setAccelerator = function(accelerator) {
 91     if (accelerator != undefined) {
 92       action.setAccelerator(accelerator);
 93       this.accelerator = accelerator;
 94     }
 95   }
 96 
 97 
 98   /**
 99    * Sets or retrieves the enabled state of the action. When an action is enabled
100    * any menu item associated with the action are possible to click on.
101    * When an action is disabled, the menu items can not be clicked on and will appear
102    * disabled to the user.
103    * <p>
104    * This method can also be used to see the current enable/disable state. When called
105    * with no parameters it will just return the current enable/disable state.
106    *
107    * @param {Boolean} value true to enable this <code>Action</code>, false to disable it
108    * @return true or false when called without any parameters, and <code>undefined</code> if called with any parameters.
109    * @type Boolean
110    * @example
111    * // toggle an enabled action
112    * if (hello.enabled()) {
113    *   hello.enabled(false);
114    * }
115    * else {
116    *   hello.enabled(true)
117    * }
118    */
119   this.enabled = function(value) {
120     if(value === undefined) {
121       return action.isEnabled();
122     } else {
123       action.setEnabled(value);
124       instance.emit('enabled');
125     }
126   };
127 }
128 
129 //todo this is a util method ... should be moved some other place
130 /**
131  * Creates a prototype for the subclass to inherits the prototype of the super class.
132  * @ignore
133  * @class This is used to inherit property from the parent class.
134  * @constructor
135  * @param p prototype of the parent class
136  * @returns an instance of the parent class prototype.
137  */
138 function heir(p) {
139   /** @ignore */
140   function F() {
141   }
142 
143   F.prototype = p;
144   return new F();
145 }
146 
147 Action.prototype = heir(EventEmitter.prototype);
148 
149 // set the constructor to the subclass prototype
150 Action.prototype.constructor = Action;
151 
152 /**
153  * Provides access to menu items.
154  * @namespace
155  * Provides access to menu items.
156  * To access the namespace, use <code>require('actions')</code>.
157  * The <code>actions</code> namespace provides methods to work with <code>Action</code>s.
158  * Actions can be added to Content Studio's menus, and can also be assigned a shortcut
159  * key combination.  
160  * <p>
161  * When actions are invoked by the user, an event is emitted;
162  * actions are also event emitters, and emit the <code>action</code> event when invoked
163  * by the user.
164  * @name actions
165  * @example
166  * var actions = require('actions');
167  * var hello = actions.createAction('Hello');
168  * hello.on('action', function() {
169  *   console.log('Hello there');
170  * });
171  * actions.add(hello, 'help');
172  */
173 
174 (function() {
175 
176 function Actions() {
177 
178   /**
179    * Returns an {@link Action} instance with the given name and accelerator.
180    * @param name the name of the action.
181    * @param accelerator the keyboard shortcut of the action.
182    * @memberOf actions
183    * @function
184    * @name createAction
185    * @example
186    * var doit = actions.createAction('Do it!', 'alt F2');
187    */
188   this.createAction = function(name, accelerator) {
189     return new Action(name, accelerator);
190   };
191 
192   var studioContext = jsStudioContext;
193 
194   /**
195    * Removes the menu item associated with the {@link Action} from the given Content Studio menu.  If no name is provided, the action will be removed from all menus.
196    * @param {Action} action the Action used when creating the menu item
197    * @param {String} menuName optionally, the name of the menu from which to remove the action.
198    * @memberOf actions
199    * @function
200    * @name removeAction
201    * @example
202    * actions.removeAction(doit, 'file');
203    */
204   this.removeAction = function(action, menuName) {
205     if (typeof(menuName) == 'undefined') {
206       studioContext.removeMenuItem(null, action.getSwingAction());
207     }
208     else {
209       studioContext.removeMenuItem(menuName, action.getSwingAction());
210     }
211   };
212 
213   /**
214    * Adds an menuItem to the given menu with the {@link Action}.
215    * @param {Action} action the action created earlier to add to the menu
216    * @param {String} where The name of the menu to which the action should be added. One of <code>file</code>, <code>edit</code>, <code>view</code>, <code>tools</code>, <code>plugins</code> or <code>help</code>
217    * @memberOf actions
218    * @function
219    * @name addAction
220    * @example
221    * actions.addAction(doit, 'file');
222    */
223   this.addAction = function (action, where) {
224     studioContext.addMenuItem(where, action.getSwingAction());
225   };
226 }
227 
228 
229 Require['actions'] = new Actions();
230 }())
231 
232 /*
233  * usage
234  *
235  * var actions = require('actions');
236  * var helloWorld = actions.createAction('Hello World', 'shortcut shift F5');
237  *
238  * actions.addAction(helloWorld, 'file');
239  *
240  * helloWorld.on('action', function(){ console.log('I am clicked'); });
241  * 
242  * helloWorld.on('enabled', function(value) { if (helloWorld.isEnabled()) { console.log('enabled'); } else { console.log('disabled'); } }); 
243  * helloWorld.enabled(false);
244  *
245  *
246  * for removing action
247  * 
248  * actions.removeAction(helloWorld, 'file'); //will remove menu item from file menu.
249  * actions.removeAction(helloWorld); // will remove menu item from all menu.
250  *
251  * */
252