--- a/javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/org/eclipse/swt/internal/qt/CommandArranger.java Fri Jun 11 13:33:44 2010 +0300
+++ b/javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/org/eclipse/swt/internal/qt/CommandArranger.java Wed Jun 23 18:07:10 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,420 @@
* 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;
- }
+/**
+ * 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
+ */
+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;
}
- 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;
}
+ }
+ 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;
+}
- /**
- * Returns the number of the Commands
- *
- * @return boolean
- */
- public int getSize(){
- int size = 0;
- if (fCommands != null ) size = fCommands.length;
- return size;
- }
+}// CommandCollection
- /**
- * 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;
- }
- 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;
- }
- }
- }
- 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() {
+ Shell activeShell = display.getActiveShell();
+
+ if (activeShell == lastKnownActiveShell) {
+ return;
+ }
+ lastKnownActiveShell = activeShell;
+
+ cleanPositiveCommands();
+ cleanNegativeCommand();
+
+ currentCommands = new CommandCollection();
+
+ if (activeShell != null && Command.internal_getCommands(activeShell).length > 0) {
+ currentCommands.addCommand(Command.internal_getCommands(activeShell));
}
+ // 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);
+ }
+}
+
+/**
+ * Returns the default command or null if there is none.
+ *
+ * @return
+ * @see Command#isDefaultCommand()
+ */
+public Command getDefaultCommand() {
+ return defaultCommand;
+}
- /**
- * 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 ){
+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();
+}
- 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 );
- }
+private void handleDefaultCommandChange(Command defaultCommand) {
+ this.defaultCommand = defaultCommand;
+ cleanPositiveCommands();
+ placePositiveCommands();
+}
- /**
- * Called when a new Control gains focus.
- *
- * @see Control#qt_swt_event_focusWasGained()
- */
- public void focusedControlChanged(){
- Control focusControl = display.getFocusControl();
- if (focusControl == focusedControl) {
- return;
+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;
}
- 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) );
+ 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++;
}
- ctrl = ctrl.getParent();
+ continue;
}
- if (activeShell != null && Command.internal_getCommands(activeShell).length > 0 ){
- currentCommands.addCommand( Command.internal_getCommands(activeShell) );
- }
-
- if (strategy != null) {
- strategy.handleFocusChange(focusControl, oldCollection, currentCommands);
- }
+ positiveKeyCommands[positiveKeyIndex] = cmd;
+ positiveKeyIndex++;
}
+ if ((positiveKeyIndex) < positiveKeyCommands.length) {// needs to shrink
+ Command[] rightSized = new Command[positiveKeyIndex];
+ System.arraycopy(positiveKeyCommands, 0, rightSized, 0, rightSized.length);
+ positiveKeyCommands = rightSized;
+ }
+}
- /**
- * 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);
+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));
}
}
-
- /**
- * 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);
- }
- }
+ 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));
- /**
- * Called when the Display is getting disposed.
- */
- public void dispose(){
- strategy.dispose();
- strategy = null;
- currentCommands = null;
- display = null;
- }
- /**
- * 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);
}
}
+}
- /**
- * Returns the default command or null if there is none.
- *
- * @return
- * @see Command#isDefaultCommand()
- */
- public Command getDefaultCommand(){
- return defaultCommand;
+private void cleanNegativeCommand() {
+ if (negativeKeyCommand != null && !negativeKeyCommand.isDisposed()
+ && !negativeKeyCommand.control.isDisposed()) {
+ OS.QWidget_removeAction(topHandle(negativeKeyCommand.control),
+ topHandle(negativeKeyCommand));
}
+}
- /**
- * 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 void placeNegativeCommand() {
+ if (negativeKeyCommand != null) {
+ OS.QWidget_addAction(Internal_PackageSupport.topHandle(negativeKeyCommand.control),
+ topHandle(negativeKeyCommand));
+ }
+}
+
+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 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 handleMenuBarChanged(int newMenuBar, CommandCollection commands) {
+ placePositiveCommands();
+}
- 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 static final int topHandle(Widget w) {
+ return Internal_PackageSupport.topHandle(w);
+}
}