Source Code Cross Referenced for StructuredViewer.java in  » IDE-Eclipse » jface » org » eclipse » jface » viewers » 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 » jface » org.eclipse.jface.viewers 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *     Tom Schindl - bug 151205
0011:         *******************************************************************************/package org.eclipse.jface.viewers;
0012:
0013:        import java.util.ArrayList;
0014:        import java.util.Arrays;
0015:        import java.util.Iterator;
0016:        import java.util.List;
0017:
0018:        import org.eclipse.core.runtime.ListenerList;
0019:        import org.eclipse.core.runtime.Assert;
0020:        import org.eclipse.jface.util.IOpenEventListener;
0021:        import org.eclipse.jface.util.OpenStrategy;
0022:        import org.eclipse.jface.util.SafeRunnable;
0023:        import org.eclipse.swt.custom.TableTreeItem;
0024:        import org.eclipse.swt.dnd.DragSource;
0025:        import org.eclipse.swt.dnd.DragSourceListener;
0026:        import org.eclipse.swt.dnd.DropTarget;
0027:        import org.eclipse.swt.dnd.DropTargetListener;
0028:        import org.eclipse.swt.dnd.Transfer;
0029:        import org.eclipse.swt.events.DisposeEvent;
0030:        import org.eclipse.swt.events.SelectionAdapter;
0031:        import org.eclipse.swt.events.SelectionEvent;
0032:        import org.eclipse.swt.events.SelectionListener;
0033:        import org.eclipse.swt.graphics.Color;
0034:        import org.eclipse.swt.graphics.Font;
0035:        import org.eclipse.swt.widgets.Control;
0036:        import org.eclipse.swt.widgets.Item;
0037:        import org.eclipse.swt.widgets.TableItem;
0038:        import org.eclipse.swt.widgets.TreeItem;
0039:        import org.eclipse.swt.widgets.Widget;
0040:
0041:        /**
0042:         * Abstract base implementation for structure-oriented viewers (trees, lists,
0043:         * tables). Supports custom sorting, filtering, and rendering.
0044:         * <p>
0045:         * Any number of viewer filters can be added to this viewer (using
0046:         * <code>addFilter</code>). When the viewer receives an update, it asks each
0047:         * of its filters if it is out of date, and refilters elements as required.
0048:         * </p>
0049:         * 
0050:         * @see ViewerFilter
0051:         * @see ViewerComparator
0052:         */
0053:        public abstract class StructuredViewer extends ContentViewer implements 
0054:                IPostSelectionProvider {
0055:
0056:            /**
0057:             * A map from the viewer's model elements to SWT widgets. (key type:
0058:             * <code>Object</code>, value type: <code>Widget</code>, or <code>Widget[]</code>).
0059:             * <code>null</code> means that the element map is disabled.
0060:             */
0061:            private CustomHashtable elementMap;
0062:
0063:            /**
0064:             * The comparer to use for comparing elements, or <code>null</code> to use
0065:             * the default <code>equals</code> and <code>hashCode</code> methods on
0066:             * the element itself.
0067:             */
0068:            private IElementComparer comparer;
0069:
0070:            /**
0071:             * This viewer's comparator used for sorting. <code>null</code> means there is no comparator.
0072:             */
0073:            private ViewerComparator sorter;
0074:
0075:            /**
0076:             * This viewer's filters (element type: <code>ViewerFilter</code>).
0077:             * <code>null</code> means there are no filters.
0078:             */
0079:            private List filters;
0080:
0081:            /**
0082:             * Indicates whether a selection change is in progress on this viewer.
0083:             * 
0084:             * @see #setSelection(ISelection, boolean)
0085:             */
0086:            private boolean inChange;
0087:
0088:            /**
0089:             * Used while a selection change is in progress on this viewer to indicates
0090:             * whether the selection should be restored.
0091:             * 
0092:             * @see #setSelection(ISelection, boolean)
0093:             */
0094:            private boolean restoreSelection;
0095:
0096:            /**
0097:             * List of double-click state listeners (element type:
0098:             * <code>IDoubleClickListener</code>).
0099:             * 
0100:             * @see #fireDoubleClick
0101:             */
0102:            private ListenerList doubleClickListeners = new ListenerList();
0103:
0104:            /**
0105:             * List of open listeners (element type:
0106:             * <code>ISelectionActivateListener</code>).
0107:             * 
0108:             * @see #fireOpen
0109:             */
0110:            private ListenerList openListeners = new ListenerList();
0111:
0112:            /**
0113:             * List of post selection listeners (element type:
0114:             * <code>ISelectionActivateListener</code>).
0115:             * 
0116:             * @see #firePostSelectionChanged
0117:             */
0118:            private ListenerList postSelectionChangedListeners = new ListenerList();
0119:
0120:            /**
0121:             * The colorAndFontCollector is an object used by viewers that
0122:             * support the IColorProvider, the IFontProvider and/or the 
0123:             * IViewerLabelProvider for color and font updates.
0124:             * Initialize it to have no color or font providing
0125:             * initially.
0126:             * @since 3.1
0127:             */
0128:            private ColorAndFontCollector colorAndFontCollector = new ColorAndFontCollector();
0129:
0130:            /**
0131:             * Empty array of widgets.
0132:             */
0133:            private static Widget[] NO_WIDGETS = new Widget[0];
0134:
0135:            /**
0136:             * The ColorAndFontCollector is a helper class for viewers
0137:             * that have color and font support ad optionally decorators.
0138:             * @see IColorDecorator
0139:             * @see IFontDecorator
0140:             * @see IColorProvider
0141:             * @see IFontProvider
0142:             * @see IDecoration
0143:             */
0144:            protected class ColorAndFontCollectorWithProviders extends
0145:                    ColorAndFontCollector {
0146:
0147:                IColorProvider colorProvider;
0148:
0149:                IFontProvider fontProvider;
0150:
0151:                /**
0152:                 * Create a new instance of the receiver using the supplied
0153:                 * label provider. If it is an IColorProvider or IFontProvider
0154:                 * set these values up.
0155:                 * @param provider IBaseLabelProvider
0156:                 * @see IColorProvider
0157:                 * @see IFontProvider
0158:                 */
0159:                public ColorAndFontCollectorWithProviders(
0160:                        IBaseLabelProvider provider) {
0161:                    super ();
0162:                    if (provider instanceof  IColorProvider) {
0163:                        colorProvider = (IColorProvider) provider;
0164:                    }
0165:                    if (provider instanceof  IFontProvider) {
0166:                        fontProvider = (IFontProvider) provider;
0167:                    }
0168:                }
0169:
0170:                /* (non-Javadoc)
0171:                 * @see org.eclipse.jface.viewers.StructuredViewer.ColorAndFontManager#setFontsAndColors(java.lang.Object)
0172:                 */
0173:                public void setFontsAndColors(Object element) {
0174:
0175:                    if (fontProvider != null) {
0176:                        if (font == null) {
0177:                            font = fontProvider.getFont(element);
0178:                        }
0179:                    }
0180:
0181:                    if (colorProvider == null) {
0182:                        return;
0183:                    }
0184:                    //Set the colors if they are not set yet
0185:                    if (background == null) {
0186:                        background = colorProvider.getBackground(element);
0187:                    }
0188:
0189:                    if (foreground == null) {
0190:                        foreground = colorProvider.getForeground(element);
0191:                    }
0192:                }
0193:
0194:                /**
0195:                 * Apply the fonts and colors to the control if
0196:                 * required.
0197:                 * @param control
0198:                 */
0199:                public void applyFontsAndColors(TableItem control) {
0200:
0201:                    if (colorProvider == null) {
0202:                        if (usedDecorators) {
0203:                            //If there is no provider only apply set values
0204:                            if (background != null) {
0205:                                control.setBackground(background);
0206:                            }
0207:
0208:                            if (foreground != null) {
0209:                                control.setForeground(foreground);
0210:                            }
0211:                        }
0212:                    } else {
0213:                        //Always set the value if there is a provider
0214:                        control.setBackground(background);
0215:                        control.setForeground(foreground);
0216:                    }
0217:
0218:                    if (fontProvider == null) {
0219:                        if (usedDecorators && font != null) {
0220:                            control.setFont(font);
0221:                        }
0222:                    } else {
0223:                        control.setFont(font);
0224:                    }
0225:
0226:                    clear();
0227:                }
0228:
0229:                /* (non-Javadoc)
0230:                 * @see org.eclipse.jface.viewers.StructuredViewer.ColorAndFontManager#applyFontsAndColors(org.eclipse.swt.widgets.TreeItem)
0231:                 */
0232:                public void applyFontsAndColors(TreeItem control) {
0233:
0234:                    if (colorProvider == null) {
0235:                        if (usedDecorators) {
0236:                            //If there is no provider only apply set values
0237:                            if (background != null) {
0238:                                control.setBackground(background);
0239:                            }
0240:
0241:                            if (foreground != null) {
0242:                                control.setForeground(foreground);
0243:                            }
0244:                        }
0245:                    } else {
0246:                        //Always set the value if there is a provider
0247:                        control.setBackground(background);
0248:                        control.setForeground(foreground);
0249:                    }
0250:
0251:                    if (fontProvider == null) {
0252:                        if (usedDecorators && font != null) {
0253:                            control.setFont(font);
0254:                        }
0255:                    } else {
0256:                        control.setFont(font);
0257:                    }
0258:
0259:                    clear();
0260:                }
0261:
0262:                /* (non-Javadoc)
0263:                 * @see org.eclipse.jface.viewers.StructuredViewer.ColorAndFontManager#applyFontsAndColors(org.eclipse.swt.custom.TableTreeItem)
0264:                 */
0265:                public void applyFontsAndColors(TableTreeItem control) {
0266:
0267:                    if (colorProvider == null) {
0268:                        if (usedDecorators) {
0269:                            //If there is no provider only apply set values
0270:                            if (background != null) {
0271:                                control.setBackground(background);
0272:                            }
0273:
0274:                            if (foreground != null) {
0275:                                control.setForeground(foreground);
0276:                            }
0277:                        }
0278:                    } else {
0279:                        //Always set the value if there is a provider
0280:                        control.setBackground(background);
0281:                        control.setForeground(foreground);
0282:                    }
0283:
0284:                    if (fontProvider == null) {
0285:                        if (usedDecorators && font != null) {
0286:                            control.setFont(font);
0287:                        }
0288:                    } else {
0289:                        control.setFont(font);
0290:                    }
0291:
0292:                    clear();
0293:                }
0294:
0295:            }
0296:
0297:            /**
0298:             * The ColorAndFontCollector collects fonts and colors without a
0299:             * a color or font provider.
0300:             *
0301:             */
0302:            protected class ColorAndFontCollector {
0303:
0304:                Color foreground = null;
0305:
0306:                Color background = null;
0307:
0308:                Font font = null;
0309:
0310:                boolean usedDecorators = false;
0311:
0312:                /**
0313:                 * Create a new instance of the receiver with
0314:                 * no color and font provider.	
0315:                 */
0316:                public ColorAndFontCollector() {
0317:                    super ();
0318:                }
0319:
0320:                /**
0321:                 * Clear all of the results.
0322:                 */
0323:                public void clear() {
0324:                    foreground = null;
0325:                    background = null;
0326:                    font = null;
0327:                    usedDecorators = false;
0328:                }
0329:
0330:                /**
0331:                 * Set the initial fonts and colors for the element from the
0332:                 * content providers.
0333:                 * @param element Object
0334:                 */
0335:                public void setFontsAndColors(Object element) {
0336:                    //Do nothing if there are no providers
0337:                }
0338:
0339:                /**
0340:                 * Set that decorators were applied.
0341:                 */
0342:                public void setUsedDecorators() {
0343:                    this .usedDecorators = true;
0344:                }
0345:
0346:                /**
0347:                 * Apply the fonts and colors to the control if
0348:                 * required.
0349:                 * @param control
0350:                 */
0351:                public void applyFontsAndColors(TableItem control) {
0352:
0353:                    if (usedDecorators) {
0354:                        //If there is no provider only apply set values
0355:                        if (background != null) {
0356:                            control.setBackground(background);
0357:                        }
0358:
0359:                        if (foreground != null) {
0360:                            control.setForeground(foreground);
0361:                        }
0362:
0363:                        if (font != null) {
0364:                            control.setFont(font);
0365:                        }
0366:                    }
0367:                    clear();
0368:                }
0369:
0370:                /**
0371:                 * Apply the fonts and colors to the control if
0372:                 * required.
0373:                 * @param control
0374:                 */
0375:                public void applyFontsAndColors(TreeItem control) {
0376:                    if (usedDecorators) {
0377:                        //If there is no provider only apply set values
0378:                        if (background != null) {
0379:                            control.setBackground(background);
0380:                        }
0381:
0382:                        if (foreground != null) {
0383:                            control.setForeground(foreground);
0384:                        }
0385:
0386:                        if (font != null) {
0387:                            control.setFont(font);
0388:                        }
0389:                    }
0390:                    clear();
0391:                }
0392:
0393:                /**
0394:                 * Apply the fonts and colors to the control if
0395:                 * required.
0396:                 * @param control
0397:                 */
0398:                public void applyFontsAndColors(TableTreeItem control) {
0399:                    if (usedDecorators) {
0400:                        //If there is no provider only apply set values
0401:                        if (background != null) {
0402:                            control.setBackground(background);
0403:                        }
0404:
0405:                        if (foreground != null) {
0406:                            control.setForeground(foreground);
0407:                        }
0408:
0409:                        if (font != null) {
0410:                            control.setFont(font);
0411:                        }
0412:                    }
0413:                    clear();
0414:                }
0415:
0416:                /**
0417:                 * Set the background color.
0418:                 * @param background 
0419:                 */
0420:                public void setBackground(Color background) {
0421:                    this .background = background;
0422:                }
0423:
0424:                /**
0425:                 * Set the font.
0426:                 * @param font 
0427:                 */
0428:                public void setFont(Font font) {
0429:                    this .font = font;
0430:                }
0431:
0432:                /**
0433:                 * Set the foreground color.
0434:                 * @param foreground
0435:                 */
0436:                public void setForeground(Color foreground) {
0437:                    this .foreground = foreground;
0438:                }
0439:
0440:            }
0441:
0442:            /**
0443:             * The safe runnable used to update an item.
0444:             */
0445:            class UpdateItemSafeRunnable extends SafeRunnable {
0446:                private Widget widget;
0447:
0448:                private Object element;
0449:
0450:                private boolean fullMap;
0451:
0452:                UpdateItemSafeRunnable(Widget widget, Object element,
0453:                        boolean fullMap) {
0454:                    this .widget = widget;
0455:                    this .element = element;
0456:                    this .fullMap = fullMap;
0457:                }
0458:
0459:                public void run() {
0460:                    doUpdateItem(widget, element, fullMap);
0461:                }
0462:            }
0463:
0464:            /**
0465:             * Creates a structured element viewer. The viewer has no input, no content
0466:             * provider, a default label provider, no sorter, and no filters.
0467:             */
0468:            protected StructuredViewer() {
0469:                // do nothing
0470:            }
0471:
0472:            /**
0473:             * Adds a listener for double-clicks in this viewer. Has no effect if an
0474:             * identical listener is already registered.
0475:             * 
0476:             * @param listener
0477:             *            a double-click listener
0478:             */
0479:            public void addDoubleClickListener(IDoubleClickListener listener) {
0480:                doubleClickListeners.add(listener);
0481:            }
0482:
0483:            /**
0484:             * Adds a listener for selection-open in this viewer. Has no effect if an
0485:             * identical listener is already registered.
0486:             * 
0487:             * @param listener
0488:             *            a double-click listener
0489:             */
0490:            public void addOpenListener(IOpenListener listener) {
0491:                openListeners.add(listener);
0492:            }
0493:
0494:            /*
0495:             * (non-Javadoc) Method declared on IPostSelectionProvider.
0496:             */
0497:            public void addPostSelectionChangedListener(
0498:                    ISelectionChangedListener listener) {
0499:                postSelectionChangedListeners.add(listener);
0500:            }
0501:
0502:            /**
0503:             * Adds support for dragging items out of this viewer via a user
0504:             * drag-and-drop operation.
0505:             * 
0506:             * @param operations
0507:             *            a bitwise OR of the supported drag and drop operation types (
0508:             *            <code>DROP_COPY</code>,<code>DROP_LINK</code>, and
0509:             *            <code>DROP_MOVE</code>)
0510:             * @param transferTypes
0511:             *            the transfer types that are supported by the drag operation
0512:             * @param listener
0513:             *            the callback that will be invoked to set the drag data and to
0514:             *            cleanup after the drag and drop operation finishes
0515:             * @see org.eclipse.swt.dnd.DND
0516:             */
0517:            public void addDragSupport(int operations,
0518:                    Transfer[] transferTypes, DragSourceListener listener) {
0519:
0520:                Control myControl = getControl();
0521:                final DragSource dragSource = new DragSource(myControl,
0522:                        operations);
0523:                dragSource.setTransfer(transferTypes);
0524:                dragSource.addDragListener(listener);
0525:            }
0526:
0527:            /**
0528:             * Adds support for dropping items into this viewer via a user drag-and-drop
0529:             * operation.
0530:             * 
0531:             * @param operations
0532:             *            a bitwise OR of the supported drag and drop operation types (
0533:             *            <code>DROP_COPY</code>,<code>DROP_LINK</code>, and
0534:             *            <code>DROP_MOVE</code>)
0535:             * @param transferTypes
0536:             *            the transfer types that are supported by the drop operation
0537:             * @param listener
0538:             *            the callback that will be invoked after the drag and drop
0539:             *            operation finishes
0540:             * @see org.eclipse.swt.dnd.DND
0541:             */
0542:            public void addDropSupport(int operations,
0543:                    Transfer[] transferTypes, final DropTargetListener listener) {
0544:                Control control = getControl();
0545:                DropTarget dropTarget = new DropTarget(control, operations);
0546:                dropTarget.setTransfer(transferTypes);
0547:                dropTarget.addDropListener(listener);
0548:            }
0549:
0550:            /**
0551:             * Adds the given filter to this viewer, and triggers refiltering and
0552:             * resorting of the elements. If you want to add more than one filter
0553:             * consider using {@link StructuredViewer#setFilters(ViewerFilter[])}.
0554:             * 
0555:             * @param filter
0556:             *            a viewer filter
0557:             * @see StructuredViewer#setFilters(ViewerFilter[])
0558:             */
0559:            public void addFilter(ViewerFilter filter) {
0560:                if (filters == null) {
0561:                    filters = new ArrayList();
0562:                }
0563:                filters.add(filter);
0564:                refresh();
0565:            }
0566:
0567:            /**
0568:             * Asserts that the given array of elements is itself non- <code>null</code>
0569:             * and contains no <code>null</code> elements.
0570:             * 
0571:             * @param elements
0572:             *            the array to check
0573:             */
0574:            protected void assertElementsNotNull(Object[] elements) {
0575:                Assert.isNotNull(elements);
0576:                for (int i = 0, n = elements.length; i < n; ++i) {
0577:                    Assert.isNotNull(elements[i]);
0578:                }
0579:            }
0580:
0581:            /**
0582:             * Associates the given element with the given widget. Sets the given item's
0583:             * data to be the element, and maps the element to the item in the element
0584:             * map (if enabled).
0585:             * 
0586:             * @param element
0587:             *            the element
0588:             * @param item
0589:             *            the widget
0590:             */
0591:            protected void associate(Object element, Item item) {
0592:                Object data = item.getData();
0593:                if (data != element) {
0594:                    if (data != null) {
0595:                        disassociate(item);
0596:                    }
0597:                    item.setData(element);
0598:                }
0599:                // Always map the element, even if data == element,
0600:                // since unmapAllElements() can leave the map inconsistent
0601:                // See bug 2741 for details.
0602:                mapElement(element, item);
0603:            }
0604:
0605:            /**
0606:             * Disassociates the given SWT item from its corresponding element. Sets the
0607:             * item's data to <code>null</code> and removes the element from the
0608:             * element map (if enabled).
0609:             * 
0610:             * @param item
0611:             *            the widget
0612:             */
0613:            protected void disassociate(Item item) {
0614:                Object element = item.getData();
0615:                Assert.isNotNull(element);
0616:                //Clear the map before we clear the data
0617:                unmapElement(element, item);
0618:                item.setData(null);
0619:            }
0620:
0621:            /**
0622:             * Returns the widget in this viewer's control which represents the given
0623:             * element if it is the viewer's input.
0624:             * <p>
0625:             * This method is internal to the framework; subclassers should not call
0626:             * this method.
0627:             * </p>
0628:             * 
0629:             * @param element
0630:             * @return the corresponding widget, or <code>null</code> if none
0631:             */
0632:            protected abstract Widget doFindInputItem(Object element);
0633:
0634:            /**
0635:             * Returns the widget in this viewer's control which represent the given
0636:             * element. This method searches all the children of the input element.
0637:             * <p>
0638:             * This method is internal to the framework; subclassers should not call
0639:             * this method.
0640:             * </p>
0641:             * 
0642:             * @param element
0643:             * @return the corresponding widget, or <code>null</code> if none
0644:             */
0645:            protected abstract Widget doFindItem(Object element);
0646:
0647:            /**
0648:             * Copies the attributes of the given element into the given SWT item. The
0649:             * element map is updated according to the value of <code>fullMap</code>.
0650:             * If <code>fullMap</code> is <code>true</code> then the current mapping
0651:             * from element to widgets is removed and the new mapping is added. If
0652:             * full map is <code>false</code> then only the new map gets installed.
0653:             * Installing only the new map is necessary in cases where only the order of
0654:             * elements changes but not the set of elements.
0655:             * <p>
0656:             * This method is internal to the framework; subclassers should not call
0657:             * this method.
0658:             * </p>
0659:             * 
0660:             * @param item
0661:             * @param element element
0662:             * @param fullMap
0663:             *            <code>true</code> if mappings are added and removed, and
0664:             *            <code>false</code> if only the new map gets installed
0665:             */
0666:            protected abstract void doUpdateItem(Widget item, Object element,
0667:                    boolean fullMap);
0668:
0669:            /**
0670:             * Compares two elements for equality. Uses the element comparer if one has
0671:             * been set, otherwise uses the default <code>equals</code> method on the
0672:             * elements themselves.
0673:             * 
0674:             * @param elementA
0675:             *            the first element
0676:             * @param elementB
0677:             *            the second element
0678:             * @return whether elementA is equal to elementB
0679:             */
0680:            protected boolean equals(Object elementA, Object elementB) {
0681:                if (comparer == null) {
0682:                    return elementA == null ? elementB == null : elementA
0683:                            .equals(elementB);
0684:                } else {
0685:                    return elementA == null ? elementB == null : comparer
0686:                            .equals(elementA, elementB);
0687:                }
0688:            }
0689:
0690:            /**
0691:             * Returns the result of running the given elements through the filters.
0692:             * 
0693:             * @param elements
0694:             *            the elements to filter
0695:             * @return only the elements which all filters accept
0696:             */
0697:            protected Object[] filter(Object[] elements) {
0698:                if (filters != null) {
0699:                    ArrayList filtered = new ArrayList(elements.length);
0700:                    Object root = getRoot();
0701:                    for (int i = 0; i < elements.length; i++) {
0702:                        boolean add = true;
0703:                        for (int j = 0; j < filters.size(); j++) {
0704:                            add = ((ViewerFilter) filters.get(j)).select(this ,
0705:                                    root, elements[i]);
0706:                            if (!add) {
0707:                                break;
0708:                            }
0709:                        }
0710:                        if (add) {
0711:                            filtered.add(elements[i]);
0712:                        }
0713:                    }
0714:                    return filtered.toArray();
0715:                }
0716:                return elements;
0717:            }
0718:
0719:            /**
0720:             * Finds the widget which represents the given element.
0721:             * <p>
0722:             * The default implementation of this method tries first to find the widget
0723:             * for the given element assuming that it is the viewer's input; this is
0724:             * done by calling <code>doFindInputItem</code>. If it is not found
0725:             * there, it is looked up in the internal element map provided that this
0726:             * feature has been enabled. If the element map is disabled, the widget is
0727:             * found via <code>doFindInputItem</code>.
0728:             * </p>
0729:             * 
0730:             * @param element
0731:             *            the element
0732:             * @return the corresponding widget, or <code>null</code> if none
0733:             */
0734:            protected final Widget findItem(Object element) {
0735:                Widget[] result = findItems(element);
0736:                return result.length == 0 ? null : result[0];
0737:            }
0738:
0739:            /**
0740:             * Finds the widgets which represent the given element. The returned array
0741:             * must not be changed by clients; it might change upon calling other
0742:             * methods on this viewer.
0743:             * <p>
0744:             * This method was introduced to support multiple equal elements in a viewer
0745:             * (@see {@link AbstractTreeViewer}). Multiple equal elements are only
0746:             * supported if the element map is enabled by calling
0747:             * {@link #setUseHashlookup(boolean)} and passing <code>true</code>.
0748:             * </p>
0749:             * <p>
0750:             * The default implementation of this method tries first to find the widget
0751:             * for the given element assuming that it is the viewer's input; this is
0752:             * done by calling <code>doFindInputItem</code>. If it is not found
0753:             * there, the widgets are looked up in the internal element map provided
0754:             * that this feature has been enabled. If the element map is disabled, the
0755:             * widget is found via <code>doFindInputItem</code>.
0756:             * </p>
0757:             * 
0758:             * @param element
0759:             *            the element
0760:             * @return the corresponding widgets
0761:             * 
0762:             * @since 3.2
0763:             */
0764:            protected final Widget[] findItems(Object element) {
0765:                Widget result = doFindInputItem(element);
0766:                if (result != null) {
0767:                    return new Widget[] { result };
0768:                }
0769:                // if we have an element map use it, otherwise search for the item.
0770:                if (usingElementMap()) {
0771:                    Object widgetOrWidgets = elementMap.get(element);
0772:                    if (widgetOrWidgets == null) {
0773:                        return NO_WIDGETS;
0774:                    } else if (widgetOrWidgets instanceof  Widget) {
0775:                        return new Widget[] { (Widget) widgetOrWidgets };
0776:                    } else {
0777:                        return (Widget[]) widgetOrWidgets;
0778:                    }
0779:                }
0780:                result = doFindItem(element);
0781:                return result == null ? NO_WIDGETS : new Widget[] { result };
0782:            }
0783:
0784:            /**
0785:             * Notifies any double-click listeners that a double-click has been
0786:             * received. Only listeners registered at the time this method is called are
0787:             * notified.
0788:             * 
0789:             * @param event
0790:             *            a double-click event
0791:             * 
0792:             * @see IDoubleClickListener#doubleClick
0793:             */
0794:            protected void fireDoubleClick(final DoubleClickEvent event) {
0795:                Object[] listeners = doubleClickListeners.getListeners();
0796:                for (int i = 0; i < listeners.length; ++i) {
0797:                    final IDoubleClickListener l = (IDoubleClickListener) listeners[i];
0798:                    SafeRunnable.run(new SafeRunnable() {
0799:                        public void run() {
0800:                            l.doubleClick(event);
0801:                        }
0802:                    });
0803:                }
0804:            }
0805:
0806:            /**
0807:             * Notifies any open event listeners that a open event has been received.
0808:             * Only listeners registered at the time this method is called are notified.
0809:             * 
0810:             * @param event
0811:             *            a double-click event
0812:             * 
0813:             * @see IOpenListener#open(OpenEvent)
0814:             */
0815:            protected void fireOpen(final OpenEvent event) {
0816:                Object[] listeners = openListeners.getListeners();
0817:                for (int i = 0; i < listeners.length; ++i) {
0818:                    final IOpenListener l = (IOpenListener) listeners[i];
0819:                    SafeRunnable.run(new SafeRunnable() {
0820:                        public void run() {
0821:                            l.open(event);
0822:                        }
0823:                    });
0824:                }
0825:            }
0826:
0827:            /**
0828:             * Notifies any post selection listeners that a post selection event has
0829:             * been received. Only listeners registered at the time this method is
0830:             * called are notified.
0831:             * 
0832:             * @param event
0833:             *            a selection changed event
0834:             * 
0835:             * @see #addPostSelectionChangedListener(ISelectionChangedListener)
0836:             */
0837:            protected void firePostSelectionChanged(
0838:                    final SelectionChangedEvent event) {
0839:                Object[] listeners = postSelectionChangedListeners
0840:                        .getListeners();
0841:                for (int i = 0; i < listeners.length; ++i) {
0842:                    final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i];
0843:                    SafeRunnable.run(new SafeRunnable() {
0844:                        public void run() {
0845:                            l.selectionChanged(event);
0846:                        }
0847:                    });
0848:                }
0849:            }
0850:
0851:            /**
0852:             * Returns the comparer to use for comparing elements, or
0853:             * <code>null</code> if none has been set.  If specified,
0854:             * the viewer uses this to compare and hash elements rather
0855:             * than the elements' own equals and hashCode methods.
0856:             *           
0857:             * @return the comparer to use for comparing elements or
0858:             *            <code>null</code>
0859:             */
0860:            public IElementComparer getComparer() {
0861:                return comparer;
0862:            }
0863:
0864:            /**
0865:             * Returns the filtered array of children of the given element. The
0866:             * resulting array must not be modified, as it may come directly from the
0867:             * model's internal state.
0868:             * 
0869:             * @param parent
0870:             *            the parent element
0871:             * @return a filtered array of child elements
0872:             */
0873:            protected Object[] getFilteredChildren(Object parent) {
0874:                Object[] result = getRawChildren(parent);
0875:                if (filters != null) {
0876:                    for (Iterator iter = filters.iterator(); iter.hasNext();) {
0877:                        ViewerFilter f = (ViewerFilter) iter.next();
0878:                        result = f.filter(this , parent, result);
0879:                    }
0880:                }
0881:                return result;
0882:            }
0883:
0884:            /**
0885:             * Returns this viewer's filters.
0886:             * 
0887:             * @return an array of viewer filters
0888:             * @see StructuredViewer#setFilters(ViewerFilter[])
0889:             */
0890:            public ViewerFilter[] getFilters() {
0891:                if (filters == null) {
0892:                    return new ViewerFilter[0];
0893:                }
0894:                ViewerFilter[] result = new ViewerFilter[filters.size()];
0895:                filters.toArray(result);
0896:                return result;
0897:            }
0898:
0899:            /**
0900:             * Returns the item at the given display-relative coordinates, or
0901:             * <code>null</code> if there is no item at that location or 
0902:             * the underlying SWT-Control is not made up of {@link Item} 
0903:             * (e.g {@link ListViewer}) 
0904:             * <p>
0905:             * The default implementation of this method returns <code>null</code>.
0906:             * </p>
0907:             * 
0908:             * @param x
0909:             *            horizontal coordinate
0910:             * @param y
0911:             *            vertical coordinate
0912:             * @return the item, or <code>null</code> if there is no item at the given
0913:             *         coordinates
0914:             * @deprecated This method is deprecated in 3.3 in favor of {@link ColumnViewer#getItemAt(org.eclipse.swt.graphics.Point)}. 
0915:             * Viewers who are not subclasses of {@link ColumnViewer} should consider using a
0916:             * widget relative implementation like {@link ColumnViewer#getItemAt(org.eclipse.swt.graphics.Point)}.
0917:             *  
0918:             */
0919:            protected Item getItem(int x, int y) {
0920:                return null;
0921:            }
0922:
0923:            /**
0924:             * Returns the children of the given parent without sorting and filtering
0925:             * them. The resulting array must not be modified, as it may come directly
0926:             * from the model's internal state.
0927:             * <p>
0928:             * Returns an empty array if the given parent is <code>null</code>.
0929:             * </p>
0930:             * 
0931:             * @param parent
0932:             *            the parent element
0933:             * @return the child elements
0934:             */
0935:            protected Object[] getRawChildren(Object parent) {
0936:                Object[] result = null;
0937:                if (parent != null) {
0938:                    IStructuredContentProvider cp = (IStructuredContentProvider) getContentProvider();
0939:                    if (cp != null) {
0940:                        result = cp.getElements(parent);
0941:                        assertElementsNotNull(result);
0942:                    }
0943:                }
0944:                return (result != null) ? result : new Object[0];
0945:            }
0946:
0947:            /**
0948:             * Returns the root element.
0949:             * <p>
0950:             * The default implementation of this framework method forwards to
0951:             * <code>getInput</code>. Override if the root element is different from
0952:             * the viewer's input element.
0953:             * </p>
0954:             * 
0955:             * @return the root element, or <code>null</code> if none
0956:             */
0957:            protected Object getRoot() {
0958:                return getInput();
0959:            }
0960:
0961:            /**
0962:             * The <code>StructuredViewer</code> implementation of this method returns
0963:             * the result as an <code>IStructuredSelection</code>.
0964:             * <p>
0965:             * Subclasses do not typically override this method, but implement
0966:             * <code>getSelectionFromWidget(List)</code> instead.
0967:             * <p>
0968:             * @return ISelection
0969:             */
0970:            public ISelection getSelection() {
0971:                Control control = getControl();
0972:                if (control == null || control.isDisposed()) {
0973:                    return StructuredSelection.EMPTY;
0974:                }
0975:                List list = getSelectionFromWidget();
0976:                return new StructuredSelection(list);
0977:            }
0978:
0979:            /**
0980:             * Retrieves the selection, as a <code>List</code>, from the underlying
0981:             * widget.
0982:             * 
0983:             * @return the list of selected elements
0984:             */
0985:            protected abstract List getSelectionFromWidget();
0986:
0987:            /**
0988:             * Returns the sorted and filtered set of children of the given element. The
0989:             * resulting array must not be modified, as it may come directly from the
0990:             * model's internal state.
0991:             * 
0992:             * @param parent
0993:             *            the parent element
0994:             * @return a sorted and filtered array of child elements
0995:             */
0996:            protected Object[] getSortedChildren(Object parent) {
0997:                Object[] result = getFilteredChildren(parent);
0998:                if (sorter != null) {
0999:                    // be sure we're not modifying the original array from the model
1000:                    result = (Object[]) result.clone();
1001:                    sorter.sort(this , result);
1002:                }
1003:                return result;
1004:            }
1005:
1006:            /**
1007:             * Returns this viewer's sorter, or <code>null</code> if it does not have
1008:             * one.  If this viewer has a comparator that was set via 
1009:             * <code>setComparator(ViewerComparator)</code> then this method will return 
1010:             * <code>null</code> if the comparator is not an instance of ViewerSorter.
1011:             * <p>
1012:             * It is recommended to use <code>getComparator()</code> instead.
1013:             * </p>
1014:             * 
1015:             * @return a viewer sorter, or <code>null</code> if none or if the comparator is 
1016:             * 				not an instance of ViewerSorter
1017:             */
1018:            public ViewerSorter getSorter() {
1019:                if (sorter instanceof  ViewerSorter)
1020:                    return (ViewerSorter) sorter;
1021:                return null;
1022:            }
1023:
1024:            /**
1025:             * Return this viewer's comparator used to sort elements.
1026:             * This method should be used instead of <code>getSorter()</code>.
1027:             * 
1028:             * @return a viewer comparator, or <code>null</code> if none
1029:             *
1030:             * @since 3.2
1031:             */
1032:            public ViewerComparator getComparator() {
1033:                return sorter;
1034:            }
1035:
1036:            /**
1037:             * Handles a double-click select event from the widget.
1038:             * <p>
1039:             * This method is internal to the framework; subclassers should not call
1040:             * this method.
1041:             * </p>
1042:             * 
1043:             * @param event
1044:             *            the SWT selection event
1045:             */
1046:            protected void handleDoubleSelect(SelectionEvent event) {
1047:                // This method is reimplemented in AbstractTreeViewer to fix bug 108102.
1048:
1049:                // handle case where an earlier selection listener disposed the control.
1050:                Control control = getControl();
1051:                if (control != null && !control.isDisposed()) {
1052:                    // If the double-clicked element can be obtained from the event, use it
1053:                    // otherwise get it from the control.  Some controls like List do
1054:                    // not have the notion of item.
1055:                    // For details, see bug 90161 [Navigator] DefaultSelecting folders shouldn't always expand first one
1056:                    ISelection selection;
1057:                    if (event.item != null && event.item.getData() != null) {
1058:                        selection = new StructuredSelection(event.item
1059:                                .getData());
1060:                    } else {
1061:                        selection = getSelection();
1062:                        updateSelection(selection);
1063:                    }
1064:                    fireDoubleClick(new DoubleClickEvent(this , selection));
1065:                }
1066:            }
1067:
1068:            /**
1069:             * Handles an open event from the OpenStrategy.
1070:             * <p>
1071:             * This method is internal to the framework; subclassers should not call
1072:             * this method.
1073:             * </p>
1074:             * 
1075:             * @param event
1076:             *            the SWT selection event
1077:             */
1078:            protected void handleOpen(SelectionEvent event) {
1079:                Control control = getControl();
1080:                if (control != null && !control.isDisposed()) {
1081:                    ISelection selection = getSelection();
1082:                    fireOpen(new OpenEvent(this , selection));
1083:                }
1084:            }
1085:
1086:            /**
1087:             * Handles an invalid selection.
1088:             * <p>
1089:             * This framework method is called if a model change picked up by a viewer
1090:             * results in an invalid selection. For instance if an element contained in
1091:             * the selection has been removed from the viewer, the viewer is free to
1092:             * either remove the element from the selection or to pick another element
1093:             * as its new selection. The default implementation of this method calls
1094:             * <code>updateSelection</code>. Subclasses may override it to implement
1095:             * a different strategy for picking a new selection when the old selection
1096:             * becomes invalid.
1097:             * </p>
1098:             * 
1099:             * @param invalidSelection
1100:             *            the selection before the viewer was updated
1101:             * @param newSelection
1102:             *            the selection after the update, or <code>null</code> if none
1103:             */
1104:            protected void handleInvalidSelection(ISelection invalidSelection,
1105:                    ISelection newSelection) {
1106:                updateSelection(newSelection);
1107:                SelectionChangedEvent event = new SelectionChangedEvent(this ,
1108:                        newSelection);
1109:                firePostSelectionChanged(event);
1110:            }
1111:
1112:            /**
1113:             * The <code>StructuredViewer</code> implementation of this
1114:             * <code>ContentViewer</code> method calls <code>update</code> if the
1115:             * event specifies that the label of a given element has changed, otherwise
1116:             * it calls super. Subclasses may reimplement or extend.
1117:             * </p>
1118:             * @param event the event that generated this update
1119:             */
1120:            protected void handleLabelProviderChanged(
1121:                    LabelProviderChangedEvent event) {
1122:                Object[] elements = event.getElements();
1123:                if (elements != null) {
1124:                    update(elements, null);
1125:                } else {
1126:                    super .handleLabelProviderChanged(event);
1127:                }
1128:            }
1129:
1130:            /**
1131:             * Handles a select event from the widget.
1132:             * <p>
1133:             * This method is internal to the framework; subclassers should not call
1134:             * this method.
1135:             * </p>
1136:             * 
1137:             * @param event
1138:             *            the SWT selection event
1139:             */
1140:            protected void handleSelect(SelectionEvent event) {
1141:                // handle case where an earlier selection listener disposed the control.
1142:                Control control = getControl();
1143:                if (control != null && !control.isDisposed()) {
1144:                    updateSelection(getSelection());
1145:                }
1146:            }
1147:
1148:            /**
1149:             * Handles a post select event from the widget.
1150:             * <p>
1151:             * This method is internal to the framework; subclassers should not call
1152:             * this method.
1153:             * </p>
1154:             * 
1155:             * @param e the SWT selection event
1156:             */
1157:            protected void handlePostSelect(SelectionEvent e) {
1158:                SelectionChangedEvent event = new SelectionChangedEvent(this ,
1159:                        getSelection());
1160:                firePostSelectionChanged(event);
1161:            }
1162:
1163:            /*
1164:             * (non-Javadoc) Method declared on Viewer.
1165:             */
1166:            protected void hookControl(Control control) {
1167:                super .hookControl(control);
1168:                OpenStrategy handler = new OpenStrategy(control);
1169:                handler.addSelectionListener(new SelectionListener() {
1170:                    public void widgetSelected(SelectionEvent e) {
1171:                        // On Windows, selection events may happen during a refresh.
1172:                        // Ignore these events if we are currently in preservingSelection().
1173:                        // See bug 184441.
1174:                        if (!inChange) {
1175:                            handleSelect(e);
1176:                        }
1177:                    }
1178:
1179:                    public void widgetDefaultSelected(SelectionEvent e) {
1180:                        handleDoubleSelect(e);
1181:                    }
1182:                });
1183:                handler.addPostSelectionListener(new SelectionAdapter() {
1184:                    public void widgetSelected(SelectionEvent e) {
1185:                        handlePostSelect(e);
1186:                    }
1187:                });
1188:                handler.addOpenListener(new IOpenEventListener() {
1189:                    public void handleOpen(SelectionEvent e) {
1190:                        StructuredViewer.this .handleOpen(e);
1191:                    }
1192:                });
1193:            }
1194:
1195:            /**
1196:             * Returns whether this viewer has any filters.
1197:             * @return boolean
1198:             */
1199:            protected boolean hasFilters() {
1200:                return filters != null && filters.size() > 0;
1201:            }
1202:
1203:            /**
1204:             * Refreshes this viewer starting at the given element.
1205:             * 
1206:             * @param element
1207:             *            the element
1208:             */
1209:            protected abstract void internalRefresh(Object element);
1210:
1211:            /**
1212:             * Refreshes this viewer starting at the given element. Labels are updated
1213:             * as described in <code>refresh(boolean updateLabels)</code>.
1214:             * <p>
1215:             * The default implementation simply calls
1216:             * <code>internalRefresh(element)</code>, ignoring
1217:             * <code>updateLabels</code>.
1218:             * <p>
1219:             * If this method is overridden to do the actual refresh, then
1220:             * <code>internalRefresh(Object element)</code> should simply call
1221:             * <code>internalRefresh(element, true)</code>.
1222:             * 
1223:             * @param element
1224:             *            the element
1225:             * @param updateLabels
1226:             *            <code>true</code> to update labels for existing elements,
1227:             *            <code>false</code> to only update labels as needed, assuming
1228:             *            that labels for existing elements are unchanged.
1229:             * 
1230:             * @since 2.0
1231:             */
1232:            protected void internalRefresh(Object element, boolean updateLabels) {
1233:                internalRefresh(element);
1234:            }
1235:
1236:            /**
1237:             * Adds the element item pair to the element map.
1238:             * <p>
1239:             * This method is internal to the framework; subclassers should not call
1240:             * this method.
1241:             * </p>
1242:             * 
1243:             * @param element
1244:             *            the element
1245:             * @param item
1246:             *            the corresponding widget
1247:             */
1248:            protected void mapElement(Object element, Widget item) {
1249:                if (elementMap != null) {
1250:                    Object widgetOrWidgets = elementMap.get(element);
1251:                    if (widgetOrWidgets == null) {
1252:                        elementMap.put(element, item);
1253:                    } else if (widgetOrWidgets instanceof  Widget) {
1254:                        if (widgetOrWidgets != item) {
1255:                            elementMap.put(element, new Widget[] {
1256:                                    (Widget) widgetOrWidgets, item });
1257:                        }
1258:                    } else {
1259:                        Widget[] widgets = (Widget[]) widgetOrWidgets;
1260:                        int indexOfItem = Arrays.asList(widgets).indexOf(item);
1261:                        if (indexOfItem == -1) {
1262:                            int length = widgets.length;
1263:                            System
1264:                                    .arraycopy(widgets, 0,
1265:                                            widgets = new Widget[length + 1],
1266:                                            0, length);
1267:                            widgets[length] = item;
1268:                            elementMap.put(element, widgets);
1269:                        }
1270:                    }
1271:                }
1272:            }
1273:
1274:            /**
1275:             * Determines whether a change to the given property of the given element
1276:             * would require refiltering and/or resorting.
1277:             * <p>
1278:             * This method is internal to the framework; subclassers should not call
1279:             * this method.
1280:             * </p>
1281:             * 
1282:             * @param element
1283:             *            the element
1284:             * @param property
1285:             *            the property
1286:             * @return <code>true</code> if refiltering is required, and
1287:             *         <code>false</code> otherwise
1288:             */
1289:            protected boolean needsRefilter(Object element, String property) {
1290:                if (sorter != null
1291:                        && sorter.isSorterProperty(element, property)) {
1292:                    return true;
1293:                }
1294:
1295:                if (filters != null) {
1296:                    for (int i = 0, n = filters.size(); i < n; ++i) {
1297:                        ViewerFilter filter = (ViewerFilter) filters.get(i);
1298:                        if (filter.isFilterProperty(element, property)) {
1299:                            return true;
1300:                        }
1301:                    }
1302:                }
1303:                return false;
1304:            }
1305:
1306:            /**
1307:             * Returns a new hashtable using the given capacity and this viewer's element comparer.
1308:             * 
1309:             * @param capacity the initial capacity of the hashtable
1310:             * @return a new hashtable
1311:             * 
1312:             * @since 3.0
1313:             */
1314:            CustomHashtable newHashtable(int capacity) {
1315:                return new CustomHashtable(capacity, getComparer());
1316:            }
1317:
1318:            /**
1319:             * Attempts to preserves the current selection across a run of the given
1320:             * code.
1321:             * <p>
1322:             * The default implementation of this method:
1323:             * <ul>
1324:             * <li>discovers the old selection (via <code>getSelection</code>)</li>
1325:             * <li>runs the given runnable</li>
1326:             * <li>attempts to restore the old selection (using
1327:             * <code>setSelectionToWidget</code></li>
1328:             * <li>rediscovers the resulting selection (via <code>getSelection</code>)
1329:             * </li>
1330:             * <li>calls <code>handleInvalidSelection</code> if the resulting selection is different from the old selection</li>
1331:             * </ul>
1332:             * </p>
1333:             * 
1334:             * @param updateCode
1335:             *            the code to run
1336:             */
1337:            protected void preservingSelection(Runnable updateCode) {
1338:                preservingSelection(updateCode, false);
1339:            }
1340:
1341:            /**
1342:             * Attempts to preserves the current selection across a run of the given
1343:             * code, with a best effort to avoid scrolling if <code>reveal</code> is false,
1344:             * or to reveal the selection if <code>reveal</code> is true.
1345:             * <p>
1346:             * The default implementation of this method:
1347:             * <ul>
1348:             * <li>discovers the old selection (via <code>getSelection</code>)</li>
1349:             * <li>runs the given runnable</li>
1350:             * <li>attempts to restore the old selection (using
1351:             * <code>setSelectionToWidget</code></li>
1352:             * <li>rediscovers the resulting selection (via <code>getSelection</code>)
1353:             * </li>
1354:             * <li>calls <code>handleInvalidSelection</code> if the selection did not
1355:             * take</li>
1356:             * <li>calls <code>postUpdateHook</code></li>
1357:             * </ul>
1358:             * </p>
1359:             * 
1360:             * @param updateCode
1361:             *            the code to run
1362:             * @param reveal
1363:             *            <code>true</code> if the selection should be made visible,
1364:             *            <code>false</code> if scrolling should be avoided
1365:             * @since 3.3
1366:             */
1367:            void preservingSelection(Runnable updateCode, boolean reveal) {
1368:
1369:                ISelection oldSelection = null;
1370:                try {
1371:                    // preserve selection
1372:                    oldSelection = getSelection();
1373:                    inChange = restoreSelection = true;
1374:
1375:                    // perform the update
1376:                    updateCode.run();
1377:
1378:                } finally {
1379:                    inChange = false;
1380:
1381:                    // restore selection
1382:                    if (restoreSelection) {
1383:                        setSelectionToWidget(oldSelection, reveal);
1384:                    }
1385:
1386:                    // send out notification if old and new differ
1387:                    ISelection newSelection = getSelection();
1388:                    if (!newSelection.equals(oldSelection)) {
1389:                        handleInvalidSelection(oldSelection, newSelection);
1390:                    }
1391:                }
1392:            }
1393:
1394:            /*
1395:             * Non-Javadoc. Method declared on Viewer.
1396:             */
1397:            public void refresh() {
1398:                refresh(getRoot());
1399:            }
1400:
1401:            /**
1402:             * Refreshes this viewer with information freshly obtained from this
1403:             * viewer's model. If <code>updateLabels</code> is <code>true</code>
1404:             * then labels for otherwise unaffected elements are updated as well.
1405:             * Otherwise, it assumes labels for existing elements are unchanged, and
1406:             * labels are only obtained as needed (for example, for new elements).
1407:             * <p>
1408:             * Calling <code>refresh(true)</code> has the same effect as
1409:             * <code>refresh()</code>.
1410:             * <p>
1411:             * Note that the implementation may still obtain labels for existing
1412:             * elements even if <code>updateLabels</code> is false. The intent is
1413:             * simply to allow optimization where possible.
1414:             * 
1415:             * @param updateLabels
1416:             *            <code>true</code> to update labels for existing elements,
1417:             *            <code>false</code> to only update labels as needed, assuming
1418:             *            that labels for existing elements are unchanged.
1419:             * 
1420:             * @since 2.0
1421:             */
1422:            public void refresh(boolean updateLabels) {
1423:                refresh(getRoot(), updateLabels);
1424:            }
1425:
1426:            /**
1427:             * Refreshes this viewer starting with the given element.
1428:             * <p>
1429:             * Unlike the <code>update</code> methods, this handles structural changes
1430:             * to the given element (e.g. addition or removal of children). If only the
1431:             * given element needs updating, it is more efficient to use the
1432:             * <code>update</code> methods.
1433:             * </p>
1434:             * 
1435:             * @param element
1436:             *            the element
1437:             */
1438:            public void refresh(final Object element) {
1439:                preservingSelection(new Runnable() {
1440:                    public void run() {
1441:                        internalRefresh(element);
1442:                    }
1443:                });
1444:            }
1445:
1446:            /**
1447:             * Refreshes this viewer starting with the given element. Labels are updated
1448:             * as described in <code>refresh(boolean updateLabels)</code>.
1449:             * <p>
1450:             * Unlike the <code>update</code> methods, this handles structural changes
1451:             * to the given element (e.g. addition or removal of children). If only the
1452:             * given element needs updating, it is more efficient to use the
1453:             * <code>update</code> methods.
1454:             * </p>
1455:             * 
1456:             * @param element
1457:             *            the element
1458:             * @param updateLabels
1459:             *            <code>true</code> to update labels for existing elements,
1460:             *            <code>false</code> to only update labels as needed, assuming
1461:             *            that labels for existing elements are unchanged.
1462:             * 
1463:             * @since 2.0
1464:             */
1465:            public void refresh(final Object element, final boolean updateLabels) {
1466:                preservingSelection(new Runnable() {
1467:                    public void run() {
1468:                        internalRefresh(element, updateLabels);
1469:                    }
1470:                });
1471:            }
1472:
1473:            /**
1474:             * 
1475:             * Refreshes the given item with the given element. Calls
1476:             * <code>doUpdateItem(..., false)</code>.
1477:             * <p>
1478:             * This method is internal to the framework; subclassers should not call
1479:             * this method.
1480:             * </p>
1481:             * @param widget
1482:             *            the widget
1483:             * @param element
1484:             *            the element
1485:             */
1486:            protected final void refreshItem(Widget widget, Object element) {
1487:                SafeRunnable.run(new UpdateItemSafeRunnable(widget, element,
1488:                        true));
1489:            }
1490:
1491:            /**
1492:             * Removes the given open listener from this viewer. Has no affect if an
1493:             * identical listener is not registered.
1494:             * 
1495:             * @param listener
1496:             *            a double-click listener
1497:             */
1498:            public void removeOpenListener(IOpenListener listener) {
1499:                openListeners.remove(listener);
1500:            }
1501:
1502:            /*
1503:             * (non-Javadoc) Method declared on IPostSelectionProvider.
1504:             */
1505:            public void removePostSelectionChangedListener(
1506:                    ISelectionChangedListener listener) {
1507:                postSelectionChangedListeners.remove(listener);
1508:            }
1509:
1510:            /**
1511:             * Removes the given double-click listener from this viewer. Has no affect
1512:             * if an identical listener is not registered.
1513:             * 
1514:             * @param listener
1515:             *            a double-click listener
1516:             */
1517:            public void removeDoubleClickListener(IDoubleClickListener listener) {
1518:                doubleClickListeners.remove(listener);
1519:            }
1520:
1521:            /**
1522:             * Removes the given filter from this viewer, and triggers refiltering and
1523:             * resorting of the elements if required. Has no effect if the identical
1524:             * filter is not registered. If you want to remove more than one filter
1525:             * consider using {@link StructuredViewer#setFilters(ViewerFilter[])}.
1526:             * 
1527:             * @param filter
1528:             *            a viewer filter
1529:             * @see StructuredViewer#setFilters(ViewerFilter[])
1530:             */
1531:            public void removeFilter(ViewerFilter filter) {
1532:                Assert.isNotNull(filter);
1533:                if (filters != null) {
1534:                    // Note: can't use List.remove(Object). Use identity comparison
1535:                    // instead.
1536:                    for (Iterator i = filters.iterator(); i.hasNext();) {
1537:                        Object o = i.next();
1538:                        if (o == filter) {
1539:                            i.remove();
1540:                            refresh();
1541:                            if (filters.size() == 0) {
1542:                                filters = null;
1543:                            }
1544:                            return;
1545:                        }
1546:                    }
1547:                }
1548:            }
1549:
1550:            /**
1551:             * Sets the filters, replacing any previous filters, and triggers
1552:             * refiltering and resorting of the elements.
1553:             * 
1554:             * @param filters
1555:             *            an array of viewer filters
1556:             * @since 3.3
1557:             */
1558:            public void setFilters(ViewerFilter[] filters) {
1559:                if (filters.length == 0) {
1560:                    resetFilters();
1561:                } else {
1562:                    this .filters = new ArrayList(Arrays.asList(filters));
1563:                    refresh();
1564:                }
1565:            }
1566:
1567:            /**
1568:             * Discards this viewer's filters and triggers refiltering and resorting of
1569:             * the elements.
1570:             */
1571:            public void resetFilters() {
1572:                if (filters != null) {
1573:                    filters = null;
1574:                    refresh();
1575:                }
1576:            }
1577:
1578:            /**
1579:             * Ensures that the given element is visible, scrolling the viewer if
1580:             * necessary. The selection is unchanged.
1581:             * 
1582:             * @param element
1583:             *            the element to reveal
1584:             */
1585:            public abstract void reveal(Object element);
1586:
1587:            /*
1588:             *  (non-Javadoc)
1589:             * @see org.eclipse.jface.viewers.ContentViewer#setContentProvider(org.eclipse.jface.viewers.IContentProvider)
1590:             */
1591:            public void setContentProvider(IContentProvider provider) {
1592:                assertContentProviderType(provider);
1593:                super .setContentProvider(provider);
1594:            }
1595:
1596:            /**
1597:             * Assert that the content provider is of one of the
1598:             * supported types.
1599:             * @param provider
1600:             */
1601:            protected void assertContentProviderType(IContentProvider provider) {
1602:                Assert.isTrue(provider instanceof  IStructuredContentProvider);
1603:            }
1604:
1605:            /*
1606:             *  (non-Javadoc)
1607:             * @see org.eclipse.jface.viewers.Viewer#setInput(java.lang.Object)
1608:             */
1609:            public final void setInput(Object input) {
1610:
1611:                try {
1612:                    //		fInChange= true;
1613:
1614:                    unmapAllElements();
1615:
1616:                    super .setInput(input);
1617:
1618:                } finally {
1619:                    //		fInChange= false;
1620:                }
1621:            }
1622:
1623:            /*
1624:             *  (non-Javadoc)
1625:             * @see org.eclipse.jface.viewers.Viewer#setSelection(org.eclipse.jface.viewers.ISelection, boolean)
1626:             */
1627:            public void setSelection(ISelection selection, boolean reveal) {
1628:                /**
1629:                 * <p>
1630:                 * If the new selection differs from the current selection the hook
1631:                 * <code>updateSelection</code> is called.
1632:                 * </p>
1633:                 * <p>
1634:                 * If <code>setSelection</code> is called from within
1635:                 * <code>preserveSelection</code>, the call to
1636:                 * <code>updateSelection</code> is delayed until the end of
1637:                 * <code>preserveSelection</code>.
1638:                 * </p>
1639:                 * <p>
1640:                 * Subclasses do not typically override this method, but implement
1641:                 * <code>setSelectionToWidget</code> instead.
1642:                 * </p>
1643:                 */
1644:                Control control = getControl();
1645:                if (control == null || control.isDisposed()) {
1646:                    return;
1647:                }
1648:                if (!inChange) {
1649:                    setSelectionToWidget(selection, reveal);
1650:                    ISelection sel = getSelection();
1651:                    updateSelection(sel);
1652:                    firePostSelectionChanged(new SelectionChangedEvent(this ,
1653:                            sel));
1654:                } else {
1655:                    restoreSelection = false;
1656:                    setSelectionToWidget(selection, reveal);
1657:                }
1658:            }
1659:
1660:            /**
1661:             * Parlays the given list of selected elements into selections on this
1662:             * viewer's control.
1663:             * <p>
1664:             * Subclasses should override to set their selection based on the given list
1665:             * of elements.
1666:             * </p>
1667:             * 
1668:             * @param l
1669:             *            list of selected elements (element type: <code>Object</code>)
1670:             *            or <code>null</code> if the selection is to be cleared
1671:             * @param reveal
1672:             *            <code>true</code> if the selection is to be made visible,
1673:             *            and <code>false</code> otherwise
1674:             */
1675:            protected abstract void setSelectionToWidget(List l, boolean reveal);
1676:
1677:            /**
1678:             * Converts the selection to a <code>List</code> and calls
1679:             * <code>setSelectionToWidget(List, boolean)</code>. The selection is
1680:             * expected to be an <code>IStructuredSelection</code> of elements. If
1681:             * not, the selection is cleared.
1682:             * <p>
1683:             * Subclasses do not typically override this method, but implement
1684:             * <code>setSelectionToWidget(List, boolean)</code> instead.
1685:             * 
1686:             * @param selection
1687:             *            an IStructuredSelection of elements
1688:             * @param reveal
1689:             *            <code>true</code> to reveal the first element in the
1690:             *            selection, or <code>false</code> otherwise
1691:             */
1692:            protected void setSelectionToWidget(ISelection selection,
1693:                    boolean reveal) {
1694:                if (selection instanceof  IStructuredSelection) {
1695:                    setSelectionToWidget(((IStructuredSelection) selection)
1696:                            .toList(), reveal);
1697:                } else {
1698:                    setSelectionToWidget((List) null, reveal);
1699:                }
1700:            }
1701:
1702:            /**
1703:             * Sets this viewer's sorter and triggers refiltering and resorting of this
1704:             * viewer's element. Passing <code>null</code> turns sorting off.  
1705:             * <p>
1706:             * It is recommended to use <code>setComparator()</code> instead.
1707:             * </p>
1708:             * 
1709:             * @param sorter
1710:             *            a viewer sorter, or <code>null</code> if none
1711:             */
1712:            public void setSorter(ViewerSorter sorter) {
1713:                if (this .sorter != sorter) {
1714:                    this .sorter = sorter;
1715:                    refresh();
1716:                }
1717:            }
1718:
1719:            /**
1720:             * Sets this viewer's comparator to be used for sorting elements, and triggers refiltering and 
1721:             * resorting of this viewer's element.  <code>null</code> turns sorting off.
1722:             * To get the viewer's comparator, call <code>getComparator()</code>.
1723:             * <p>
1724:             * IMPORTANT: This method was introduced in 3.2. If a reference to this viewer object 
1725:             * is passed to clients who call <code>getSorter()<code>, null may be returned from
1726:             * from that method even though the viewer is sorting its elements using the
1727:             * viewer's comparator.
1728:             * </p>
1729:             * 
1730:             * @param comparator a viewer comparator, or <code>null</code> if none
1731:             *
1732:             * @since 3.2
1733:             */
1734:            public void setComparator(ViewerComparator comparator) {
1735:                if (this .sorter != comparator) {
1736:                    this .sorter = comparator;
1737:                    refresh();
1738:                }
1739:            }
1740:
1741:            /**
1742:             * Configures whether this structured viewer uses an internal hash table to
1743:             * speeds up the mapping between elements and SWT items. This must be called
1744:             * before the viewer is given an input (via <code>setInput</code>).
1745:             * 
1746:             * @param enable
1747:             *            <code>true</code> to enable hash lookup, and
1748:             *            <code>false</code> to disable it
1749:             */
1750:            public void setUseHashlookup(boolean enable) {
1751:                Assert
1752:                        .isTrue(getInput() == null,
1753:                                "Can only enable the hash look up before input has been set");//$NON-NLS-1$
1754:                if (enable) {
1755:                    elementMap = newHashtable(CustomHashtable.DEFAULT_CAPACITY);
1756:                } else {
1757:                    elementMap = null;
1758:                }
1759:            }
1760:
1761:            /**
1762:             * Sets the comparer to use for comparing elements, or <code>null</code>
1763:             * to use the default <code>equals</code> and <code>hashCode</code>
1764:             * methods on the elements themselves.
1765:             * 
1766:             * @param comparer
1767:             *            the comparer to use for comparing elements or
1768:             *            <code>null</code>
1769:             */
1770:            public void setComparer(IElementComparer comparer) {
1771:                this .comparer = comparer;
1772:                if (elementMap != null) {
1773:                    elementMap = new CustomHashtable(elementMap, comparer);
1774:                }
1775:            }
1776:
1777:            /**
1778:             * Hook for testing.
1779:             * @param element
1780:             * @return Widget
1781:             */
1782:            public Widget testFindItem(Object element) {
1783:                return findItem(element);
1784:            }
1785:
1786:            /**
1787:             * Hook for testing.
1788:             * @param element
1789:             * @return Widget[]
1790:             * @since 3.2
1791:             */
1792:            public Widget[] testFindItems(Object element) {
1793:                return findItems(element);
1794:            }
1795:
1796:            /**
1797:             * Removes all elements from the map.
1798:             * <p>
1799:             * This method is internal to the framework; subclassers should not call
1800:             * this method.
1801:             * </p>
1802:             */
1803:            protected void unmapAllElements() {
1804:                if (elementMap != null) {
1805:                    elementMap = newHashtable(CustomHashtable.DEFAULT_CAPACITY);
1806:                }
1807:            }
1808:
1809:            /**
1810:             * Removes the given element from the internal element to widget map. Does
1811:             * nothing if mapping is disabled. If mapping is enabled, the given element
1812:             * must be present.
1813:             * <p>
1814:             * This method is internal to the framework; subclassers should not call
1815:             * this method.
1816:             * </p>
1817:             * 
1818:             * @param element
1819:             *            the element
1820:             */
1821:            protected void unmapElement(Object element) {
1822:                if (elementMap != null) {
1823:                    elementMap.remove(element);
1824:                }
1825:            }
1826:
1827:            /**
1828:             * Removes the given association from the internal element to widget map.
1829:             * Does nothing if mapping is disabled, or if the given element does not map
1830:             * to the given item.
1831:             * <p>
1832:             * This method is internal to the framework; subclassers should not call
1833:             * this method.
1834:             * </p>
1835:             * 
1836:             * @param element
1837:             *            the element
1838:             * @param item the item to unmap
1839:             * @since 2.0
1840:             */
1841:            protected void unmapElement(Object element, Widget item) {
1842:                // double-check that the element actually maps to the given item before
1843:                // unmapping it
1844:                if (elementMap != null) {
1845:                    Object widgetOrWidgets = elementMap.get(element);
1846:                    if (widgetOrWidgets == null) {
1847:                        // item was not mapped, return
1848:                        return;
1849:                    } else if (widgetOrWidgets instanceof  Widget) {
1850:                        if (item == widgetOrWidgets) {
1851:                            elementMap.remove(element);
1852:                        }
1853:                    } else {
1854:                        Widget[] widgets = (Widget[]) widgetOrWidgets;
1855:                        int indexOfItem = Arrays.asList(widgets).indexOf(item);
1856:                        if (indexOfItem == -1) {
1857:                            return;
1858:                        }
1859:                        int length = widgets.length;
1860:                        if (indexOfItem == 0) {
1861:                            if (length == 1) {
1862:                                elementMap.remove(element);
1863:                            } else {
1864:                                Widget[] updatedWidgets = new Widget[length - 1];
1865:                                System.arraycopy(widgets, 1, updatedWidgets, 0,
1866:                                        length - 1);
1867:                                elementMap.put(element, updatedWidgets);
1868:                            }
1869:                        } else {
1870:                            Widget[] updatedWidgets = new Widget[length - 1];
1871:                            System.arraycopy(widgets, 0, updatedWidgets, 0,
1872:                                    indexOfItem);
1873:                            System.arraycopy(widgets, indexOfItem + 1,
1874:                                    updatedWidgets, indexOfItem, length
1875:                                            - indexOfItem - 1);
1876:                            elementMap.put(element, updatedWidgets);
1877:                        }
1878:                    }
1879:                }
1880:            }
1881:
1882:            /**
1883:             * Updates the given elements' presentation when one or more of their
1884:             * properties change. Only the given elements are updated.
1885:             * <p>
1886:             * This does not handle structural changes (e.g. addition or removal of
1887:             * elements), and does not update any other related elements (e.g. child
1888:             * elements). To handle structural changes, use the <code>refresh</code>
1889:             * methods instead.
1890:             * </p>
1891:             * <p>
1892:             * This should be called when an element has changed in the model, in order
1893:             * to have the viewer accurately reflect the model. This method only affects
1894:             * the viewer, not the model.
1895:             * </p>
1896:             * <p>
1897:             * Specifying which properties are affected may allow the viewer to optimize
1898:             * the update. For example, if the label provider is not affected by changes
1899:             * to any of these properties, an update may not actually be required.
1900:             * Specifying <code>properties</code> as <code>null</code> forces a full
1901:             * update of the given elements.
1902:             * </p>
1903:             * <p>
1904:             * If the viewer has a sorter which is affected by a change to one of the
1905:             * properties, the elements' positions are updated to maintain the sort
1906:             * order. Note that resorting does not happen if <code>properties</code>
1907:             * is <code>null</code>.
1908:             * </p>
1909:             * <p>
1910:             * If the viewer has a filter which is affected by a change to one of the
1911:             * properties, elements may appear or disappear if the change affects
1912:             * whether or not they are filtered out.
1913:             * </p>
1914:             * 
1915:             * @param elements
1916:             *            the elements
1917:             * @param properties
1918:             *            the properties that have changed, or <code>null</code> to
1919:             *            indicate unknown
1920:             */
1921:            public void update(Object[] elements, String[] properties) {
1922:                for (int i = 0; i < elements.length; ++i) {
1923:                    update(elements[i], properties);
1924:                }
1925:            }
1926:
1927:            /**
1928:             * Updates the given element's presentation when one or more of its
1929:             * properties changes. Only the given element is updated.
1930:             * <p>
1931:             * This does not handle structural changes (e.g. addition or removal of
1932:             * elements), and does not update any other related elements (e.g. child
1933:             * elements). To handle structural changes, use the <code>refresh</code>
1934:             * methods instead.
1935:             * </p>
1936:             * <p>
1937:             * This should be called when an element has changed in the model, in order
1938:             * to have the viewer accurately reflect the model. This method only affects
1939:             * the viewer, not the model.
1940:             * </p>
1941:             * <p>
1942:             * Specifying which properties are affected may allow the viewer to optimize
1943:             * the update. For example, if the label provider is not affected by changes
1944:             * to any of these properties, an update may not actually be required.
1945:             * Specifying <code>properties</code> as <code>null</code> forces a full
1946:             * update of the element.
1947:             * </p>
1948:             * <p>
1949:             * If the viewer has a sorter which is affected by a change to one of the
1950:             * properties, the element's position is updated to maintain the sort order.
1951:             * Note that resorting does not happen if <code>properties</code> is
1952:             * <code>null</code>.
1953:             * </p>
1954:             * <p>
1955:             * If the viewer has a filter which is affected by a change to one of the
1956:             * properties, the element may appear or disappear if the change affects
1957:             * whether or not the element is filtered out.
1958:             * </p>
1959:             * 
1960:             * @param element
1961:             *            the element
1962:             * @param properties
1963:             *            the properties that have changed, or <code>null</code> to
1964:             *            indicate unknown
1965:             */
1966:            public void update(Object element, String[] properties) {
1967:                Assert.isNotNull(element);
1968:                Widget[] items = findItems(element);
1969:
1970:                for (int i = 0; i < items.length; i++) {
1971:                    internalUpdate(items[i], element, properties);
1972:                }
1973:            }
1974:
1975:            /**
1976:             * Updates the given element's presentation when one or more of its
1977:             * properties changes. Only the given element is updated.
1978:             * <p>
1979:             * EXPERIMENTAL.  Not to be used except by JDT.
1980:             * This method was added to support JDT's explorations
1981:             * into grouping by working sets, which requires viewers to support multiple 
1982:             * equal elements.  See bug 76482 for more details.  This support will
1983:             * likely be removed in Eclipse 3.3 in favor of proper support for
1984:             * multiple equal elements (which was implemented for AbtractTreeViewer in 3.2). 
1985:             * </p>
1986:             * @param widget
1987:             *            the widget for the element
1988:             * @param element
1989:             *            the element
1990:             * @param properties
1991:             *            the properties that have changed, or <code>null</code> to
1992:             *            indicate unknown
1993:             */
1994:            protected void internalUpdate(Widget widget, Object element,
1995:                    String[] properties) {
1996:                boolean needsRefilter = false;
1997:                if (properties != null) {
1998:                    for (int i = 0; i < properties.length; ++i) {
1999:                        needsRefilter = needsRefilter(element, properties[i]);
2000:                        if (needsRefilter) {
2001:                            break;
2002:                        }
2003:                    }
2004:                }
2005:                if (needsRefilter) {
2006:                    preservingSelection(new Runnable() {
2007:                        public void run() {
2008:                            internalRefresh(getRoot());
2009:                        }
2010:                    });
2011:                    return;
2012:                }
2013:
2014:                boolean needsUpdate;
2015:                if (properties == null) {
2016:                    needsUpdate = true;
2017:                } else {
2018:                    needsUpdate = false;
2019:                    IBaseLabelProvider labelProvider = getLabelProvider();
2020:                    for (int i = 0; i < properties.length; ++i) {
2021:                        needsUpdate = labelProvider.isLabelProperty(element,
2022:                                properties[i]);
2023:                        if (needsUpdate) {
2024:                            break;
2025:                        }
2026:                    }
2027:                }
2028:                if (needsUpdate) {
2029:                    updateItem(widget, element);
2030:                }
2031:            }
2032:
2033:            /**
2034:             * Copies attributes of the given element into the given widget.
2035:             * <p>
2036:             * This method is internal to the framework; subclassers should not call
2037:             * this method. Calls <code>doUpdateItem(widget, element, true)</code>.
2038:             * </p>
2039:             * 
2040:             * @param widget
2041:             *            the widget
2042:             * @param element
2043:             *            the element
2044:             */
2045:            protected final void updateItem(Widget widget, Object element) {
2046:                SafeRunnable.run(new UpdateItemSafeRunnable(widget, element,
2047:                        true));
2048:            }
2049:
2050:            /**
2051:             * Updates the selection of this viewer.
2052:             * <p>
2053:             * This framework method should be called when the selection in the viewer
2054:             * widget changes.
2055:             * </p>
2056:             * <p>
2057:             * The default implementation of this method notifies all selection change
2058:             * listeners recorded in an internal state variable. Overriding this method
2059:             * is generally not required; however, if overriding in a subclass,
2060:             * <code>super.updateSelection</code> must be invoked.
2061:             * </p>
2062:             * 
2063:             * @param selection
2064:             *            the selection, or <code>null</code> if none
2065:             */
2066:            protected void updateSelection(ISelection selection) {
2067:                SelectionChangedEvent event = new SelectionChangedEvent(this ,
2068:                        selection);
2069:                fireSelectionChanged(event);
2070:            }
2071:
2072:            /**
2073:             * Returns whether this structured viewer is configured to use an internal
2074:             * map to speed up the mapping between elements and SWT items.
2075:             * <p>
2076:             * The default implementation of this framework method checks whether the
2077:             * internal map has been initialized.
2078:             * </p>
2079:             * 
2080:             * @return <code>true</code> if the element map is enabled, and
2081:             *         <code>false</code> if disabled
2082:             */
2083:            protected boolean usingElementMap() {
2084:                return elementMap != null;
2085:            }
2086:
2087:            /* (non-Javadoc)
2088:             * @see org.eclipse.jface.viewers.ContentViewer#setLabelProvider(org.eclipse.jface.viewers.IBaseLabelProvider)
2089:             */
2090:            public void setLabelProvider(IBaseLabelProvider labelProvider) {
2091:                if (labelProvider instanceof  IColorProvider
2092:                        || labelProvider instanceof  IFontProvider) {
2093:                    colorAndFontCollector = new ColorAndFontCollectorWithProviders(
2094:                            labelProvider);
2095:                } else {
2096:                    colorAndFontCollector = new ColorAndFontCollector();
2097:                }
2098:                super .setLabelProvider(labelProvider);
2099:
2100:            }
2101:
2102:            /**
2103:             * Build a label up for the element using the supplied label provider.
2104:             * @param updateLabel The ViewerLabel to collect the result in
2105:             * @param element The element being decorated.
2106:             */
2107:            protected void buildLabel(ViewerLabel updateLabel, Object element) {
2108:
2109:                if (getLabelProvider() instanceof  IViewerLabelProvider) {
2110:                    IViewerLabelProvider itemProvider = (IViewerLabelProvider) getLabelProvider();
2111:                    itemProvider.updateLabel(updateLabel, element);
2112:
2113:                    colorAndFontCollector.setUsedDecorators();
2114:
2115:                    if (updateLabel.hasNewBackground()) {
2116:                        colorAndFontCollector.setBackground(updateLabel
2117:                                .getBackground());
2118:                    }
2119:
2120:                    if (updateLabel.hasNewForeground()) {
2121:                        colorAndFontCollector.setForeground(updateLabel
2122:                                .getForeground());
2123:                    }
2124:
2125:                    if (updateLabel.hasNewFont()) {
2126:                        colorAndFontCollector.setFont(updateLabel.getFont());
2127:                    }
2128:                    return;
2129:
2130:                }
2131:
2132:                if (getLabelProvider() instanceof  ILabelProvider) {
2133:                    ILabelProvider labelProvider = (ILabelProvider) getLabelProvider();
2134:                    updateLabel.setText(labelProvider.getText(element));
2135:                    updateLabel.setImage(labelProvider.getImage(element));
2136:                }
2137:
2138:            }
2139:
2140:            /**
2141:             * Build a label up for the element using the supplied label provider.
2142:             * @param updateLabel The ViewerLabel to collect the result in
2143:             * @param element The element being decorated.
2144:             * @param labelProvider ILabelProvider the labelProvider for the receiver.
2145:             */
2146:            void buildLabel(ViewerLabel updateLabel, Object element,
2147:                    IViewerLabelProvider labelProvider) {
2148:
2149:                labelProvider.updateLabel(updateLabel, element);
2150:
2151:                colorAndFontCollector.setUsedDecorators();
2152:
2153:                if (updateLabel.hasNewBackground()) {
2154:                    colorAndFontCollector.setBackground(updateLabel
2155:                            .getBackground());
2156:                }
2157:
2158:                if (updateLabel.hasNewForeground()) {
2159:                    colorAndFontCollector.setForeground(updateLabel
2160:                            .getForeground());
2161:                }
2162:
2163:                if (updateLabel.hasNewFont()) {
2164:                    colorAndFontCollector.setFont(updateLabel.getFont());
2165:                }
2166:
2167:            }
2168:
2169:            /**
2170:             * Build a label up for the element using the supplied label provider.
2171:             * @param updateLabel The ViewerLabel to collect the result in
2172:             * @param elementPath The path of the element being decorated.
2173:             * @param labelProvider ILabelProvider the labelProvider for the receiver.
2174:             */
2175:            void buildLabel(ViewerLabel updateLabel, TreePath elementPath,
2176:                    ITreePathLabelProvider labelProvider) {
2177:
2178:                labelProvider.updateLabel(updateLabel, elementPath);
2179:
2180:                colorAndFontCollector.setUsedDecorators();
2181:
2182:                if (updateLabel.hasNewBackground()) {
2183:                    colorAndFontCollector.setBackground(updateLabel
2184:                            .getBackground());
2185:                }
2186:
2187:                if (updateLabel.hasNewForeground()) {
2188:                    colorAndFontCollector.setForeground(updateLabel
2189:                            .getForeground());
2190:                }
2191:
2192:                if (updateLabel.hasNewFont()) {
2193:                    colorAndFontCollector.setFont(updateLabel.getFont());
2194:                }
2195:
2196:            }
2197:
2198:            /**
2199:             * Build a label up for the element using the supplied label provider.
2200:             * @param updateLabel The ViewerLabel to collect the result in
2201:             * @param element The element being decorated.
2202:             * @param labelProvider ILabelProvider the labelProvider for the receiver.
2203:             */
2204:            void buildLabel(ViewerLabel updateLabel, Object element,
2205:                    ILabelProvider labelProvider) {
2206:                updateLabel.setText(labelProvider.getText(element));
2207:                updateLabel.setImage(labelProvider.getImage(element));
2208:            }
2209:
2210:            /**
2211:             * Get the ColorAndFontCollector for the receiver.
2212:             * @return ColorAndFontCollector 
2213:             * @since 3.1
2214:             */
2215:            protected ColorAndFontCollector getColorAndFontCollector() {
2216:                return colorAndFontCollector;
2217:            }
2218:
2219:            protected void handleDispose(DisposeEvent event) {
2220:                super .handleDispose(event);
2221:                sorter = null;
2222:                comparer = null;
2223:                if (filters != null)
2224:                    filters.clear();
2225:                elementMap = newHashtable(1);
2226:                openListeners.clear();
2227:                doubleClickListeners.clear();
2228:                colorAndFontCollector.clear();
2229:                postSelectionChangedListeners.clear();
2230:            }
2231:
2232:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.