--- /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 Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * 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.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.Menu;
+import org.eclipse.swt.widgets.Shell;
+/**
+ * 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 {
+ 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{
+
+ 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;
+ Display display = Display.getCurrent();
+ 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
+ */
+ public 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;
+ }
+ 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 CommandPresentationStrategy strategy;
+ private Command defaultCommand;
+
+ public CommandArranger(){
+ super();
+ currentCommands = new CommandCollection();
+ strategy = CommandPresentationStrategyWrapper.createStrategy();
+ }
+
+
+
+ /**
+ * 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 );
+ }
+
+ /**
+ * Called when a new Control gains focus.
+ *
+ * @see Control#qt_swt_event_focusWasGained()
+ */
+ public void focusedControlChanged(){
+ Display display = Display.getCurrent();
+ 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);
+ }
+ }
+
+ /**
+ * 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);
+ }
+ }
+
+ /**
+ * Called when the Display is getting disposed.
+ */
+ public void dispose(){
+ strategy.dispose();
+ strategy = null;
+ currentCommands = 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;
+ }
+
+ /**
+ * 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 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);
+ }
+
+}