diff -r 1f0034e370aa -r 71ad690e91f5 javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/org/eclipse/swt/internal/qt/CommandArranger.java --- a/javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/org/eclipse/swt/internal/qt/CommandArranger.java Fri Sep 17 16:44:34 2010 +0300 +++ b/javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/org/eclipse/swt/internal/qt/CommandArranger.java Mon Oct 04 11:29:25 2010 +0300 @@ -11,12 +11,14 @@ package org.eclipse.swt.internal.qt; import org.eclipse.ercp.swt.mobile.Command; -import org.eclipse.swt.internal.CommandPresentationStrategyWrapper; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Decorations; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Internal_PackageSupport; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Widget; + /** * Manages the Command presentation cycle. This is a singleton object that gets * notified about the events that can have an effect on the way the Commands are @@ -24,298 +26,424 @@ * context with the help of {@link CommandCollection}. It also notifies the * currently active {@link CommandPresentationStrategy} so that the presentation * is updated if necessary. - * + * * @see Command * @see CommandCollection * @see CommandPresentationStrategy */ public class CommandArranger { - Control focusedControl; - /** - * A helper for keeping an ordered list of {@link Command}s in the current focus context. - * The Commands are ordered according to their proximity to the currently focused control. - * The ordered list starts with Commands from the currently focused Control if any and ends with - * the active Shell and includes all the Commands in between. If a Control has more - * than one Command they are ordered among themselves according to creation order. - */ - public class CommandCollection{ +/** + * A helper for keeping an ordered list of {@link Command}s in the current focus + * context. The Commands are ordered according to their proximity to the + * currently focused control. The ordered list starts with Commands from the + * currently focused Control if any and ends with the active Shell and includes + * all the Commands in between. If a Control has more than one Command they are + * ordered among themselves according to creation order. + */ +public class CommandCollection { - private Command[] fCommands; +private Command[] fCommands; - CommandCollection(){ - super(); - } +CommandCollection() { + super(); +} - /** - * Adds the command to the collection. - * Warning: This does not make duplicate control. - * @param command - */ - void addCommand(Command command) { - if (command == null) - return; - if (fCommands == null) { - fCommands = new Command[1]; - fCommands[0] = command; - return; - } - int size = fCommands.length + 1; - Command[] newList = new Command[size]; - // find the insertion point so that the order is correct - int insertPoint = 0; - Shell activeShell = display.getActiveShell(); - Control ctrl = display.getFocusControl(); - while (ctrl != null && ctrl != activeShell) { - if (ctrl == command.control) { - // Adding a command to focused control increment by one. - // adding Command.internal_getCommands(ctrl).length will - // just duplicate the count for Commands already in array. - insertPoint++; - break; - } - insertPoint += Command.internal_getCommands(ctrl).length; - ctrl = ctrl.getParent(); - } - System.arraycopy(fCommands, 0, newList, 0, insertPoint); - System.arraycopy(fCommands, insertPoint, newList, insertPoint + 1, - fCommands.length - insertPoint); - newList[insertPoint] = command; - fCommands = newList; +/** + * Adds the command to the collection. Warning: This does not make duplicate + * control. + * + * @param command + */ +void addCommand(Command command) { + if (command == null) + return; + if (fCommands == null) { + fCommands = new Command[1]; + fCommands[0] = command; + return; + } + int size = fCommands.length + 1; + Command[] newList = new Command[size]; + // find the insertion point so that the order is correct + int insertPoint = 0; + Shell activeShell = display.getActiveShell(); + Control ctrl = display.getFocusControl(); + while (ctrl != null && ctrl != activeShell) { + if (ctrl == command.control) { + // Adding a command to focused control increment by one. + // adding Command.internal_getCommands(ctrl).length will + // just duplicate the count for Commands already in array. + insertPoint++; + break; } + insertPoint += Command.internal_getCommands(ctrl).length; + ctrl = ctrl.getParent(); + } + System.arraycopy(fCommands, 0, newList, 0, insertPoint); + System.arraycopy(fCommands, insertPoint, newList, insertPoint + 1, fCommands.length + - insertPoint); + newList[insertPoint] = command; + fCommands = newList; +} - /** - * Adds the list of Commands to the collection. - * @param commands - */ - void addCommand( Command[] commands ){ - if (commands == null || commands.length == 0 ) return; - if (fCommands == null ){ - fCommands = new Command[ commands.length ]; - System.arraycopy(commands, 0, fCommands, 0, commands.length ); - return; - } - int size = commands.length + fCommands.length; - Command[] newList = new Command[ size ]; - System.arraycopy(fCommands, 0, newList, 0, fCommands.length); - System.arraycopy(commands, 0, newList, fCommands.length , commands.length ); - fCommands = newList; - } +/** + * Adds the list of Commands to the collection. + * + * @param commands + */ +void addCommand(Command[] commands) { + if (commands == null || commands.length == 0) + return; + if (fCommands == null) { + fCommands = new Command[commands.length]; + System.arraycopy(commands, 0, fCommands, 0, commands.length); + return; + } + int size = commands.length + fCommands.length; + Command[] newList = new Command[size]; + System.arraycopy(fCommands, 0, newList, 0, fCommands.length); + System.arraycopy(commands, 0, newList, fCommands.length, commands.length); + fCommands = newList; +} - /** - * Removes the command from the list. - * @param command - */ - void removeCommand( Command command ){ - if ( command == null ) return; - if (fCommands == null || fCommands.length == 0 ) return; - int removeIndex = -1; - for (int i = 0; i < fCommands.length; i++) { - if(fCommands[i] == command ){ - removeIndex = i; - } - } - if ( removeIndex == -1 ) return; - Command[] newList = new Command[ fCommands.length -1 ]; - System.arraycopy( fCommands, 0, newList, 0, removeIndex); - System.arraycopy( fCommands, removeIndex + 1, newList, removeIndex, (fCommands.length - removeIndex -1) ); - fCommands = newList; +/** + * Removes the command from the list. + * + * @param command + */ +void removeCommand(Command command) { + if (command == null) + return; + if (fCommands == null || fCommands.length == 0) + return; + int removeIndex = -1; + for (int i = 0; i < fCommands.length; i++) { + if (fCommands[i] == command) { + removeIndex = i; } + } + if (removeIndex == -1) + return; + Command[] newList = new Command[fCommands.length - 1]; + System.arraycopy(fCommands, 0, newList, 0, removeIndex); + System.arraycopy(fCommands, removeIndex + 1, newList, removeIndex, (fCommands.length + - removeIndex - 1)); + fCommands = newList; +} - /** - * Returns the number of the Commands - * - * @return boolean - */ - public int getSize(){ - int size = 0; - if (fCommands != null ) size = fCommands.length; - return size; - } +/** + * Returns the number of the Commands + * + * @return boolean + */ +int getSize() { + int size = 0; + if (fCommands != null) + size = fCommands.length; + return size; +} - /** - * Retrieves the Commands of the types indicated by the commandTypes array. - * The order of the commandTypes array has no significance. Passing a null parameter - * or an empty array retrieves all the available Commands. - * - * @param commandTypes - * @return Command list - */ - public Command[] getCommands( int[] commandTypes ){ - if ( commandTypes == null || commandTypes.length == 0 ){ - return fCommands; +/** + * Retrieves the Commands of the types indicated by the commandTypes array. The + * order of the commandTypes array has no significance. Passing a null parameter + * or an empty array retrieves all the available Commands. + * + * @param commandTypes + * @return Command list + */ +Command[] getCommands(int[] commandTypes) { + if (commandTypes == null || commandTypes.length == 0) { + return fCommands; + } + int size = getSize(); + Command[] filteredCommands = new Command[size]; + int index = 0; + for (int i = 0; i < fCommands.length; i++) { + for (int j = 0; j < commandTypes.length; j++) { + if (fCommands[i].type == commandTypes[j]) { + filteredCommands[index] = fCommands[i]; + index++; + break; } - int size = getSize(); - Command[] filteredCommands = new Command[size]; - int index = 0; - for (int i = 0; i < fCommands.length ; i++) { - for(int j = 0; j (index) ){// Some commands filtered resize the Array - Command[] shrunk = new Command[index]; - System.arraycopy( filteredCommands, 0, shrunk, 0, index); - return shrunk; - } - return filteredCommands; } - }// CommandCollection + } + if (size > (index)) {// Some commands filtered resize the Array + Command[] shrunk = new Command[index]; + System.arraycopy(filteredCommands, 0, shrunk, 0, index); + return shrunk; + } + return filteredCommands; +} + +}// CommandCollection + +private CommandCollection currentCommands; +private Command defaultCommand; +private Display display; +Control focusedControl; +Shell lastKnownActiveShell; +private Command[] positiveKeyCommands; +private Command negativeKeyCommand; + + +public CommandArranger(Display display) { + super(); + this.display = display; + currentCommands = new CommandCollection(); +} - private CommandCollection currentCommands; - private CommandPresentationStrategy strategy; - private Command defaultCommand; - private Display display; +/** + * Called when the application changes the QMenuBar. This method does not handle + * the cases when the QMenuBar may change when the active top-level Shell + * changes. Since this does not cause a menu bar change on all platforms. + * + * @see org.eclipse.swt.widgets.Decorations#setMenuBar(Menu) + * + **/ +public void menuBarChanged(Decorations decorations) { + if (currentCommands == null || currentCommands.getSize() < 1) + return; + // if the changed menu bar is not on the active shell ignore and leave + // it to focus change. + if (decorations.getShell() != decorations.getDisplay().getActiveShell()) + return; + // Call internal_getOwnMenuBar because the menu bar can be set to null + // in Decorations and + // we may need to create the internal one. + int menuBarHandle = decorations.internal_getOwnMenuBar(); - public CommandArranger(Display display){ - super(); - this.display = display; - currentCommands = new CommandCollection(); - strategy = CommandPresentationStrategyWrapper.createStrategy(); + handleMenuBarChanged(menuBarHandle, currentCommands); +} + +/** + * Called when a new Shell becomes active. + * + * @see Control#qt_swt_event_focusWasGained() //TODO + */ +public void shellActivityChanged() { + if (display == null) { + return; } - - - /** - * Called when the application changes the QMenuBar. - * This method does not handle the cases when the QMenuBar - * may change when the active top-level Shell changes. Since - * this does not cause a menu bar change on all platforms. - * - * @see org.eclipse.swt.widgets.Decorations#setMenuBar(Menu) - * - **/ - public void menuBarChanged( Decorations decorations ){ - - if ( currentCommands == null || currentCommands.getSize() < 1 ) return; - // if the changed menu bar is not on the active shell ignore and leave it to focus change. - if (decorations.getShell() != decorations.getDisplay().getActiveShell() )return; - // Call internal_getOwnMenuBar because the menu bar can be set to null in Decorations and - // we may need to create the internal one. - int menuBarHandle = decorations.internal_getOwnMenuBar(); - - strategy.handleMenuBarChanged( menuBarHandle, currentCommands ); + Shell activeShell = display.getActiveShell(); + + if (activeShell == lastKnownActiveShell) { + return; } + lastKnownActiveShell = activeShell; + + cleanPositiveCommands(); + cleanNegativeCommand(); + + currentCommands = new CommandCollection(); - /** - * Called when a new Control gains focus. - * - * @see Control#qt_swt_event_focusWasGained() - */ - public void focusedControlChanged(){ - Control focusControl = display.getFocusControl(); - if (focusControl == focusedControl) { - return; - } - focusedControl = focusControl; - - Shell activeShell = display.getActiveShell(); - CommandCollection oldCollection = currentCommands; - currentCommands = new CommandCollection(); - - Control ctrl = focusControl; - while ( ctrl!= null && ctrl != activeShell ){ - if ( Command.internal_getCommands(ctrl).length > 0 ){ - currentCommands.addCommand( Command.internal_getCommands(ctrl) ); - } - ctrl = ctrl.getParent(); - } - if (activeShell != null && Command.internal_getCommands(activeShell).length > 0 ){ - currentCommands.addCommand( Command.internal_getCommands(activeShell) ); - } - - if (strategy != null) { - strategy.handleFocusChange(focusControl, oldCollection, currentCommands); - } - } - - /** - * Called when a new Command is created - * @param command - */ - public void commandAdded( Command command ){ - if( isInFocusContext(command.control)){ - currentCommands.addCommand(command); - strategy.handleCommandListChange(command, null, currentCommands); - } + if (activeShell != null && Command.internal_getCommands(activeShell).length > 0) { + currentCommands.addCommand(Command.internal_getCommands(activeShell)); } - /** - * Called when a Command is disposed - * @param command - */ - public void commandRemoved( Command command ){ - if ( command == defaultCommand ) defaultCommand = null; - if (isInFocusContext(command.control)){ - currentCommands.removeCommand( command ); - strategy.handleCommandListChange(null, command, currentCommands); - } + // Determine where the commands go + if (currentCommands.getSize() > 0) { + Command[] add = currentCommands.getCommands(null); + updateCommandPositions(add); + placePositiveCommands(); + placeNegativeCommand(); + } +} + +/** + * Called when a new Command is created + * + * @param command + */ +public void commandAdded(Command command) { + if (isInFocusContext(command.control)) { + currentCommands.addCommand(command); + handleCommandListChange(command, null, currentCommands); } +} + +/** + * Called when a Command is disposed + * + * @param command + */ +public void commandRemoved(Command command) { + if (command == defaultCommand) + defaultCommand = null; + if (isInFocusContext(command.control)) { + currentCommands.removeCommand(command); + handleCommandListChange(null, command, currentCommands); + } +} + +/** + * Called when the Display is getting disposed. + */ +public void dispose() { + currentCommands = null; + display = null; + positiveKeyCommands = null; + negativeKeyCommand = null; + defaultCommand = null; + lastKnownActiveShell = null; +} + +/** + * Called when a Command is set default + * + * @param command + * @see Command#setDefaultCommand(); + */ +public void setDefaultCommand(Command command) { + defaultCommand = command; + if (isInFocusContext(command.control)) { + handleDefaultCommandChange(command); + } +} - /** - * Called when the Display is getting disposed. - */ - public void dispose(){ - strategy.dispose(); - strategy = null; - currentCommands = null; - display = null; +/** + * Returns the default command or null if there is none. + * + * @return + * @see Command#isDefaultCommand() + */ +public Command getDefaultCommand() { + return defaultCommand; +} + + +private boolean isInFocusContext(Control control) { + Display display = control.getDisplay(); + Shell activeShell = display.getActiveShell(); + return control == activeShell; +} + +private void handleCommandListChange(Command added, Command removed, CommandCollection commands) { + cleanNegativeCommand(); + cleanPositiveCommands(); + updateCommandPositions(commands.getCommands(null)); + placeNegativeCommand(); + placePositiveCommands(); +} + +private void handleDefaultCommandChange(Command defaultCommand) { + this.defaultCommand = defaultCommand; + cleanPositiveCommands(); + placePositiveCommands(); +} + +private void updateCommandPositions(Command[] commands) { + positiveKeyCommands = new Command[commands.length]; + int positiveKeyIndex = 0; + for (int i = 0; i < commands.length; i++) { + Command cmd = commands[i]; + if (cmd.isDefaultCommand()) { + defaultCommand = cmd; + continue; + } + if (CommandUtils.isNegativeType(cmd.type)) { + if (negativeKeyCommand == null || negativeKeyCommand.isDisposed()) { + negativeKeyCommand = cmd; + } else if (negativeKeyCommand.getPriority() <= cmd.getPriority()) { + positiveKeyCommands[positiveKeyIndex] = negativeKeyCommand; + positiveKeyIndex++; + negativeKeyCommand = cmd; + } else { + positiveKeyCommands[positiveKeyIndex] = cmd; + positiveKeyIndex++; + } + continue; + } + positiveKeyCommands[positiveKeyIndex] = cmd; + positiveKeyIndex++; } - /** - * Called when a Command is set default - * - * @param command - * @see Command#setDefaultCommand(); - */ - public void setDefaultCommand(Command command ){ - defaultCommand = command; - if(isInFocusContext(command.control)){ - strategy.handleDefaultCommandChange(command); + if ((positiveKeyIndex) < positiveKeyCommands.length) {// needs to shrink + Command[] rightSized = new Command[positiveKeyIndex]; + System.arraycopy(positiveKeyCommands, 0, rightSized, 0, rightSized.length); + positiveKeyCommands = rightSized; + } +} + +private void cleanPositiveCommands() { + boolean useBar = false; + if ((positiveKeyCommands != null && positiveKeyCommands.length > 1) + || (defaultCommand != null && positiveKeyCommands != null)) { + useBar = true; + } + if (defaultCommand != null && !defaultCommand.isDisposed() + && !defaultCommand.control.isDisposed()) { + if (useBar) { + OS.QWidget_removeAction(defaultCommand.control.getShell().internal_getOwnMenuBar(), + topHandle(defaultCommand)); + } else { + OS.QWidget_removeAction(topHandle(defaultCommand.control), topHandle(defaultCommand)); } } - - /** - * Returns the default command or null if there is none. - * - * @return - * @see Command#isDefaultCommand() - */ - public Command getDefaultCommand(){ - return defaultCommand; - } + if (positiveKeyCommands != null) { + for (int i = 0; i < positiveKeyCommands.length; i++) { + Command cmd = positiveKeyCommands[i]; + if (cmd == null || cmd.isDisposed() || cmd.control.isDisposed()) { + continue; + } + int handle = 0; + if (useBar) { + handle = cmd.control.getShell().internal_getOwnMenuBar(); + } else { + handle = topHandle(positiveKeyCommands[0].control); + } + OS.QWidget_removeAction(handle, topHandle(cmd)); - /** - * Sets a new {@link CommandPresentationStrategy}. It also disposes to old one. - * - * @param commandPresentationStrategy - */ - public void setPresentationStrategy( CommandPresentationStrategy commandPresentationStrategy ){ - CommandPresentationStrategy oldStrategy = strategy; - strategy = commandPresentationStrategy; - if (oldStrategy != null ){ - oldStrategy.dispose(); } } +} - private boolean isInFocusContext(Control control){ - Display display = control.getDisplay(); - Shell activeShell = display.getActiveShell(); - Control focused = display.getFocusControl(); - if( focused == null )return false; - if(control.getShell() != activeShell) return false; - if( control == focused ) return true; - return isFocusAncestor(focused, control); +private void cleanNegativeCommand() { + if (negativeKeyCommand != null && !negativeKeyCommand.isDisposed() + && !negativeKeyCommand.control.isDisposed()) { + OS.QWidget_removeAction(topHandle(negativeKeyCommand.control), + topHandle(negativeKeyCommand)); + } +} + +private void placeNegativeCommand() { + if (negativeKeyCommand != null) { + OS.QWidget_addAction(Internal_PackageSupport.topHandle(negativeKeyCommand.control), + topHandle(negativeKeyCommand)); } +} - private boolean isFocusAncestor(Control node, Control parent){ - Control nodeParent = node.getParent(); - if( nodeParent == parent )return true; - if (nodeParent == null || nodeParent == node.getShell() )return false; - return isFocusAncestor(nodeParent, parent); +private void placePositiveCommands() { + if (defaultCommand != null) { + int defaultCmdHandle = topHandle(defaultCommand); + if (positiveKeyCommands != null) { + OS.QMenuBar_addAction(defaultCommand.control.getShell().internal_getOwnMenuBar(), + defaultCmdHandle); + } else { + OS.QWidget_addAction(Internal_PackageSupport.topHandle(defaultCommand.control), + defaultCmdHandle); + } } + if (positiveKeyCommands != null) { + if (positiveKeyCommands.length == 1 && defaultCommand == null) { + OS.QWidget_addAction(Internal_PackageSupport.topHandle(positiveKeyCommands[0].control), + topHandle(positiveKeyCommands[0])); + } else { + CommandUtils.sort(positiveKeyCommands); + for (int i = 0; i < positiveKeyCommands.length; i++) { + OS.QMenuBar_addAction(positiveKeyCommands[i].control.getShell() + .internal_getOwnMenuBar(), topHandle(positiveKeyCommands[i])); + } + } + } +} + +private void handleMenuBarChanged(int newMenuBar, CommandCollection commands) { + placePositiveCommands(); +} + +private static final int topHandle(Widget w) { + return Internal_PackageSupport.topHandle(w); +} }