001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: * Stefan Xenos, IBM; Chris Torrence, ITT Visual Information Solutions - bug 51580
011: *******************************************************************************/package org.eclipse.ui.internal;
012:
013: import java.util.BitSet;
014: import java.util.HashMap;
015: import java.util.Iterator;
016: import java.util.Map;
017:
018: import org.eclipse.core.runtime.Assert;
019: import org.eclipse.core.runtime.IStatus;
020: import org.eclipse.core.runtime.ListenerList;
021: import org.eclipse.jface.resource.ImageDescriptor;
022: import org.eclipse.jface.resource.JFaceResources;
023: import org.eclipse.jface.util.IPropertyChangeListener;
024: import org.eclipse.jface.util.PropertyChangeEvent;
025: import org.eclipse.osgi.util.NLS;
026: import org.eclipse.swt.events.DisposeEvent;
027: import org.eclipse.swt.events.DisposeListener;
028: import org.eclipse.swt.graphics.Image;
029: import org.eclipse.swt.widgets.Control;
030: import org.eclipse.swt.widgets.Display;
031: import org.eclipse.ui.IPropertyListener;
032: import org.eclipse.ui.ISaveablePart;
033: import org.eclipse.ui.ISaveablesLifecycleListener;
034: import org.eclipse.ui.ISharedImages;
035: import org.eclipse.ui.ISizeProvider;
036: import org.eclipse.ui.IWorkbenchPart;
037: import org.eclipse.ui.IWorkbenchPart2;
038: import org.eclipse.ui.IWorkbenchPart3;
039: import org.eclipse.ui.IWorkbenchPartConstants;
040: import org.eclipse.ui.IWorkbenchPartReference;
041: import org.eclipse.ui.IWorkbenchPartSite;
042: import org.eclipse.ui.PartInitException;
043: import org.eclipse.ui.PlatformUI;
044: import org.eclipse.ui.internal.misc.UIListenerLogging;
045: import org.eclipse.ui.internal.util.Util;
046:
047: /**
048: *
049: */
050: public abstract class WorkbenchPartReference implements
051: IWorkbenchPartReference, ISizeProvider {
052:
053: /**
054: * Internal property ID: Indicates that the underlying part was created
055: */
056: public static final int INTERNAL_PROPERTY_OPENED = 0x211;
057:
058: /**
059: * Internal property ID: Indicates that the underlying part was destroyed
060: */
061: public static final int INTERNAL_PROPERTY_CLOSED = 0x212;
062:
063: /**
064: * Internal property ID: Indicates that the result of IEditorReference.isPinned()
065: */
066: public static final int INTERNAL_PROPERTY_PINNED = 0x213;
067:
068: /**
069: * Internal property ID: Indicates that the result of getVisible() has changed
070: */
071: public static final int INTERNAL_PROPERTY_VISIBLE = 0x214;
072:
073: /**
074: * Internal property ID: Indicates that the result of isZoomed() has changed
075: */
076: public static final int INTERNAL_PROPERTY_ZOOMED = 0x215;
077:
078: /**
079: * Internal property ID: Indicates that the part has an active child and the
080: * active child has changed. (fired by PartStack)
081: */
082: public static final int INTERNAL_PROPERTY_ACTIVE_CHILD_CHANGED = 0x216;
083:
084: /**
085: * Internal property ID: Indicates that changed in the min / max
086: * state has changed
087: */
088: public static final int INTERNAL_PROPERTY_MAXIMIZED = 0x217;
089:
090: // State constants //////////////////////////////
091:
092: /**
093: * State constant indicating that the part is not created yet
094: */
095: public static int STATE_LAZY = 0;
096:
097: /**
098: * State constant indicating that the part is in the process of being created
099: */
100: public static int STATE_CREATION_IN_PROGRESS = 1;
101:
102: /**
103: * State constant indicating that the part has been created
104: */
105: public static int STATE_CREATED = 2;
106:
107: /**
108: * State constant indicating that the reference has been disposed (the reference shouldn't be
109: * used anymore)
110: */
111: public static int STATE_DISPOSED = 3;
112:
113: /**
114: * Current state of the reference. Used to detect recursive creation errors, disposed
115: * references, etc.
116: */
117: private int state = STATE_LAZY;
118:
119: protected IWorkbenchPart part;
120:
121: private String id;
122:
123: protected PartPane pane;
124:
125: private boolean pinned = false;
126:
127: private String title;
128:
129: private String tooltip;
130:
131: /**
132: * Stores the current Image for this part reference. Lazily created. Null if not allocated.
133: */
134: private Image image = null;
135:
136: private ImageDescriptor defaultImageDescriptor;
137:
138: /**
139: * Stores the current image descriptor for the part.
140: */
141: private ImageDescriptor imageDescriptor;
142:
143: /**
144: * API listener list
145: */
146: private ListenerList propChangeListeners = new ListenerList();
147:
148: /**
149: * Internal listener list. Listens to the INTERNAL_PROPERTY_* property change events that are not yet API.
150: * TODO: Make these properties API in 3.2
151: */
152: private ListenerList internalPropChangeListeners = new ListenerList();
153:
154: private ListenerList partChangeListeners = new ListenerList();
155:
156: private String partName;
157:
158: private String contentDescription;
159:
160: protected Map propertyCache = new HashMap();
161:
162: /**
163: * Used to remember which events have been queued.
164: */
165: private BitSet queuedEvents = new BitSet();
166:
167: private boolean queueEvents = false;
168:
169: private static DisposeListener prematureDisposeListener = new DisposeListener() {
170: public void widgetDisposed(DisposeEvent e) {
171: WorkbenchPlugin.log(new RuntimeException(
172: "Widget disposed too early!")); //$NON-NLS-1$
173: }
174: };
175:
176: private IPropertyListener propertyChangeListener = new IPropertyListener() {
177: /* (non-Javadoc)
178: * @see org.eclipse.ui.IPropertyListener#propertyChanged(java.lang.Object, int)
179: */
180: public void propertyChanged(Object source, int propId) {
181: partPropertyChanged(source, propId);
182: }
183: };
184:
185: private IPropertyChangeListener partPropertyChangeListener = new IPropertyChangeListener() {
186: public void propertyChange(PropertyChangeEvent event) {
187: partPropertyChanged(event);
188: }
189: };
190:
191: public WorkbenchPartReference() {
192: //no-op
193: }
194:
195: public boolean isDisposed() {
196: return state == STATE_DISPOSED;
197: }
198:
199: protected void checkReference() {
200: if (state == STATE_DISPOSED) {
201: throw new RuntimeException(
202: "Error: IWorkbenchPartReference disposed"); //$NON-NLS-1$
203: }
204: }
205:
206: /**
207: * Calling this with deferEvents(true) will queue all property change events until a subsequent
208: * call to deferEvents(false). This should be used at the beginning of a batch of related changes
209: * to prevent duplicate property change events from being sent.
210: *
211: * @param shouldQueue
212: */
213: private void deferEvents(boolean shouldQueue) {
214: queueEvents = shouldQueue;
215:
216: if (queueEvents == false) {
217: // do not use nextSetBit, to allow compilation against JCL Foundation (bug 80053)
218: for (int i = 0, n = queuedEvents.size(); i < n; ++i) {
219: if (queuedEvents.get(i)) {
220: firePropertyChange(i);
221: queuedEvents.clear(i);
222: }
223: }
224: }
225: }
226:
227: protected void setTitle(String newTitle) {
228: if (Util.equals(title, newTitle)) {
229: return;
230: }
231:
232: title = newTitle;
233: firePropertyChange(IWorkbenchPartConstants.PROP_TITLE);
234: }
235:
236: protected void setPartName(String newPartName) {
237: if (Util.equals(partName, newPartName)) {
238: return;
239: }
240:
241: partName = newPartName;
242: firePropertyChange(IWorkbenchPartConstants.PROP_PART_NAME);
243: }
244:
245: protected void setContentDescription(String newContentDescription) {
246: if (Util.equals(contentDescription, newContentDescription)) {
247: return;
248: }
249:
250: contentDescription = newContentDescription;
251: firePropertyChange(IWorkbenchPartConstants.PROP_CONTENT_DESCRIPTION);
252: }
253:
254: protected void setImageDescriptor(ImageDescriptor descriptor) {
255: if (Util.equals(imageDescriptor, descriptor)) {
256: return;
257: }
258:
259: Image oldImage = image;
260: ImageDescriptor oldDescriptor = imageDescriptor;
261: image = null;
262: imageDescriptor = descriptor;
263:
264: // Don't queue events triggered by image changes. We'll dispose the image
265: // immediately after firing the event, so we need to fire it right away.
266: immediateFirePropertyChange(IWorkbenchPartConstants.PROP_TITLE);
267: if (queueEvents) {
268: // If there's a PROP_TITLE event queued, remove it from the queue because
269: // we've just fired it.
270: queuedEvents.clear(IWorkbenchPartConstants.PROP_TITLE);
271: }
272:
273: // If we had allocated the old image, deallocate it now (AFTER we fire the property change
274: // -- listeners may need to clean up references to the old image)
275: if (oldImage != null) {
276: JFaceResources.getResources().destroy(oldDescriptor);
277: }
278: }
279:
280: protected void setToolTip(String newToolTip) {
281: if (Util.equals(tooltip, newToolTip)) {
282: return;
283: }
284:
285: tooltip = newToolTip;
286: firePropertyChange(IWorkbenchPartConstants.PROP_TITLE);
287: }
288:
289: protected void partPropertyChanged(Object source, int propId) {
290:
291: // We handle these properties directly (some of them may be transformed
292: // before firing events to workbench listeners)
293: if (propId == IWorkbenchPartConstants.PROP_CONTENT_DESCRIPTION
294: || propId == IWorkbenchPartConstants.PROP_PART_NAME
295: || propId == IWorkbenchPartConstants.PROP_TITLE) {
296:
297: refreshFromPart();
298: } else {
299: // Any other properties are just reported to listeners verbatim
300: firePropertyChange(propId);
301: }
302:
303: // Let the model manager know as well
304: if (propId == IWorkbenchPartConstants.PROP_DIRTY) {
305: IWorkbenchPart actualPart = getPart(false);
306: if (actualPart != null) {
307: SaveablesList modelManager = (SaveablesList) actualPart
308: .getSite().getService(
309: ISaveablesLifecycleListener.class);
310: modelManager.dirtyChanged(actualPart);
311: }
312: }
313: }
314:
315: protected void partPropertyChanged(PropertyChangeEvent event) {
316: firePartPropertyChange(event);
317: }
318:
319: /**
320: * Refreshes all cached values with the values from the real part
321: */
322: protected void refreshFromPart() {
323: deferEvents(true);
324:
325: setPartName(computePartName());
326: setTitle(computeTitle());
327: setContentDescription(computeContentDescription());
328: setToolTip(getRawToolTip());
329: setImageDescriptor(computeImageDescriptor());
330:
331: deferEvents(false);
332: }
333:
334: protected ImageDescriptor computeImageDescriptor() {
335: if (part != null) {
336: return ImageDescriptor.createFromImage(
337: part.getTitleImage(), Display.getCurrent());
338: }
339: return defaultImageDescriptor;
340: }
341:
342: public void init(String id, String title, String tooltip,
343: ImageDescriptor desc, String paneName,
344: String contentDescription) {
345: Assert.isNotNull(id);
346: Assert.isNotNull(title);
347: Assert.isNotNull(tooltip);
348: Assert.isNotNull(desc);
349: Assert.isNotNull(paneName);
350: Assert.isNotNull(contentDescription);
351:
352: this .id = id;
353: this .title = title;
354: this .tooltip = tooltip;
355: this .partName = paneName;
356: this .contentDescription = contentDescription;
357: this .defaultImageDescriptor = desc;
358: this .imageDescriptor = computeImageDescriptor();
359: }
360:
361: /**
362: * Releases any references maintained by this part reference
363: * when its actual part becomes known (not called when it is disposed).
364: */
365: protected void releaseReferences() {
366:
367: }
368:
369: /* package */void addInternalPropertyListener(
370: IPropertyListener listener) {
371: internalPropChangeListeners.add(listener);
372: }
373:
374: /* package */void removeInternalPropertyListener(
375: IPropertyListener listener) {
376: internalPropChangeListeners.remove(listener);
377: }
378:
379: protected void fireInternalPropertyChange(int id) {
380: Object listeners[] = internalPropChangeListeners.getListeners();
381: for (int i = 0; i < listeners.length; i++) {
382: ((IPropertyListener) listeners[i])
383: .propertyChanged(this , id);
384: }
385: }
386:
387: /**
388: * @see IWorkbenchPart
389: */
390: public void addPropertyListener(IPropertyListener listener) {
391: // The properties of a disposed reference will never change, so don't
392: // add listeners
393: if (isDisposed()) {
394: return;
395: }
396:
397: propChangeListeners.add(listener);
398: }
399:
400: /**
401: * @see IWorkbenchPart
402: */
403: public void removePropertyListener(IPropertyListener listener) {
404: // Currently I'm not calling checkReference here for fear of breaking things late in 3.1, but it may
405: // make sense to do so later. For now we just turn it into a NOP if the reference is disposed.
406: if (isDisposed()) {
407: return;
408: }
409: propChangeListeners.remove(listener);
410: }
411:
412: public final String getId() {
413: if (part != null) {
414: IWorkbenchPartSite site = part.getSite();
415: if (site != null) {
416: return site.getId();
417: }
418: }
419: return Util.safeString(id);
420: }
421:
422: public String getTitleToolTip() {
423: return Util.safeString(tooltip);
424: }
425:
426: protected final String getRawToolTip() {
427: return Util.safeString(part.getTitleToolTip());
428: }
429:
430: /**
431: * Returns the pane name for the part
432: *
433: * @return the pane name for the part
434: */
435: public String getPartName() {
436: return Util.safeString(partName);
437: }
438:
439: /**
440: * Gets the part name directly from the associated workbench part,
441: * or the empty string if none.
442: *
443: * @return
444: */
445: protected final String getRawPartName() {
446: String result = ""; //$NON-NLS-1$
447:
448: if (part instanceof IWorkbenchPart2) {
449: IWorkbenchPart2 part2 = (IWorkbenchPart2) part;
450:
451: result = Util.safeString(part2.getPartName());
452: }
453:
454: return result;
455: }
456:
457: protected String computePartName() {
458: return getRawPartName();
459: }
460:
461: /**
462: * Returns the content description for this part.
463: *
464: * @return the pane name for the part
465: */
466: public String getContentDescription() {
467: return Util.safeString(contentDescription);
468: }
469:
470: /**
471: * Computes a new content description for the part. Subclasses may override to change the
472: * default behavior
473: *
474: * @return the new content description for the part
475: */
476: protected String computeContentDescription() {
477: return getRawContentDescription();
478: }
479:
480: /**
481: * Returns the content description as set directly by the part, or the empty string if none
482: *
483: * @return the unmodified content description from the part (or the empty string if none)
484: */
485: protected final String getRawContentDescription() {
486: if (part instanceof IWorkbenchPart2) {
487: IWorkbenchPart2 part2 = (IWorkbenchPart2) part;
488:
489: return part2.getContentDescription();
490: }
491:
492: return ""; //$NON-NLS-1$
493: }
494:
495: public boolean isDirty() {
496: if (!(part instanceof ISaveablePart)) {
497: return false;
498: }
499: return ((ISaveablePart) part).isDirty();
500: }
501:
502: public String getTitle() {
503: return Util.safeString(title);
504: }
505:
506: /**
507: * Computes a new title for the part. Subclasses may override to change the default behavior.
508: *
509: * @return the title for the part
510: */
511: protected String computeTitle() {
512: return getRawTitle();
513: }
514:
515: /**
516: * Returns the unmodified title for the part, or the empty string if none
517: *
518: * @return the unmodified title, as set by the IWorkbenchPart. Returns the empty string if none.
519: */
520: protected final String getRawTitle() {
521: return Util.safeString(part.getTitle());
522: }
523:
524: public final Image getTitleImage() {
525: if (isDisposed()) {
526: return PlatformUI.getWorkbench().getSharedImages()
527: .getImage(ISharedImages.IMG_DEF_VIEW);
528: }
529:
530: if (image == null) {
531: image = JFaceResources.getResources()
532: .createImageWithDefault(imageDescriptor);
533: }
534: return image;
535: }
536:
537: public ImageDescriptor getTitleImageDescriptor() {
538: if (isDisposed()) {
539: return PlatformUI.getWorkbench().getSharedImages()
540: .getImageDescriptor(ISharedImages.IMG_DEF_VIEW);
541: }
542:
543: return imageDescriptor;
544: }
545:
546: /* package */void fireVisibilityChange() {
547: fireInternalPropertyChange(INTERNAL_PROPERTY_VISIBLE);
548: }
549:
550: /* package */void fireZoomChange() {
551: fireInternalPropertyChange(INTERNAL_PROPERTY_ZOOMED);
552: }
553:
554: public boolean getVisible() {
555: if (isDisposed()) {
556: return false;
557: }
558: return getPane().getVisible();
559: }
560:
561: public void setVisible(boolean isVisible) {
562: if (isDisposed()) {
563: return;
564: }
565: getPane().setVisible(isVisible);
566: }
567:
568: protected void firePropertyChange(int id) {
569:
570: if (queueEvents) {
571: queuedEvents.set(id);
572: return;
573: }
574:
575: immediateFirePropertyChange(id);
576: }
577:
578: private void immediateFirePropertyChange(int id) {
579: UIListenerLogging.logPartReferencePropertyChange(this , id);
580: Object listeners[] = propChangeListeners.getListeners();
581: for (int i = 0; i < listeners.length; i++) {
582: ((IPropertyListener) listeners[i])
583: .propertyChanged(part, id);
584: }
585:
586: fireInternalPropertyChange(id);
587: }
588:
589: public final IWorkbenchPart getPart(boolean restore) {
590: if (isDisposed()) {
591: return null;
592: }
593:
594: if (part == null && restore) {
595:
596: if (state == STATE_CREATION_IN_PROGRESS) {
597: IStatus result = WorkbenchPlugin
598: .getStatus(new PartInitException(
599: NLS
600: .bind(
601: "Warning: Detected recursive attempt by part {0} to create itself (this is probably, but not necessarily, a bug)", //$NON-NLS-1$
602: getId())));
603: WorkbenchPlugin.log(result);
604: return null;
605: }
606:
607: try {
608: state = STATE_CREATION_IN_PROGRESS;
609:
610: IWorkbenchPart newPart = createPart();
611: if (newPart != null) {
612: part = newPart;
613: // Add a dispose listener to the part. This dispose listener does nothing but log an exception
614: // if the part's widgets get disposed unexpectedly. The workbench part reference is the only
615: // object that should dispose this control, and it will remove the listener before it does so.
616: getPane().getControl().addDisposeListener(
617: prematureDisposeListener);
618: part.addPropertyListener(propertyChangeListener);
619: if (part instanceof IWorkbenchPart3) {
620: ((IWorkbenchPart3) part)
621: .addPartPropertyListener(partPropertyChangeListener);
622: }
623:
624: refreshFromPart();
625: releaseReferences();
626:
627: fireInternalPropertyChange(INTERNAL_PROPERTY_OPENED);
628:
629: ISizeProvider sizeProvider = (ISizeProvider) Util
630: .getAdapter(part, ISizeProvider.class);
631: if (sizeProvider != null) {
632: // If this part has a preferred size, indicate that the preferred size may have changed at this point
633: if (sizeProvider.getSizeFlags(true) != 0
634: || sizeProvider.getSizeFlags(false) != 0) {
635: fireInternalPropertyChange(IWorkbenchPartConstants.PROP_PREFERRED_SIZE);
636: }
637: }
638: }
639: } finally {
640: state = STATE_CREATED;
641: }
642: }
643:
644: return part;
645: }
646:
647: protected abstract IWorkbenchPart createPart();
648:
649: protected abstract PartPane createPane();
650:
651: /**
652: * Returns the part pane for this part reference. Does not return null. Should not be called
653: * if the reference has been disposed.
654: *
655: * TODO: clean up all code that has any possibility of calling this on a disposed reference
656: * and make this method throw an exception if anyone else attempts to do so.
657: *
658: * @return
659: */
660: public final PartPane getPane() {
661:
662: // Note: we should never call this if the reference has already been disposed, since it
663: // may cause a PartPane to be created and leaked.
664: if (pane == null) {
665: pane = createPane();
666: }
667: return pane;
668: }
669:
670: public final void dispose() {
671:
672: if (isDisposed()) {
673: return;
674: }
675:
676: // Store the current title, tooltip, etc. so that anyone that they can be returned to
677: // anyone that held on to the disposed reference.
678: partName = getPartName();
679: contentDescription = getContentDescription();
680: tooltip = getTitleToolTip();
681: title = getTitle();
682:
683: if (state == STATE_CREATION_IN_PROGRESS) {
684: IStatus result = WorkbenchPlugin
685: .getStatus(new PartInitException(
686: NLS
687: .bind(
688: "Warning: Blocked recursive attempt by part {0} to dispose itself during creation", //$NON-NLS-1$
689: getId())));
690: WorkbenchPlugin.log(result);
691: return;
692: }
693:
694: // Disposing the pane disposes the part's widgets. The part's widgets need to be disposed before the part itself.
695: if (pane != null) {
696: // Remove the dispose listener since this is the correct place for the widgets to get disposed
697: Control targetControl = getPane().getControl();
698: if (targetControl != null) {
699: targetControl
700: .removeDisposeListener(prematureDisposeListener);
701: }
702: pane.dispose();
703: }
704:
705: doDisposePart();
706:
707: if (pane != null) {
708: pane.removeContributions();
709: }
710:
711: clearListenerList(internalPropChangeListeners);
712: clearListenerList(partChangeListeners);
713: Image oldImage = image;
714: ImageDescriptor oldDescriptor = imageDescriptor;
715: image = null;
716:
717: state = STATE_DISPOSED;
718: imageDescriptor = ImageDescriptor.getMissingImageDescriptor();
719: defaultImageDescriptor = ImageDescriptor
720: .getMissingImageDescriptor();
721: immediateFirePropertyChange(IWorkbenchPartConstants.PROP_TITLE);
722: clearListenerList(propChangeListeners);
723:
724: if (oldImage != null) {
725: JFaceResources.getResources().destroy(oldDescriptor);
726: }
727: }
728:
729: /**
730: * Clears all of the listeners in a listener list. TODO Bug 117519 Remove
731: * this method when fixed.
732: *
733: * @param list
734: * The list to be clear; must not be <code>null</code>.
735: */
736: private final void clearListenerList(final ListenerList list) {
737: final Object[] listeners = list.getListeners();
738: for (int i = 0; i < listeners.length; i++) {
739: list.remove(listeners[i]);
740: }
741: }
742:
743: /**
744: *
745: */
746: protected void doDisposePart() {
747: if (part != null) {
748: fireInternalPropertyChange(INTERNAL_PROPERTY_CLOSED);
749: // Don't let exceptions in client code bring us down. Log them and continue.
750: try {
751: part.removePropertyListener(propertyChangeListener);
752: if (part instanceof IWorkbenchPart3) {
753: ((IWorkbenchPart3) part)
754: .removePartPropertyListener(partPropertyChangeListener);
755: }
756: part.dispose();
757: } catch (Exception e) {
758: WorkbenchPlugin.log(e);
759: }
760: part = null;
761: }
762: }
763:
764: public void setPinned(boolean newPinned) {
765: if (isDisposed()) {
766: return;
767: }
768:
769: if (newPinned == pinned) {
770: return;
771: }
772:
773: pinned = newPinned;
774:
775: setImageDescriptor(computeImageDescriptor());
776:
777: fireInternalPropertyChange(INTERNAL_PROPERTY_PINNED);
778: }
779:
780: public boolean isPinned() {
781: return pinned;
782: }
783:
784: /* (non-Javadoc)
785: * @see org.eclipse.ui.IWorkbenchPartReference#getPartProperty(java.lang.String)
786: */
787: public String getPartProperty(String key) {
788: if (part != null) {
789: if (part instanceof IWorkbenchPart3) {
790: return ((IWorkbenchPart3) part).getPartProperty(key);
791: }
792: } else {
793: return (String) propertyCache.get(key);
794: }
795: return null;
796: }
797:
798: /* (non-Javadoc)
799: * @see org.eclipse.ui.IWorkbenchPartReference#addPartPropertyListener(org.eclipse.jface.util.IPropertyChangeListener)
800: */
801: public void addPartPropertyListener(IPropertyChangeListener listener) {
802: if (isDisposed()) {
803: return;
804: }
805: partChangeListeners.add(listener);
806: }
807:
808: /* (non-Javadoc)
809: * @see org.eclipse.ui.IWorkbenchPartReference#removePartPropertyListener(org.eclipse.jface.util.IPropertyChangeListener)
810: */
811: public void removePartPropertyListener(
812: IPropertyChangeListener listener) {
813: if (isDisposed()) {
814: return;
815: }
816: partChangeListeners.remove(listener);
817: }
818:
819: protected void firePartPropertyChange(PropertyChangeEvent event) {
820: Object[] l = partChangeListeners.getListeners();
821: for (int i = 0; i < l.length; i++) {
822: ((IPropertyChangeListener) l[i]).propertyChange(event);
823: }
824: }
825:
826: protected void createPartProperties(IWorkbenchPart3 workbenchPart) {
827: Iterator i = propertyCache.entrySet().iterator();
828: while (i.hasNext()) {
829: Map.Entry e = (Map.Entry) i.next();
830: workbenchPart.setPartProperty((String) e.getKey(),
831: (String) e.getValue());
832: }
833: }
834:
835: /* (non-Javadoc)
836: * @see org.eclipse.ui.ISizeProvider#computePreferredSize(boolean, int, int, int)
837: */
838: public int computePreferredSize(boolean width,
839: int availableParallel, int availablePerpendicular,
840: int preferredResult) {
841:
842: ISizeProvider sizeProvider = (ISizeProvider) Util.getAdapter(
843: part, ISizeProvider.class);
844: if (sizeProvider != null) {
845: return sizeProvider.computePreferredSize(width,
846: availableParallel, availablePerpendicular,
847: preferredResult);
848: }
849:
850: return preferredResult;
851: }
852:
853: /* (non-Javadoc)
854: * @see org.eclipse.ui.ISizeProvider#getSizeFlags(boolean)
855: */
856: public int getSizeFlags(boolean width) {
857: ISizeProvider sizeProvider = (ISizeProvider) Util.getAdapter(
858: part, ISizeProvider.class);
859: if (sizeProvider != null) {
860: return sizeProvider.getSizeFlags(width);
861: }
862: return 0;
863: }
864:
865: }
|