Source Code Cross Referenced for ContextAuthority.java in  » IDE-Eclipse » ui-workbench » org » eclipse » ui » internal » contexts » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » ui workbench » org.eclipse.ui.internal.contexts 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2005, 2007 IBM Corporation and others.
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         *     IBM Corporation - initial API and implementation
010:         *******************************************************************************/package org.eclipse.ui.internal.contexts;
011:
012:        import java.util.ArrayList;
013:        import java.util.Collection;
014:        import java.util.HashMap;
015:        import java.util.HashSet;
016:        import java.util.Iterator;
017:        import java.util.List;
018:        import java.util.Map;
019:        import java.util.Set;
020:        import java.util.WeakHashMap;
021:
022:        import org.eclipse.core.commands.contexts.ContextManager;
023:        import org.eclipse.core.commands.util.Tracing;
024:        import org.eclipse.core.expressions.Expression;
025:        import org.eclipse.core.runtime.Assert;
026:        import org.eclipse.swt.events.DisposeEvent;
027:        import org.eclipse.swt.events.DisposeListener;
028:        import org.eclipse.swt.widgets.Shell;
029:        import org.eclipse.ui.ActiveShellExpression;
030:        import org.eclipse.ui.ISources;
031:        import org.eclipse.ui.contexts.IContextActivation;
032:        import org.eclipse.ui.contexts.IContextService;
033:        import org.eclipse.ui.internal.misc.Policy;
034:        import org.eclipse.ui.internal.services.ExpressionAuthority;
035:
036:        /**
037:         * <p>
038:         * A central authority for deciding activation of contexts. This authority
039:         * listens to a variety of incoming sources, and updates the underlying context
040:         * manager if changes occur.
041:         * </p>
042:         * 
043:         * @since 3.1
044:         */
045:        public final class ContextAuthority extends ExpressionAuthority {
046:            public static final String DEFER_EVENTS = "org.eclipse.ui.internal.contexts.deferEvents"; //$NON-NLS-1$
047:            public static final String SEND_EVENTS = "org.eclipse.ui.internal.contexts.sendEvents"; //$NON-NLS-1$
048:
049:            /**
050:             * The default size of the set containing the activations to recompute. This
051:             * is more than enough to cover the average case.
052:             */
053:            private static final int ACTIVATIONS_TO_RECOMPUTE_SIZE = 4;
054:
055:            /**
056:             * Whether the context authority should kick into debugging mode. This
057:             * causes the unresolvable handler conflicts to be printed to the console.
058:             */
059:            private static final boolean DEBUG = Policy.DEBUG_CONTEXTS;
060:
061:            /**
062:             * Whether the performance information should be printed about the
063:             * performance of the context authority.
064:             */
065:            private static final boolean DEBUG_PERFORMANCE = Policy.DEBUG_CONTEXTS_PERFORMANCE;
066:
067:            /**
068:             * The name of the data tag containing the dispose listener information.
069:             */
070:            private static final String DISPOSE_LISTENER = "org.eclipse.ui.internal.contexts.ContextAuthority"; //$NON-NLS-1$
071:
072:            /**
073:             * The component name to print when displaying tracing information.
074:             */
075:            private static final String TRACING_COMPONENT = "CONTEXTS"; //$NON-NLS-1$
076:
077:            /**
078:             * A bucket sort of the context activations based on source priority. Each
079:             * activation will appear only once per set, but may appear in multiple
080:             * sets. If no activations are defined for a particular priority level, then
081:             * the array at that index will only contain <code>null</code>.
082:             */
083:            private final Set[] activationsBySourcePriority = new Set[33];
084:
085:            /**
086:             * This is a map of context activations (<code>Collection</code> of
087:             * <code>IContextActivation</code>) sorted by context identifier (<code>String</code>).
088:             * If there is only one context activation for a context, then the
089:             * <code>Collection</code> is replaced by a
090:             * <code>IContextActivation</code>. If there is no activation, the entry
091:             * should be removed entirely.
092:             */
093:            private final Map contextActivationsByContextId = new HashMap();
094:
095:            /**
096:             * The context manager that should be updated when the contexts are
097:             * changing.
098:             */
099:            private final ContextManager contextManager;
100:
101:            /**
102:             * The context service that should be used for authority-managed
103:             * shell-related contexts. This value is never <code>null</code>.
104:             */
105:            private final IContextService contextService;
106:
107:            /**
108:             * This is a map of shell to a list of activations. When a shell is
109:             * registered, it is added to this map with the list of activation that
110:             * should be submitted when the shell is active. When the shell is
111:             * deactivated, this same list should be withdrawn. A shell is removed from
112:             * this map using the {@link #unregisterShell(Shell)}method. This value may
113:             * be empty, but is never <code>null</code>. The <code>null</code> key
114:             * is reserved for active shells that have not been registered but have a
115:             * parent (i.e., default dialog service).
116:             */
117:            private final Map registeredWindows = new WeakHashMap();
118:
119:            /**
120:             * Constructs a new instance of <code>ContextAuthority</code>.
121:             * 
122:             * @param contextManager
123:             *            The context manager from which contexts can be retrieved (to
124:             *            update their active state); must not be <code>null</code>.
125:             * @param contextService
126:             *            The workbench context service for which this authority is
127:             *            acting. This allows the authority to manage shell-specific
128:             *            contexts. This value must not be <code>null</code>.
129:             */
130:            ContextAuthority(final ContextManager contextManager,
131:                    final IContextService contextService) {
132:                if (contextManager == null) {
133:                    throw new NullPointerException(
134:                            "The context authority needs a context manager"); //$NON-NLS-1$
135:                }
136:                if (contextService == null) {
137:                    throw new NullPointerException(
138:                            "The context authority needs an evaluation context"); //$NON-NLS-1$
139:                }
140:
141:                this .contextManager = contextManager;
142:                this .contextService = contextService;
143:            }
144:
145:            /**
146:             * Activates a context on the workbench. This will add it to a master list.
147:             * 
148:             * @param activation
149:             *            The activation; must not be <code>null</code>.
150:             */
151:            final void activateContext(final IContextActivation activation) {
152:                // First we update the contextActivationsByContextId map.
153:                final String contextId = activation.getContextId();
154:                if (DEFER_EVENTS.equals(contextId)
155:                        || SEND_EVENTS.equals(contextId)) {
156:                    contextManager.addActiveContext(contextId);
157:                    return;
158:                }
159:                final Object value = contextActivationsByContextId
160:                        .get(contextId);
161:                if (value instanceof  Collection) {
162:                    final Collection contextActivations = (Collection) value;
163:                    if (!contextActivations.contains(activation)) {
164:                        contextActivations.add(activation);
165:                        updateContext(contextId,
166:                                containsActive(contextActivations));
167:                    }
168:                } else if (value instanceof  IContextActivation) {
169:                    if (value != activation) {
170:                        final Collection contextActivations = new ArrayList(2);
171:                        contextActivations.add(value);
172:                        contextActivations.add(activation);
173:                        contextActivationsByContextId.put(contextId,
174:                                contextActivations);
175:                        updateContext(contextId,
176:                                containsActive(contextActivations));
177:                    }
178:                } else {
179:                    contextActivationsByContextId.put(contextId, activation);
180:                    updateContext(contextId, evaluate(activation));
181:                }
182:
183:                // Next we update the source priority bucket sort of activations.
184:                final int sourcePriority = activation.getSourcePriority();
185:                for (int i = 1; i <= 32; i++) {
186:                    if ((sourcePriority & (1 << i)) != 0) {
187:                        Set activations = activationsBySourcePriority[i];
188:                        if (activations == null) {
189:                            activations = new HashSet(1);
190:                            activationsBySourcePriority[i] = activations;
191:                        }
192:                        activations.add(activation);
193:                    }
194:                }
195:            }
196:
197:            /**
198:             * Checks whether the new active shell is registered. If it is already
199:             * registered, then it does no work. If it is not registered, then it checks
200:             * what type of contexts the shell should have by default. This is
201:             * determined by parenting. A shell with no parent receives no contexts. A
202:             * shell with a parent, receives the dialog contexts.
203:             * 
204:             * @param newShell
205:             *            The newly active shell; may be <code>null</code> or
206:             *            disposed.
207:             * @param oldShell
208:             *            The previously active shell; may be <code>null</code> or
209:             *            disposed.
210:             */
211:            private final void checkWindowType(final Shell newShell,
212:                    final Shell oldShell) {
213:                /*
214:                 * If the previous active shell was recognized as a dialog by default,
215:                 * then remove its submissions.
216:                 */
217:                Collection oldActivations = (Collection) registeredWindows
218:                        .get(oldShell);
219:                if (oldActivations == null) {
220:                    /*
221:                     * The old shell wasn't registered. So, we need to check if it was
222:                     * considered a dialog by default.
223:                     */
224:                    oldActivations = (Collection) registeredWindows.get(null);
225:                    if (oldActivations != null) {
226:                        final Iterator oldActivationItr = oldActivations
227:                                .iterator();
228:                        while (oldActivationItr.hasNext()) {
229:                            final IContextActivation activation = (IContextActivation) oldActivationItr
230:                                    .next();
231:                            deactivateContext(activation);
232:                        }
233:                    }
234:                }
235:
236:                /*
237:                 * If the new active shell is recognized as a dialog by default, then
238:                 * create some submissions, remember them, and submit them for
239:                 * processing.
240:                 */
241:                if ((newShell != null) && (!newShell.isDisposed())) {
242:                    final Collection newActivations;
243:
244:                    if ((newShell.getParent() != null)
245:                            && (registeredWindows.get(newShell) == null)) {
246:                        // This is a dialog by default.
247:                        newActivations = new ArrayList();
248:                        final Expression expression = new ActiveShellExpression(
249:                                newShell);
250:                        final IContextActivation dialogWindowActivation = new ContextActivation(
251:                                IContextService.CONTEXT_ID_DIALOG_AND_WINDOW,
252:                                expression, contextService);
253:                        activateContext(dialogWindowActivation);
254:                        newActivations.add(dialogWindowActivation);
255:                        final IContextActivation dialogActivation = new ContextActivation(
256:                                IContextService.CONTEXT_ID_DIALOG, expression,
257:                                contextService);
258:                        activateContext(dialogActivation);
259:                        newActivations.add(dialogActivation);
260:                        registeredWindows.put(null, newActivations);
261:
262:                        /*
263:                         * Make sure the submissions will be removed in event of
264:                         * disposal. This is really just a paranoid check. The
265:                         * "oldSubmissions" code above should take care of this.
266:                         */
267:                        newShell.addDisposeListener(new DisposeListener() {
268:
269:                            /*
270:                             * (non-Javadoc)
271:                             * 
272:                             * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
273:                             */
274:                            public void widgetDisposed(DisposeEvent e) {
275:                                registeredWindows.remove(null);
276:                                if (!newShell.isDisposed()) {
277:                                    newShell.removeDisposeListener(this );
278:                                }
279:
280:                                /*
281:                                 * In the case where a dispose has happened, we are
282:                                 * expecting an activation event to arrive at some point
283:                                 * in the future. If we process the submissions now,
284:                                 * then we will update the activeShell before
285:                                 * checkWindowType is called. This means that dialogs
286:                                 * won't be recognized as dialogs.
287:                                 */
288:                                final Iterator newActivationItr = newActivations
289:                                        .iterator();
290:                                while (newActivationItr.hasNext()) {
291:                                    deactivateContext((IContextActivation) newActivationItr
292:                                            .next());
293:                                }
294:                            }
295:                        });
296:
297:                    } else {
298:                        // Shells that are not dialogs by default must register.
299:                        newActivations = null;
300:
301:                    }
302:                }
303:            }
304:
305:            /**
306:             * Returns a subset of the given <code>activations</code> containing only
307:             * those that are active
308:             * 
309:             * @param activations
310:             *            The activations to trim; must not be <code>null</code>, but
311:             *            may be empty.
312:             * @return <code>true</code> if there is at least one active context;
313:             *         <code>false</code> otherwise.
314:             */
315:            private final boolean containsActive(final Collection activations) {
316:                final Iterator activationItr = activations.iterator();
317:                while (activationItr.hasNext()) {
318:                    final IContextActivation activation = (IContextActivation) activationItr
319:                            .next();
320:                    if (evaluate(activation)) {
321:                        return true;
322:                    }
323:                }
324:
325:                return false;
326:            }
327:
328:            /**
329:             * Removes an activation for a context on the workbench. This will remove it
330:             * from the master list, and update the appropriate context, if necessary.
331:             * 
332:             * @param activation
333:             *            The activation; must not be <code>null</code>.
334:             */
335:            final void deactivateContext(final IContextActivation activation) {
336:                // First we update the handlerActivationsByCommandId map.
337:                final String contextId = activation.getContextId();
338:                if (DEFER_EVENTS.equals(contextId)
339:                        || SEND_EVENTS.equals(contextId)) {
340:                    return;
341:                }
342:                final Object value = contextActivationsByContextId
343:                        .get(contextId);
344:                if (value instanceof  Collection) {
345:                    final Collection contextActivations = (Collection) value;
346:                    if (contextActivations.contains(activation)) {
347:                        contextActivations.remove(activation);
348:                        if (contextActivations.isEmpty()) {
349:                            contextActivationsByContextId.remove(contextId);
350:                            updateContext(contextId, false);
351:
352:                        } else if (contextActivations.size() == 1) {
353:                            final IContextActivation remainingActivation = (IContextActivation) contextActivations
354:                                    .iterator().next();
355:                            contextActivationsByContextId.put(contextId,
356:                                    remainingActivation);
357:                            updateContext(contextId,
358:                                    evaluate(remainingActivation));
359:
360:                        } else {
361:                            updateContext(contextId,
362:                                    containsActive(contextActivations));
363:                        }
364:                    }
365:                } else if (value instanceof  IContextActivation) {
366:                    if (value == activation) {
367:                        contextActivationsByContextId.remove(contextId);
368:                        updateContext(contextId, false);
369:                    }
370:                }
371:
372:                // Next we update the source priority bucket sort of activations.
373:                final int sourcePriority = activation.getSourcePriority();
374:                for (int i = 1; i <= 32; i++) {
375:                    if ((sourcePriority & (1 << i)) != 0) {
376:                        final Set activations = activationsBySourcePriority[i];
377:                        if (activations == null) {
378:                            continue;
379:                        }
380:                        activations.remove(activation);
381:                        if (activations.isEmpty()) {
382:                            activationsBySourcePriority[i] = null;
383:                        }
384:                    }
385:                }
386:            }
387:
388:            /**
389:             * Returns the currently active shell.
390:             * 
391:             * @return The currently active shell; may be <code>null</code>.
392:             */
393:            final Shell getActiveShell() {
394:                return (Shell) getVariable(ISources.ACTIVE_SHELL_NAME);
395:            }
396:
397:            /**
398:             * Returns the shell type for the given shell.
399:             * 
400:             * @param shell
401:             *            The shell for which the type should be determined. If this
402:             *            value is <code>null</code>, then
403:             *            <code>IWorkbenchContextSupport.TYPE_NONE</code> is returned.
404:             * @return <code>IWorkbenchContextSupport.TYPE_WINDOW</code>,
405:             *         <code>IWorkbenchContextSupport.TYPE_DIALOG</code>, or
406:             *         <code>IWorkbenchContextSupport.TYPE_NONE</code>.
407:             */
408:            public final int getShellType(final Shell shell) {
409:                // If the shell is null, then return none.
410:                if (shell == null) {
411:                    return IContextService.TYPE_NONE;
412:                }
413:
414:                final Collection activations = (Collection) registeredWindows
415:                        .get(shell);
416:                if (activations != null) {
417:                    // The shell is registered, so check what type it was registered as.
418:                    if (activations.isEmpty()) {
419:                        // It was registered as none.
420:                        return IContextService.TYPE_NONE;
421:                    }
422:
423:                    // Look for the right type of context id.
424:                    final Iterator activationItr = activations.iterator();
425:                    while (activationItr.hasNext()) {
426:                        final IContextActivation activation = (IContextActivation) activationItr
427:                                .next();
428:                        final String contextId = activation.getContextId();
429:                        if (contextId == IContextService.CONTEXT_ID_DIALOG) {
430:                            return IContextService.TYPE_DIALOG;
431:                        } else if (contextId == IContextService.CONTEXT_ID_WINDOW) {
432:                            return IContextService.TYPE_WINDOW;
433:                        }
434:                    }
435:
436:                    // This shouldn't be possible.
437:                    Assert
438:                            .isTrue(
439:                                    false,
440:                                    "A registered shell should have at least one submission matching TYPE_WINDOW or TYPE_DIALOG"); //$NON-NLS-1$
441:                    return IContextService.TYPE_NONE; // not reachable
442:
443:                } else if (shell.getParent() != null) {
444:                    /*
445:                     * The shell is not registered, but it has a parent. It is therefore
446:                     * considered a dialog by default.
447:                     */
448:                    return IContextService.TYPE_DIALOG;
449:
450:                } else {
451:                    /*
452:                     * The shell is not registered, but has no parent. It gets no key
453:                     * bindings.
454:                     */
455:                    return IContextService.TYPE_NONE;
456:                }
457:            }
458:
459:            /**
460:             * <p>
461:             * Registers a shell to automatically promote or demote some basic types of
462:             * contexts. The "In Dialogs" and "In Windows" contexts are provided by the
463:             * system. This a convenience method to ensure that these contexts are
464:             * promoted when the given is shell is active.
465:             * </p>
466:             * <p>
467:             * If a shell is registered as a window, then the "In Windows" context is
468:             * enabled when that shell is active. If a shell is registered as a dialog --
469:             * or is not registered, but has a parent shell -- then the "In Dialogs"
470:             * context is enabled when that shell is active. If the shell is registered
471:             * as none -- or is not registered, but has no parent shell -- then the
472:             * neither of the contexts will be enabled (by us -- someone else can always
473:             * enabled them).
474:             * </p>
475:             * <p>
476:             * If the provided shell has already been registered, then this method will
477:             * change the registration.
478:             * </p>
479:             * 
480:             * @param shell
481:             *            The shell to register for key bindings; must not be
482:             *            <code>null</code>.
483:             * @param type
484:             *            The type of shell being registered. This value must be one of
485:             *            the constants given in this interface.
486:             * 
487:             * @return <code>true</code> if the shell had already been registered
488:             *         (i.e., the registration has changed); <code>false</code>
489:             *         otherwise.
490:             */
491:            public final boolean registerShell(final Shell shell, final int type) {
492:                // We do not allow null shell registration. It is reserved.
493:                if (shell == null) {
494:                    throw new NullPointerException("The shell was null"); //$NON-NLS-1$
495:                }
496:
497:                // Debugging output
498:                if (DEBUG) {
499:                    final StringBuffer buffer = new StringBuffer(
500:                            "register shell '"); //$NON-NLS-1$
501:                    buffer.append(shell);
502:                    buffer.append("' as "); //$NON-NLS-1$
503:                    switch (type) {
504:                    case IContextService.TYPE_DIALOG:
505:                        buffer.append("dialog"); //$NON-NLS-1$
506:                        break;
507:                    case IContextService.TYPE_WINDOW:
508:                        buffer.append("window"); //$NON-NLS-1$
509:                        break;
510:                    case IContextService.TYPE_NONE:
511:                        buffer.append("none"); //$NON-NLS-1$
512:                        break;
513:                    default:
514:                        buffer.append("unknown"); //$NON-NLS-1$
515:                        break;
516:                    }
517:                    Tracing.printTrace(TRACING_COMPONENT, buffer.toString());
518:                }
519:
520:                // Build the list of submissions.
521:                final List activations = new ArrayList();
522:                Expression expression;
523:                IContextActivation dialogWindowActivation;
524:                switch (type) {
525:                case IContextService.TYPE_DIALOG:
526:                    expression = new ActiveShellExpression(shell);
527:                    dialogWindowActivation = new ContextActivation(
528:                            IContextService.CONTEXT_ID_DIALOG_AND_WINDOW,
529:                            expression, contextService);
530:                    activateContext(dialogWindowActivation);
531:                    activations.add(dialogWindowActivation);
532:                    final IContextActivation dialogActivation = new ContextActivation(
533:                            IContextService.CONTEXT_ID_DIALOG, expression,
534:                            contextService);
535:                    activateContext(dialogActivation);
536:                    activations.add(dialogActivation);
537:                    break;
538:                case IContextService.TYPE_NONE:
539:                    break;
540:                case IContextService.TYPE_WINDOW:
541:                    expression = new ActiveShellExpression(shell);
542:                    dialogWindowActivation = new ContextActivation(
543:                            IContextService.CONTEXT_ID_DIALOG_AND_WINDOW,
544:                            expression, contextService);
545:                    activateContext(dialogWindowActivation);
546:                    activations.add(dialogWindowActivation);
547:                    final IContextActivation windowActivation = new ContextActivation(
548:                            IContextService.CONTEXT_ID_WINDOW, expression,
549:                            contextService);
550:                    activateContext(windowActivation);
551:                    activations.add(windowActivation);
552:                    break;
553:                default:
554:                    throw new IllegalArgumentException(
555:                            "The type is not recognized: " //$NON-NLS-1$
556:                                    + type);
557:                }
558:
559:                // Check to see if the activations are already present.
560:                boolean returnValue = false;
561:                final Collection previousActivations = (Collection) registeredWindows
562:                        .get(shell);
563:                if (previousActivations != null) {
564:                    returnValue = true;
565:                    final Iterator previousActivationItr = previousActivations
566:                            .iterator();
567:                    while (previousActivationItr.hasNext()) {
568:                        final IContextActivation activation = (IContextActivation) previousActivationItr
569:                                .next();
570:                        deactivateContext(activation);
571:                    }
572:                }
573:
574:                // Add the new submissions, and force some reprocessing to occur.
575:                registeredWindows.put(shell, activations);
576:
577:                /*
578:                 * Remember the dispose listener so that we can remove it later if we
579:                 * unregister the shell.
580:                 */
581:                final DisposeListener shellDisposeListener = new DisposeListener() {
582:
583:                    /*
584:                     * (non-Javadoc)
585:                     * 
586:                     * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
587:                     */
588:                    public void widgetDisposed(DisposeEvent e) {
589:                        registeredWindows.remove(shell);
590:                        if (!shell.isDisposed()) {
591:                            shell.removeDisposeListener(this );
592:                        }
593:
594:                        /*
595:                         * In the case where a dispose has happened, we are expecting an
596:                         * activation event to arrive at some point in the future. If we
597:                         * process the submissions now, then we will update the
598:                         * activeShell before checkWindowType is called. This means that
599:                         * dialogs won't be recognized as dialogs.
600:                         */
601:                        final Iterator activationItr = activations.iterator();
602:                        while (activationItr.hasNext()) {
603:                            deactivateContext((IContextActivation) activationItr
604:                                    .next());
605:                        }
606:                    }
607:                };
608:
609:                // Make sure the submissions will be removed in event of disposal.
610:                shell.addDisposeListener(shellDisposeListener);
611:                shell.setData(DISPOSE_LISTENER, shellDisposeListener);
612:
613:                return returnValue;
614:            }
615:
616:            /**
617:             * Carries out the actual source change notification. It assumed that by the
618:             * time this method is called, <code>context</code> is up-to-date with the
619:             * current state of the application.
620:             * 
621:             * @param sourcePriority
622:             *            A bit mask of all the source priorities that have changed.
623:             */
624:            protected final void sourceChanged(final int sourcePriority) {
625:                // If tracing, then track how long it takes to process the activations.
626:                long startTime = 0L;
627:                if (DEBUG_PERFORMANCE) {
628:                    startTime = System.currentTimeMillis();
629:                }
630:
631:                /*
632:                 * In this first phase, we cycle through all of the activations that
633:                 * could have potentially changed. Each such activation is added to a
634:                 * set for future processing. We add it to a set so that we avoid
635:                 * handling any individual activation more than once.
636:                 */
637:                final Set activationsToRecompute = new HashSet(
638:                        ACTIVATIONS_TO_RECOMPUTE_SIZE);
639:                for (int i = 1; i <= 32; i++) {
640:                    if ((sourcePriority & (1 << i)) != 0) {
641:                        final Collection activations = activationsBySourcePriority[i];
642:                        if (activations != null) {
643:                            final Iterator activationItr = activations
644:                                    .iterator();
645:                            while (activationItr.hasNext()) {
646:                                activationsToRecompute
647:                                        .add(activationItr.next());
648:                            }
649:                        }
650:                    }
651:                }
652:
653:                /*
654:                 * For every activation, we recompute its active state, and check
655:                 * whether it has changed. If it has changed, then we take note of the
656:                 * context identifier so we can update the context later.
657:                 */
658:                final Collection changedContextIds = new ArrayList(
659:                        activationsToRecompute.size());
660:                final Iterator activationItr = activationsToRecompute
661:                        .iterator();
662:                while (activationItr.hasNext()) {
663:                    final IContextActivation activation = (IContextActivation) activationItr
664:                            .next();
665:                    final boolean currentActive = evaluate(activation);
666:                    activation.clearResult();
667:                    final boolean newActive = evaluate(activation);
668:                    if (newActive != currentActive) {
669:                        changedContextIds.add(activation.getContextId());
670:                    }
671:                }
672:
673:                try {
674:                    contextManager.addActiveContext(DEFER_EVENTS);
675:                    /*
676:                     * For every context identifier with a changed activation, we
677:                     * resolve conflicts and trigger an update.
678:                     */
679:                    final Iterator changedContextIdItr = changedContextIds
680:                            .iterator();
681:                    while (changedContextIdItr.hasNext()) {
682:                        final String contextId = (String) changedContextIdItr
683:                                .next();
684:                        final Object value = contextActivationsByContextId
685:                                .get(contextId);
686:                        if (value instanceof  IContextActivation) {
687:                            final IContextActivation activation = (IContextActivation) value;
688:                            updateContext(contextId, evaluate(activation));
689:                        } else if (value instanceof  Collection) {
690:                            updateContext(contextId,
691:                                    containsActive((Collection) value));
692:                        } else {
693:                            updateContext(contextId, false);
694:                        }
695:                    }
696:                } finally {
697:                    contextManager.addActiveContext(SEND_EVENTS);
698:                }
699:
700:                // If tracing performance, then print the results.
701:                if (DEBUG_PERFORMANCE) {
702:                    final long elapsedTime = System.currentTimeMillis()
703:                            - startTime;
704:                    final int size = activationsToRecompute.size();
705:                    if (size > 0) {
706:                        Tracing
707:                                .printTrace(
708:                                        TRACING_COMPONENT,
709:                                        size
710:                                                + " activations recomputed in " + elapsedTime + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
711:                    }
712:                }
713:            }
714:
715:            /**
716:             * <p>
717:             * Unregisters a shell that was previously registered. After this method
718:             * completes, the shell will be treated as if it had never been registered
719:             * at all. If you have registered a shell, you should ensure that this
720:             * method is called when the shell is disposed. Otherwise, a potential
721:             * memory leak will exist.
722:             * </p>
723:             * <p>
724:             * If the shell was never registered, or if the shell is <code>null</code>,
725:             * then this method returns <code>false</code> and does nothing.
726:             * 
727:             * @param shell
728:             *            The shell to be unregistered; does nothing if this value is
729:             *            <code>null</code>.
730:             * 
731:             * @return <code>true</code> if the shell had been registered;
732:             *         <code>false</code> otherwise.
733:             */
734:            public final boolean unregisterShell(final Shell shell) {
735:                // Don't allow this method to play with the special null slot.
736:                if (shell == null) {
737:                    return false;
738:                }
739:
740:                /*
741:                 * If we're unregistering the shell but we're not about to dispose it,
742:                 * then we'll end up leaking the DisposeListener unless we remove it
743:                 * here.
744:                 */
745:                if (!shell.isDisposed()) {
746:                    final DisposeListener oldListener = (DisposeListener) shell
747:                            .getData(DISPOSE_LISTENER);
748:                    if (oldListener != null) {
749:                        shell.removeDisposeListener(oldListener);
750:                    }
751:                }
752:
753:                Collection previousActivations = (Collection) registeredWindows
754:                        .get(shell);
755:                if (previousActivations != null) {
756:                    registeredWindows.remove(shell);
757:
758:                    final Iterator previousActivationItr = previousActivations
759:                            .iterator();
760:                    while (previousActivationItr.hasNext()) {
761:                        final IContextActivation activation = (IContextActivation) previousActivationItr
762:                                .next();
763:                        deactivateContext(activation);
764:                    }
765:                    return true;
766:                }
767:
768:                return false;
769:            }
770:
771:            /**
772:             * Updates the context with the given context activation.
773:             * 
774:             * @param contextId
775:             *            The identifier of the context which should be updated; must
776:             *            not be <code>null</code>.
777:             * @param active
778:             *            Whether the context should be active; <code>false</code>
779:             *            otherwise.
780:             */
781:            private final void updateContext(final String contextId,
782:                    final boolean active) {
783:                if (active) {
784:                    contextManager.addActiveContext(contextId);
785:                } else {
786:                    contextManager.removeActiveContext(contextId);
787:                }
788:            }
789:
790:            /**
791:             * Updates this authority's evaluation context. If the changed variable is
792:             * the <code>ISources.ACTIVE_SHELL_NAME</code> variable, then this also
793:             * triggers an update of the shell-specific contexts. For example, if a
794:             * dialog becomes active, then the dialog context will be activated by this
795:             * method.
796:             * 
797:             * @param name
798:             *            The name of the variable to update; must not be
799:             *            <code>null</code>.
800:             * @param value
801:             *            The new value of the variable. If this value is
802:             *            <code>null</code>, then the variable is removed.
803:             */
804:            protected final void updateEvaluationContext(final String name,
805:                    final Object value) {
806:                /*
807:                 * Bug 84056. If we update the active workbench window, then we risk
808:                 * falling back to that shell when the active shell has registered as
809:                 * "none".
810:                 */
811:                if ((name != null)
812:                        && (!ISources.ACTIVE_WORKBENCH_WINDOW_SHELL_NAME
813:                                .equals(name))) {
814:                    /*
815:                     * We need to track shell activation ourselves, as some special
816:                     * contexts are automatically activated in response to different
817:                     * types of shells becoming active.
818:                     */
819:                    if (ISources.ACTIVE_SHELL_NAME.equals(name)) {
820:                        checkWindowType((Shell) value,
821:                                (Shell) getVariable(ISources.ACTIVE_SHELL_NAME));
822:                    }
823:
824:                    // Update the evaluation context itself.
825:                    changeVariable(name, value);
826:                }
827:            }
828:
829:            /**
830:             * <p>
831:             * Bug 95792. A mechanism by which the key binding architecture can force an
832:             * update of the contexts (based on the active shell) before trying to
833:             * execute a command. This mechanism is required for GTK+ only.
834:             * </p>
835:             * <p>
836:             * DO NOT CALL THIS METHOD.
837:             * </p>
838:             */
839:            final void updateShellKludge() {
840:                updateCurrentState();
841:                sourceChanged(ISources.ACTIVE_SHELL);
842:            }
843:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.