javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/org/eclipse/swt/internal/qt/CommandArranger.java
changeset 21 2a9601315dfc
child 35 85266cc22c7f
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     1 /*******************************************************************************
       
     2  * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3  * All rights reserved. This program and the accompanying materials
       
     4  * are made available under the terms of the Eclipse Public License v1.0
       
     5  * which accompanies this distribution, and is available at
       
     6  * http://www.eclipse.org/legal/epl-v10.html
       
     7  *
       
     8  * Contributors:
       
     9  *     Nokia Corporation - initial implementation
       
    10  *******************************************************************************/
       
    11 package org.eclipse.swt.internal.qt;
       
    12 
       
    13 import org.eclipse.ercp.swt.mobile.Command;
       
    14 import org.eclipse.swt.internal.CommandPresentationStrategyWrapper;
       
    15 import org.eclipse.swt.widgets.Control;
       
    16 import org.eclipse.swt.widgets.Decorations;
       
    17 import org.eclipse.swt.widgets.Display;
       
    18 import org.eclipse.swt.widgets.Menu;
       
    19 import org.eclipse.swt.widgets.Shell;
       
    20 /**
       
    21  * Manages the Command presentation cycle. This is a singleton object that gets
       
    22  * notified about the events that can have an effect on the way the Commands are
       
    23  * represented. It maintains an ordered list of Commands on the current focus
       
    24  * context with the help of {@link CommandCollection}. It also notifies the
       
    25  * currently active {@link CommandPresentationStrategy} so that the presentation
       
    26  * is updated if necessary.
       
    27  *
       
    28  * @see Command
       
    29  * @see CommandCollection
       
    30  * @see CommandPresentationStrategy
       
    31  */
       
    32 public class CommandArranger {
       
    33     Control focusedControl;
       
    34 
       
    35     /**
       
    36      * A helper for keeping an ordered list of {@link Command}s in the current focus context.
       
    37      * The Commands are ordered according to their proximity to the currently focused control.
       
    38      * The ordered list starts with Commands from the currently focused Control if any and ends with
       
    39      * the active Shell and includes all the Commands in between. If a Control has more
       
    40      * than one Command they are ordered among themselves according to creation order.
       
    41      */
       
    42     public class CommandCollection{
       
    43 
       
    44         private Command[] fCommands;
       
    45 
       
    46         CommandCollection(){
       
    47             super();
       
    48         }
       
    49 
       
    50         /**
       
    51          * Adds the command to the collection.
       
    52          * Warning: This does not make duplicate control.
       
    53          * @param command
       
    54          */
       
    55         void addCommand(Command command) {
       
    56             if (command == null)
       
    57                 return;
       
    58             if (fCommands == null) {
       
    59                 fCommands = new Command[1];
       
    60                 fCommands[0] = command;
       
    61                 return;
       
    62             }
       
    63             int size = fCommands.length + 1;
       
    64             Command[] newList = new Command[size];
       
    65             // find the insertion point so that the order is correct
       
    66             int insertPoint = 0;
       
    67             Display display = Display.getCurrent();
       
    68             Shell activeShell = display.getActiveShell();
       
    69             Control ctrl = display.getFocusControl();
       
    70             while (ctrl != null && ctrl != activeShell) {
       
    71                 if (ctrl == command.control) {
       
    72                     // Adding a command to focused control increment by one.
       
    73                     // adding Command.internal_getCommands(ctrl).length will
       
    74                     // just duplicate the count for Commands already in array.
       
    75                     insertPoint++;
       
    76                     break;
       
    77                 }
       
    78                 insertPoint += Command.internal_getCommands(ctrl).length;
       
    79                 ctrl = ctrl.getParent();
       
    80             }
       
    81             System.arraycopy(fCommands, 0, newList, 0, insertPoint);
       
    82             System.arraycopy(fCommands, insertPoint, newList, insertPoint + 1,
       
    83                     fCommands.length - insertPoint);
       
    84             newList[insertPoint] = command;
       
    85             fCommands = newList;
       
    86         }
       
    87 
       
    88         /**
       
    89          * Adds the list of Commands to the collection.
       
    90          * @param commands
       
    91          */
       
    92         void addCommand( Command[] commands ){
       
    93             if (commands == null || commands.length == 0 ) return;
       
    94             if (fCommands == null ){
       
    95                 fCommands = new Command[ commands.length ];
       
    96                 System.arraycopy(commands, 0, fCommands, 0, commands.length );
       
    97                 return;
       
    98             }
       
    99             int size = commands.length + fCommands.length;
       
   100             Command[] newList = new Command[ size ];
       
   101             System.arraycopy(fCommands, 0, newList, 0, fCommands.length);
       
   102             System.arraycopy(commands, 0, newList, fCommands.length , commands.length );
       
   103             fCommands = newList;
       
   104         }
       
   105 
       
   106         /**
       
   107          * Removes the command from the list.
       
   108          * @param command
       
   109          */
       
   110         void removeCommand( Command command ){
       
   111             if ( command == null ) return;
       
   112             if (fCommands == null || fCommands.length == 0 ) return;
       
   113             int removeIndex = -1;
       
   114             for (int i = 0; i < fCommands.length; i++) {
       
   115                 if(fCommands[i] == command ){
       
   116                     removeIndex = i;
       
   117                 }
       
   118             }
       
   119             if ( removeIndex == -1 ) return;
       
   120             Command[] newList = new Command[ fCommands.length -1 ];
       
   121             System.arraycopy( fCommands, 0, newList, 0, removeIndex);
       
   122             System.arraycopy( fCommands, removeIndex + 1, newList, removeIndex, (fCommands.length - removeIndex -1) );
       
   123             fCommands = newList;
       
   124         }
       
   125 
       
   126         /**
       
   127          * Returns the number of the Commands
       
   128          *
       
   129          * @return boolean
       
   130          */
       
   131         public int getSize(){
       
   132             int size = 0;
       
   133             if (fCommands != null ) size = fCommands.length;
       
   134             return size;
       
   135         }
       
   136 
       
   137         /**
       
   138          * Retrieves the Commands of the types indicated by the commandTypes array.
       
   139          * The order of the commandTypes array has no significance. Passing a null parameter
       
   140          * or an empty array retrieves all the available Commands.
       
   141          *
       
   142          * @param commandTypes
       
   143          * @return Command list
       
   144          */
       
   145         public Command[] getCommands( int[] commandTypes ){
       
   146             if ( commandTypes == null || commandTypes.length == 0 ){
       
   147                 return fCommands;
       
   148             }
       
   149             int size = getSize();
       
   150             Command[] filteredCommands = new Command[size];
       
   151             int index = 0;
       
   152             for (int i = 0; i < fCommands.length ; i++) {
       
   153                 for(int j = 0; j<commandTypes.length; j++){
       
   154                     if ( fCommands[i].type == commandTypes[j] ){
       
   155                         filteredCommands[index]=fCommands[i];
       
   156                         index++;
       
   157                         break;
       
   158                     }
       
   159                 }
       
   160             }
       
   161             if( size > (index) ){// Some commands filtered resize the Array
       
   162                 Command[] shrunk = new Command[index];
       
   163                 System.arraycopy( filteredCommands, 0, shrunk, 0, index);
       
   164                 return shrunk;
       
   165             }
       
   166             return filteredCommands;
       
   167         }
       
   168     }// CommandCollection
       
   169 
       
   170     private CommandCollection currentCommands;
       
   171     private CommandPresentationStrategy strategy;
       
   172     private Command defaultCommand;
       
   173 
       
   174     public CommandArranger(){
       
   175         super();
       
   176         currentCommands = new CommandCollection();
       
   177         strategy = CommandPresentationStrategyWrapper.createStrategy();
       
   178     }
       
   179 
       
   180 
       
   181 
       
   182     /**
       
   183      * Called when the application changes the QMenuBar.
       
   184      * This method does not handle the cases when the QMenuBar
       
   185      * may change when the active top-level Shell changes. Since
       
   186      * this does not cause a menu bar change on all platforms.
       
   187      *
       
   188      * @see org.eclipse.swt.widgets.Decorations#setMenuBar(Menu)
       
   189      *
       
   190      **/
       
   191     public void menuBarChanged( Decorations decorations ){
       
   192 
       
   193         if ( currentCommands == null || currentCommands.getSize() < 1 ) return;
       
   194         // if the changed menu bar is not on the active shell ignore and leave it to focus change.
       
   195         if (decorations.getShell() != decorations.getDisplay().getActiveShell() )return;
       
   196         // Call internal_getOwnMenuBar because the menu bar can be set to null in Decorations and
       
   197         // we may need to create the internal one.
       
   198         int menuBarHandle = decorations.internal_getOwnMenuBar();
       
   199 
       
   200         strategy.handleMenuBarChanged( menuBarHandle, currentCommands );
       
   201     }
       
   202 
       
   203     /**
       
   204      * Called when a new Control gains focus.
       
   205      *
       
   206      * @see Control#qt_swt_event_focusWasGained()
       
   207      */
       
   208     public void focusedControlChanged(){
       
   209         Display display = Display.getCurrent();
       
   210         Control focusControl = display.getFocusControl();
       
   211         if (focusControl == focusedControl) {
       
   212             return;
       
   213         }
       
   214         focusedControl = focusControl;
       
   215 
       
   216         Shell activeShell = display.getActiveShell();
       
   217         CommandCollection oldCollection = currentCommands;
       
   218         currentCommands = new CommandCollection();
       
   219 
       
   220         Control ctrl = focusControl;
       
   221         while ( ctrl!= null && ctrl != activeShell ){
       
   222             if ( Command.internal_getCommands(ctrl).length > 0 ){
       
   223                 currentCommands.addCommand( Command.internal_getCommands(ctrl) );
       
   224             }
       
   225             ctrl = ctrl.getParent();
       
   226         }
       
   227         if (activeShell != null && Command.internal_getCommands(activeShell).length > 0 ){
       
   228             currentCommands.addCommand( Command.internal_getCommands(activeShell) );
       
   229         }
       
   230 
       
   231         if (strategy != null) {
       
   232             strategy.handleFocusChange(focusControl, oldCollection, currentCommands);
       
   233         }
       
   234     }
       
   235 
       
   236     /**
       
   237      * Called when a new Command is created
       
   238      * @param command
       
   239      */
       
   240     public void commandAdded( Command command ){
       
   241         if( isInFocusContext(command.control)){
       
   242             currentCommands.addCommand(command);
       
   243             strategy.handleCommandListChange(command, null, currentCommands);
       
   244         }
       
   245     }
       
   246 
       
   247     /**
       
   248      * Called when a Command is disposed
       
   249      * @param command
       
   250      */
       
   251     public void commandRemoved( Command command ){
       
   252         if ( command == defaultCommand ) defaultCommand = null;
       
   253         if (isInFocusContext(command.control)){
       
   254             currentCommands.removeCommand( command );
       
   255             strategy.handleCommandListChange(null, command, currentCommands);
       
   256         }
       
   257     }
       
   258 
       
   259     /**
       
   260      * Called when the Display is getting disposed.
       
   261      */
       
   262     public void dispose(){
       
   263         strategy.dispose();
       
   264         strategy = null;
       
   265         currentCommands = null;
       
   266     }
       
   267     /**
       
   268      * Called when a Command is set default
       
   269      *
       
   270      * @param command
       
   271      * @see Command#setDefaultCommand();
       
   272      */
       
   273     public void setDefaultCommand(Command command ){
       
   274         defaultCommand = command;
       
   275         if(isInFocusContext(command.control)){
       
   276             strategy.handleDefaultCommandChange(command);
       
   277         }
       
   278     }
       
   279 
       
   280     /**
       
   281      * Returns the default command or null if there is none.
       
   282      *
       
   283      * @return
       
   284      * @see Command#isDefaultCommand()
       
   285      */
       
   286     public Command getDefaultCommand(){
       
   287         return defaultCommand;
       
   288     }
       
   289 
       
   290     /**
       
   291      * Sets a new {@link CommandPresentationStrategy}. It also disposes to old one.
       
   292      *
       
   293      * @param commandPresentationStrategy
       
   294      */
       
   295     public void setPresentationStrategy( CommandPresentationStrategy commandPresentationStrategy ){
       
   296         CommandPresentationStrategy oldStrategy = strategy;
       
   297         strategy = commandPresentationStrategy;
       
   298         if (oldStrategy != null ){
       
   299             oldStrategy.dispose();
       
   300         }
       
   301     }
       
   302 
       
   303     private boolean isInFocusContext(Control control){
       
   304         Display display = control.getDisplay();
       
   305         Shell activeShell = display.getActiveShell();
       
   306         Control focused = display.getFocusControl();
       
   307         if( focused == null )return false;
       
   308         if(control.getShell() != activeShell) return false;
       
   309         if( control == focused ) return true;
       
   310         return isFocusAncestor(focused, control);
       
   311     }
       
   312 
       
   313     private boolean isFocusAncestor(Control node, Control parent){
       
   314         Control nodeParent = node.getParent();
       
   315         if( nodeParent == parent )return true;
       
   316         if (nodeParent == null || nodeParent == node.getShell() )return false;
       
   317         return isFocusAncestor(nodeParent, parent);
       
   318     }
       
   319 
       
   320 }