--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/org/eclipse/swt/internal/qt/CommandArranger.java Tue Aug 31 15:09:22 2010 +0300
@@ -0,0 +1,449 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Nokia Corporation - initial implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.qt;
+
+import org.eclipse.ercp.swt.mobile.Command;
+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
+ * represented. It maintains an ordered list of Commands on the current focus
+ * 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 {
+
+/**
+ * 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;
+
+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 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;
+}
+
+/**
+ * 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 (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();
+}
+
+/**
+ * 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();
+
+ handleMenuBarChanged(menuBarHandle, currentCommands);
+}
+
+/**
+ * Called when a new Shell becomes active.
+ *
+ * @see Control#qt_swt_event_focusWasGained() //TODO
+ */
+public void shellActivityChanged() {
+ if (display == null) {
+ return;
+ }
+
+ 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;
+}
+
+
+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++;
+ }
+ 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));
+ }
+ }
+ 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));
+
+ }
+ }
+}
+
+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 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);
+}
+
+}