]>
git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.webapp/src/main/webapp/argeo-ria-src/class/org/argeo/ria/event/CommandsManager.js
f4e38a4084211662b58faa004fe74c20f0398f05
2 * The main controller (in a standard MVC point of view) of the application. It is a singleton
3 * thus can be called by any part of the application.
4 * This will wire all the commands that can be defined dynamically by any IView, and add their
5 * corresponding buttons to the application menubar and toolbars.
6 * See the "definitions" property documentation below for more info on how to define new commands.
8 * @author Charles du Jeu
10 qx
.Class
.define("org.argeo.ria.event.CommandsManager",
13 extend
: qx
.core
.Object
,
15 construct : function(){
17 this.setInitialDefinitions(qx
.lang
.Object
.copy(this.getDefinitions()));
18 this.addListener("changedCommands", this.createCommands
, this);
24 * The commands definitions is a Map described as below
28 * | The label of the action
33 * <b>shortcut : "",</b>
34 * | The keyboard shortcut, as defined in qooxdoo (Control+s, Alt+k, etc.). Warning, the letter must be lowercase.
36 * <b>enabled : true,</b>
37 * | Whether it is enabled or disabled at creation
39 * <b>menu : ""|null,</b>
40 * | The menu group to which the command will be added. If null, will not appear in the menus.
42 * <b>menuPosition : "first"|"last"</b>
43 * | Optional : force the menu group to be first or last in the menubar.
45 * <b>toolbar : ""|null,</b>
46 * | The toolbar group to which the command will be added. If null, will not appear in the toolbars.
48 * <b>init : function(){},</b>
49 * | Optional function called at command creation.
50 * | Function context : the command itself
52 * <b>callback : function(e){},</b>
53 * | The main callback to be triggered when command is executed.
54 * | Function context : the current class (not the command!)
56 * <b>selectionChange : function(viewPaneId, xmlNodes){},</b>
57 * | Optional function called each time a selectionChange is detected in one of the active viewPane.
58 * | The origin viewPaneId and the new selection as a map of nodes are passed as arguments.
59 * | Function context : the command itself.
61 * <b>submenu : [{label:"", icon:"", commandId:""}, ...],</b>
62 * | If set, the command will create a submenu, being in a menu or in the toolbar.
63 * | The submenu is created with the various array entries, and the submenuCallback function
64 * | will be called with the 'commandId' parameter when a submenu entry is selected.
66 * <b>submenuCallback : function(commandId){},</b>
67 * | Callback if command is a submenu (cf. above).
68 * | Function context : the current class/
70 * <b>command : null</b>
71 * | For internal use only, caching the actual org.argeo.ria.event.Command object.
74 * @see org.argeo.ria.event.Command for the definition Map details.
83 initialDefinitions
: {
88 * Special command definitions that are shared between focusable parts.
98 * Triggered when the whole commands list is changed. Mainly used internally by the manager.
100 "changedCommands" : "qx.event.type.Event"
104 *****************************************************************************
106 *****************************************************************************
112 * Initialize the manager with basic definitions.
113 * @param initDefinitions {Map} A map of commands definitions.
115 init : function(initDefinitions
){
116 this.setDefinitions(initDefinitions
);
117 this.setInitialDefinitions(qx
.lang
.Object
.copy(initDefinitions
));
121 * Creates all the objects (if they are not already existing) from the definitions maps.
123 createCommands : function(){
126 var defs
= this.getDefinitions();
127 var shared
= this.getSharedDefinitions();
128 for(var key
in defs
){
129 var definition
= defs
[key
];
131 if(!definition
.command
){
132 command
= new org
.argeo
.ria
.event
.Command(key
, definition
.label
, definition
.icon
, definition
.shortcut
);
133 if(definition
.submenu
){
134 command
.setMenu(definition
.submenu
);
135 if(definition
.submenuCallback
){
136 command
.setMenuCallback(definition
.submenuCallback
);
137 command
.setMenuContext((definition
.callbackContext
?definition
.callbackContext
:null));
140 command
.setEnabled(definition
.enabled
);
141 if(definition
.toggle
){
142 command
.setToggle(true);
143 if(definition
.toggleInitialState
){
144 command
.setToggleInitialState(definition
.toggleInitialState
);
147 this._attachListener(command
, definition
.callback
, definition
.callbackContext
);
149 var binded
= qx
.lang
.Function
.bind(definition
.init
, command
);
152 definition
.command
= command
;
154 command
= definition
.command
;
157 for(var focusPartId
in shared
[key
]){
158 var sharedCommand
= shared
[key
][focusPartId
];
159 if(sharedCommand
.callback
){
160 var split
= sharedCommand
.callbackContext
.split(":");
161 var focusPart
= split
[0];
162 var viewId
= split
[1];
163 command
.registerCallback(sharedCommand
.callback
, split
[1]);
164 //this._attachListener(command, sharedCommand.callback, sharedCommand.callbackContext);
171 if(!this.menus
[definition
.menu
]) this.menus
[definition
.menu
] = [];
172 this.menus
[definition
.menu
].push(definition
);
174 if(definition
.toolbar
){
175 if(!this.toolbars
[definition
.toolbar
]) this.toolbars
[definition
.toolbar
] = [];
176 this.toolbars
[definition
.toolbar
].push(command
);
179 this.setDefinitions(defs
);
183 * Refresh the current commands status depending on the viewSelection.
184 * @param viewSelection {org.argeo.ria.components.ViewSelection} The current ViewSelection
186 refreshCommands : function(viewSelection
){
187 var defs
= this.getDefinitions();
188 var shared
= this.getSharedDefinitions();
190 if(viewSelection
.getCount() > 0){
191 var xmlNodes
= viewSelection
.getNodes();
193 for(var key
in defs
){
194 var definition
= defs
[key
];
195 if(!definition
.selectionChange
) continue;
197 var currentFocus
= org
.argeo
.ria
.components
.ViewsManager
.getInstance().getCurrentFocus();
198 //this.debug(currentFocus);
199 if(!currentFocus
) continue;
200 var sharedComm
= shared
[key
][currentFocus
.getViewId()];
201 if(sharedComm
&& sharedComm
.selectionChange
){
202 var binded
= qx
.lang
.Function
.bind(sharedComm
.selectionChange
, definition
.command
);
203 binded(viewSelection
.getViewId(), xmlNodes
);
206 var binded
= qx
.lang
.Function
.bind(definition
.selectionChange
, definition
.command
);
207 binded(viewSelection
.getViewId(), xmlNodes
);
212 * Record a menubar for the application
213 * @param menuBar {qx.ui.menubar.MenuBar} The application menubar
215 registerMenuBar : function(menuBar
){
216 this.addListener("changedCommands", function(){
217 this.createMenuButtons(menuBar
);
219 this.createMenuButtons(menuBar
);
223 * Record a toolbar for the application
224 * @param toolBar {qx.ui.toolbar.ToolBar} The application toolbar
226 registerToolBar : function(toolBar
){
227 this.addListener("changedCommands", function(){
228 this.createToolbarParts(toolBar
);
230 this.createToolbarParts(toolBar
);
234 * Creates the real buttons and add them to the passed menuBar.
235 * @param menuBar {qx.ui.menubar.MenuBar} The application menubar
237 createMenuButtons : function(menuBar
){
240 for(var key
in this.menus
){
241 var menu
= new qx
.ui
.menu
.Menu();
242 var button
= new qx
.ui
.menubar
.Button(key
, null, menu
);
243 var anchorDetected
= false;
244 for(var i
=0; i
<this.menus
[key
].length
;i
++){
245 var def
= this.menus
[key
][i
];
246 menu
.add(def
.command
.getMenuButton());
247 if(!anchorDetected
&& def
.menuPosition
){
248 anchorDetected
= true;
249 anchors
[def
.menuPosition
] = button
;
256 // Add specific anchored buttons
257 if(anchors
.first
) menuBar
.addAt(anchors
.first
, 0);
258 else if(anchors
.last
){
259 menuBar
.add(anchors
.last
);
264 * Creates the real buttons and add them to the passed toolbar.
265 * @param toolbar {qx.ui.toolbar.ToolBar} The application toolbar
267 createToolbarParts : function(toolbar
){
269 for(var key
in this.toolbars
){
270 var tPart
= new qx
.ui
.toolbar
.Part();
272 this.toolbars
[key
].map(function(command
){
273 tPart
.add(command
.getToolbarButton());
278 * Creates a context menu from an array of commands ids.
279 * @param commandIdsArray {Array} An array of string
280 * @return {qx.ui.menu.Menu}
282 createMenuFromIds : function(commandIdsArray
){
283 var defs
= this.getDefinitions();
284 var contextMenu
= new qx
.ui
.menu
.Menu();
285 for(var i
=0;i
<commandIdsArray
.length
;i
++){
286 var definition
= defs
[commandIdsArray
[i
]];
288 var command
= definition
.command
;
289 contextMenu
.add(command
.getMenuButton());
295 * Add a new set of commands definitions. See the definitions property of this class.
296 * @param definitions {Map} a set of commands definitions.
297 * @param callbackContext {qx.ui.core.Object} The context used inside the commands callbacks.
298 * @param focusablePartId {String} A string identifying the associated focusable part, like "view:viewId".
300 addCommands : function(definitions
, callbackContext
, focusablePartId
){
301 var crtDefs
= this.getDefinitions();
302 for(var key
in definitions
){
303 if(callbackContext
) definitions
[key
]['callbackContext'] = callbackContext
;
304 if(crtDefs
[key
] && definitions
[key
]['shared']){
305 if(focusablePartId
) {
306 definitions
[key
]['focusablePartId'] = focusablePartId
;
307 if(!this.getSharedDefinitions()[key
]){
308 this.getSharedDefinitions()[key
] = {};
310 this.getSharedDefinitions()[key
][focusablePartId
] = definitions
[key
];
314 crtDefs
[key
] = definitions
[key
];
317 this.setDefinitions(crtDefs
);
318 this.fireEvent("changedCommands");
321 * Removes a whole set of commands by their definitions maps.
322 * @param definitions {Map} a set of commands definitions
323 * @param focusablePartId {String} A string identifying the associated focusable part, like "view:viewId".
325 removeCommands : function(definitions
, focusablePartId
){
326 var crtDefs
= this.getDefinitions();
327 var initDefs
= this.getInitialDefinitions();
328 var sharedDefs
= this.getSharedDefinitions();
329 for(var key
in definitions
){
330 if(!crtDefs
[key
]) continue;
332 crtDefs
[key
] = initDefs
[key
];
334 if(sharedDefs
[key
] && sharedDefs
[key
][focusablePartId
]){
335 crtDefs
[key
].command
.removeCallback(focusablePartId
);
336 delete sharedDefs
[key
][focusablePartId
];
342 this.setDefinitions(crtDefs
);
343 this.fireEvent("changedCommands");
346 * Executes a command by its id.
347 * @param commandId {String} The command id.
349 executeCommand : function(commandId
){
350 var defs
= this.getDefinitions();
351 if(defs
[commandId
] && defs
[commandId
].command
.getEnabled()){
352 defs
[commandId
].command
.execute();
356 * Retrieves a command by its id.
357 * @param commandId {String} The command id.
359 getCommandById : function(commandId
){
360 var defs
= this.getDefinitions();
361 if(defs
[commandId
] && defs
[commandId
].command
){
362 return defs
[commandId
].command
;
366 * Add a standard context menu to a toolbar for button look and feel (show icon, text, both).
367 * @param toolbar {qx.ui.toolbar.ToolBar} The toolbar
369 addToolbarContextMenu : function(toolbar
){
370 var menu
= new qx
.ui
.menu
.Menu();
371 var icon
= new qx
.ui
.menu
.RadioButton("Show Icons");
372 icon
.setValue("icon");
373 var text
= new qx
.ui
.menu
.RadioButton("Show Text");
374 text
.setValue("label");
375 var both
= new qx
.ui
.menu
.RadioButton("Show Both");
376 both
.setValue("both");
377 var mgr
= new qx
.ui
.form
.RadioGroup(icon
, text
, both
);
381 mgr
.setSelected(both
);
382 toolbar
.setContextMenu(menu
);
383 mgr
.addListener("changeValue", function(e
){
384 this.setShow(e
.getData());
389 * Attach a listener to a command, with a context.
390 * The context can be an object, a string like "view:viewId" or null.
391 * If a string, the viewPaneId content will be retrieved at runtime. If null, "this" will be used
392 * as default context.
393 * @param command {org.argeo.ria.event.Command} The command
394 * @param callback {Function} The function to execute
395 * @param callbackContext {Object|String} The context in which the function will be executed.
397 _attachListener:function(command
, callback
, callbackContext
){
398 if(!callbackContext
){
399 command
.addListener("execute", callback
, this);
402 if(typeof(callbackContext
) == "object"){
403 command
.addListener("execute", callback
, callbackContext
);
406 if(typeof(callbackContext
) == "string"){
408 var split
= callbackContext
.split(":");
409 var focusPart
= split
[0];
410 var viewId
= split
[1];
411 if(command
.getCallbacks()[viewId
]) return;
412 command
.registerCallback(callback
, split
[1]);
413 command
.addListener("execute", function(event
){
414 var target
= event
.getTarget();
415 var callbacks
= target
.getCallbacks();
416 if(qx
.lang
.Object
.getLength(callbacks
) == 0) return;
417 var view
= org
.argeo
.ria
.components
.ViewsManager
.getInstance().getViewPaneById(viewId
).getContent();
418 if(qx
.lang
.Object
.getLength(callbacks
) == 1){
419 var binded
= qx
.lang
.Function
.bind(callbacks
[qx
.lang
.Object
.getKeys(callbacks
)[0]], view
);
423 var currentFocus
= org
.argeo
.ria
.components
.ViewsManager
.getInstance().getCurrentFocus();
424 if(currentFocus
&& currentFocus
.getViewId() && callbacks
[currentFocus
.getViewId()]){
425 var currentViewId
= currentFocus
.getViewId();
426 view
= org
.argeo
.ria
.components
.ViewsManager
.getInstance().getViewPaneById(currentViewId
).getContent();
427 var binded
= qx
.lang
.Function
.bind(callbacks
[currentFocus
.getViewId()], view
);
435 if(callbackContext.split(":")[0] == "view"){
436 var viewId = callbackContext.split(":")[1];
437 command.addListener("execute", function(event){
438 if(event.getTarget().getCheckFocusAtCallback()){
439 var currentFocus = org.argeo.ria.components.ViewsManager.getInstance().getCurrentFocus();
440 if(currentFocus.getViewId() != viewId) return;
442 var view = org.argeo.ria.components.ViewsManager.getInstance().getViewPaneById(viewId).getContent();
443 var binded = qx.lang.Function.bind(callback, view);
447 command.addListener("execute", callback, callbackContext);