KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > PartPane


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal;
12
13 import org.eclipse.core.runtime.ListenerList;
14 import org.eclipse.jface.action.MenuManager;
15 import org.eclipse.jface.util.IPropertyChangeListener;
16 import org.eclipse.jface.util.PropertyChangeEvent;
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.events.FocusAdapter;
19 import org.eclipse.swt.events.FocusEvent;
20 import org.eclipse.swt.events.KeyAdapter;
21 import org.eclipse.swt.events.KeyEvent;
22 import org.eclipse.swt.events.KeyListener;
23 import org.eclipse.swt.events.SelectionAdapter;
24 import org.eclipse.swt.events.SelectionEvent;
25 import org.eclipse.swt.events.TraverseEvent;
26 import org.eclipse.swt.events.TraverseListener;
27 import org.eclipse.swt.graphics.Point;
28 import org.eclipse.swt.graphics.Rectangle;
29 import org.eclipse.swt.layout.FillLayout;
30 import org.eclipse.swt.widgets.Composite;
31 import org.eclipse.swt.widgets.Control;
32 import org.eclipse.swt.widgets.Event;
33 import org.eclipse.swt.widgets.Listener;
34 import org.eclipse.swt.widgets.Menu;
35 import org.eclipse.swt.widgets.MenuItem;
36 import org.eclipse.swt.widgets.Sash;
37 import org.eclipse.ui.IPropertyListener;
38 import org.eclipse.ui.IWorkbenchPart;
39 import org.eclipse.ui.IWorkbenchPartReference;
40 import org.eclipse.ui.internal.dnd.SwtUtil;
41 import org.eclipse.ui.part.MultiEditor;
42 import org.eclipse.ui.presentations.IPresentablePart;
43
44 /**
45  * Provides the common behavior for both views
46  * and editor panes.
47  *
48  * TODO: Delete ViewPane and EditorPane, and make this class non-abstract.
49  *
50  * TODO: Stop subclassing LayoutPart. This class cannot be interchanged with other LayoutParts.
51  * Pointers that refer to PartPane instances should do so directly rather than referring to
52  * LayoutPart and downcasting. The getPresentablePart() method only applies to PartPanes, and
53  * should be removed from LayoutPart.
54  */

55 public abstract class PartPane extends LayoutPart implements IPropertyListener,
56         Listener, IPropertyChangeListener {
57
58     public static final String JavaDoc PROP_ZOOMED = "zoomed"; //$NON-NLS-1$
59

60     private boolean isZoomed = false;
61
62     private MenuManager paneMenuManager;
63     private ListenerList listeners = new ListenerList();
64     private ListenerList partListeners = new ListenerList();
65
66     protected IWorkbenchPartReference partReference;
67
68     protected WorkbenchPage page;
69
70     protected Composite control;
71
72     private boolean inLayout = true;
73     
74     private TraverseListener traverseListener = new TraverseListener() {
75         /* (non-Javadoc)
76          * @see org.eclipse.swt.events.TraverseListener#keyTraversed(org.eclipse.swt.events.TraverseEvent)
77          */

78         public void keyTraversed(TraverseEvent e) {
79             // Hack: Currently, SWT sets focus whenever we call Control.traverse. This doesn't
80
// cause too much of a problem for ctrl-pgup and ctrl-pgdn, but it is seriously unexpected
81
// for other traversal events. When (and if) it becomes possible to call traverse() without
82
// forcing a focus change, this if statement should be removed and ALL events should be
83
// forwarded to the container.
84
if (e.detail == SWT.TRAVERSE_PAGE_NEXT
85                     || e.detail == SWT.TRAVERSE_PAGE_PREVIOUS) {
86                 ILayoutContainer container = getContainer();
87                 if (container != null && container instanceof LayoutPart) {
88                     LayoutPart parent = (LayoutPart) container;
89                     Control parentControl = parent.getControl();
90                     if (parentControl != null && !parentControl.isDisposed()) {
91                         e.doit = parentControl.traverse(e.detail);
92                         if (e.doit) {
93                             e.detail = SWT.TRAVERSE_NONE;
94                         }
95                     }
96                 }
97             }
98         }
99
100     };
101
102     private boolean busy;
103
104     public static class Sashes {
105         public Sash left;
106
107         public Sash right;
108
109         public Sash top;
110
111         public Sash bottom;
112     }
113
114     /**
115      * Construct a pane for a part.
116      */

117     public PartPane(IWorkbenchPartReference partReference,
118             WorkbenchPage workbenchPage) {
119         super(partReference.getId());
120         this.partReference = partReference;
121         this.page = workbenchPage;
122     }
123
124     public void addSizeMenuItem(Menu menu, int index) {
125         //Add size menu
126
MenuItem item = new MenuItem(menu, SWT.CASCADE, index);
127         item.setText(WorkbenchMessages.PartPane_size);
128         Menu sizeMenu = new Menu(menu);
129         item.setMenu(sizeMenu);
130         addSizeItems(sizeMenu);
131     }
132
133     /**
134      *
135      */

136     public void createControl(Composite parent) {
137         if (getControl() != null) {
138             return;
139         }
140
141         partReference.addPropertyListener(this);
142         partReference.addPartPropertyListener(this);
143         // Create view form.
144
control = new Composite(parent, SWT.NONE);
145         control.setLayout(new FillLayout());
146         // the part should never be visible by default. It will be made visible
147
// by activation. This allows us to have views appear in tabs without
148
// becoming active by default.
149
control.setVisible(false);
150         control.moveAbove(null);
151         // Create a title bar.
152
createTitleBar();
153
154         
155         // When the pane or any child gains focus, notify the workbench.
156
control.addListener(SWT.Activate, this);
157
158         control.addTraverseListener(traverseListener);
159     }
160
161     /**
162      * Create a title bar for the pane if required.
163      */

164     protected abstract void createTitleBar();
165
166     /**
167      * @private
168      */

169     public void dispose() {
170         super.dispose();
171
172         if ((control != null) && (!control.isDisposed())) {
173             control.removeListener(SWT.Activate, this);
174             control.removeTraverseListener(traverseListener);
175             control.dispose();
176             control = null;
177         }
178         if ((paneMenuManager != null)) {
179             paneMenuManager.dispose();
180             paneMenuManager = null;
181         }
182         
183         partReference.removePropertyListener(this);
184         partReference.removePartPropertyListener(this);
185     }
186
187     /**
188      * User has requested to close the pane.
189      * Take appropriate action depending on type.
190      */

191     abstract public void doHide();
192
193     /**
194      * Zooms in on the part contained in this pane.
195      */

196     protected void doZoom() {
197         if (isDocked()) {
198             page.toggleZoom(partReference);
199         }
200     }
201
202     /**
203      * Gets the presentation bounds.
204      */

205     public Rectangle getBounds() {
206         return getControl().getBounds();
207     }
208
209     /**
210      * Get the control.
211      */

212     public Control getControl() {
213         return control;
214     }
215
216     /**
217      * Answer the part child.
218      */

219     public IWorkbenchPartReference getPartReference() {
220         return partReference;
221     }
222
223     /**
224      * @see Listener
225      */

226     public void handleEvent(Event event) {
227         if (event.type == SWT.Activate) {
228             if (inLayout) {
229                 requestActivation();
230             }
231         }
232     }
233
234     /**
235      * Return whether the pane is zoomed or not
236      */

237     public boolean isZoomed() {
238         return isZoomed;
239     }
240
241     /**
242      * Move the control over another one.
243      */

244     public void moveAbove(Control refControl) {
245         if (getControl() != null) {
246             getControl().moveAbove(refControl);
247         }
248     }
249
250     /**
251      * Notify the workbook page that the part pane has
252      * been activated by the user.
253      */

254     public void requestActivation() {
255         IWorkbenchPart part = partReference.getPart(true);
256         // Cannot activate the outer bit of a MultiEditor. In previous versions of the
257
// workbench, MultiEditors had their own implementation of EditorPane for the purpose
258
// of overriding requestActivation with a NOP... however, keeping the old pattern would
259
// mean it is necessary to eagerly activate an editor's plugin in order to determine
260
// what type of pane to create.
261
if (part instanceof MultiEditor) {
262             return;
263         }
264         
265         this.page.requestActivation(part);
266     }
267
268     /**
269      * Sets the parent for this part.
270      */

271     public void setContainer(ILayoutContainer container) {
272         
273         if (container instanceof LayoutPart) {
274             LayoutPart part = (LayoutPart) container;
275             
276             Control containerControl = part.getControl();
277             
278             if (containerControl != null) {
279                 Control control = getControl();
280                 Composite newParent = containerControl.getParent();
281                 if (control != null && newParent != control.getParent()) {
282                     reparent(newParent);
283                 }
284             }
285         }
286         super.setContainer(container);
287     }
288
289     /**
290      * Shows the receiver if <code>visible</code> is true otherwise hide it.
291      */

292     public void setVisible(boolean makeVisible) {
293         // Avoid redundant visibility changes
294
if (makeVisible == getVisible()) {
295             return;
296         }
297         
298         if (makeVisible) {
299             partReference.getPart(true);
300         }
301         
302         super.setVisible(makeVisible);
303         
304         ((WorkbenchPartReference) partReference).fireVisibilityChange();
305     }
306     
307     /**
308      * Sets focus to this part.
309      */

310     public void setFocus() {
311         requestActivation();
312
313         IWorkbenchPart part = partReference.getPart(true);
314         if (part != null) {
315             Control control = getControl();
316             if (!SwtUtil.isFocusAncestor(control)) {
317                 // First try to call part.setFocus
318
part.setFocus();
319             }
320         }
321     }
322
323     /**
324      * Sets the workbench page of the view.
325      */

326     public void setWorkbenchPage(WorkbenchPage workbenchPage) {
327         this.page = workbenchPage;
328     }
329
330     /**
331      * Set whether the pane is zoomed or not
332      */

333     public void setZoomed(boolean isZoomed) {
334         if (this.isZoomed == isZoomed) {
335             return; // do nothing if we're already in the right state.
336
}
337
338         super.setZoomed(isZoomed);
339
340         this.isZoomed = isZoomed;
341
342         ((WorkbenchPartReference) partReference).fireZoomChange();
343     }
344     
345     /**
346      * Informs the pane that it's window shell has
347      * been activated.
348      */

349     /* package */abstract void shellActivated();
350
351     /**
352      * Informs the pane that it's window shell has
353      * been deactivated.
354      */

355     /* package */abstract void shellDeactivated();
356
357     /**
358      * Indicate focus in part.
359      */

360     public abstract void showFocus(boolean inFocus);
361
362     /**
363      * @see IPartDropTarget::targetPartFor
364      */

365     public LayoutPart targetPartFor(LayoutPart dragSource) {
366         return this;
367     }
368
369     /**
370      * Returns the PartStack that contains this PartPane, or null if none.
371      *
372      * @return
373      */

374     public PartStack getStack() {
375         ILayoutContainer container = getContainer();
376         if (container instanceof PartStack) {
377             return (PartStack) container;
378         }
379
380         return null;
381     }
382
383     /**
384      * Show a title label menu for this pane.
385      */

386     public void showPaneMenu() {
387         PartStack folder = getStack();
388
389         if (folder != null) {
390             folder.showPaneMenu();
391         }
392     }
393
394     /**
395      * Show the context menu for this part.
396      */

397     public void showSystemMenu() {
398         PartStack folder = getStack();
399
400         if (folder != null) {
401             folder.showSystemMenu();
402         }
403     }
404
405     /**
406      * Finds and return the sashes around this part.
407      */

408     protected Sashes findSashes() {
409         Sashes result = new Sashes();
410
411         ILayoutContainer container = getContainer();
412
413         if (container == null) {
414             return result;
415         }
416
417         container.findSashes(this, result);
418         return result;
419     }
420
421     /**
422      * Enable the user to resize this part using
423      * the keyboard to move the specified sash
424      */

425     protected void moveSash(final Sash sash) {
426         moveSash(sash, this);
427     }
428
429     public static void moveSash(final Sash sash,
430             final LayoutPart toGetFocusWhenDone) {
431         final KeyListener listener = new KeyAdapter() {
432             public void keyPressed(KeyEvent e) {
433                 if (e.character == SWT.ESC || e.character == '\r') {
434                     if (toGetFocusWhenDone != null) {
435                         toGetFocusWhenDone.setFocus();
436                     }
437                 }
438             }
439         };
440         sash.addFocusListener(new FocusAdapter() {
441             public void focusGained(FocusEvent e) {
442                 sash.setBackground(sash.getDisplay().getSystemColor(
443                         SWT.COLOR_LIST_SELECTION));
444                 sash.addKeyListener(listener);
445             }
446
447             public void focusLost(FocusEvent e) {
448                 sash.setBackground(null);
449                 sash.removeKeyListener(listener);
450             }
451         });
452         sash.setFocus();
453
454     }
455
456     /**
457      * Add a menu item to the Size Menu
458      */

459     protected void addSizeItem(Menu sizeMenu, String JavaDoc labelMessage,
460             final Sash sash) {
461         MenuItem item = new MenuItem(sizeMenu, SWT.NONE);
462         item.setText(labelMessage);
463         item.addSelectionListener(new SelectionAdapter() {
464             public void widgetSelected(SelectionEvent e) {
465                 moveSash(sash);
466             }
467         });
468         item.setEnabled(!isZoomed() && sash != null);
469     }
470
471     /**
472      * Returns the workbench page of this pane.
473      */

474     public WorkbenchPage getPage() {
475         return page;
476     }
477
478     /**
479      * Add the Left,Right,Up,Botton menu items to the Size menu.
480      */

481     protected void addSizeItems(Menu sizeMenu) {
482         Sashes sashes = findSashes();
483         addSizeItem(sizeMenu,
484                 WorkbenchMessages.PartPane_sizeLeft, sashes.left);
485         addSizeItem(sizeMenu,
486                 WorkbenchMessages.PartPane_sizeRight, sashes.right);
487         addSizeItem(sizeMenu,
488                 WorkbenchMessages.PartPane_sizeTop, sashes.top);
489         addSizeItem(sizeMenu, WorkbenchMessages.PartPane_sizeBottom, sashes.bottom);
490     }
491
492     /**
493      * Pin this part.
494      */

495     protected void doDock() {
496         // do nothing
497
}
498
499     /**
500      * Set the busy state of the pane.
501      */

502     public void setBusy(boolean isBusy) {
503         if (isBusy != busy) {
504             busy = isBusy;
505             firePropertyChange(IPresentablePart.PROP_BUSY);
506         }
507     }
508
509     /**
510      * Show a highlight for the receiver if it is
511      * not currently the part in the front of its
512      * presentation.
513      *
514      */

515     public void showHighlight() {
516         //No nothing by default
517
}
518
519     /**
520      * @return
521      */

522     public abstract Control getToolBar();
523
524     /**
525      * @return
526      */

527     public boolean hasViewMenu() {
528         return false;
529     }
530
531     /**
532      * @param location
533      */

534     public void showViewMenu(Point location) {
535
536     }
537     
538     public boolean isBusy() {
539         return busy;
540     }
541
542     /**
543      * Writes a description of the layout to the given string buffer.
544      * This is used for drag-drop test suites to determine if two layouts are the
545      * same. Like a hash code, the description should compare as equal iff the
546      * layouts are the same. However, it should be user-readable in order to
547      * help debug failed tests. Although these are english readable strings,
548      * they do not need to be translated.
549      *
550      * @param buf
551      */

552     public void describeLayout(StringBuffer JavaDoc buf) {
553
554         IWorkbenchPartReference part = getPartReference();
555
556         if (part != null) {
557             buf.append(part.getPartName());
558             return;
559         }
560     }
561     
562     /**
563      * @return
564      * @since 3.1
565      */

566     public abstract boolean isCloseable();
567     
568     public void setInLayout(boolean inLayout) {
569         this.inLayout = inLayout;
570     }
571     
572     public boolean getInLayout() {
573         return inLayout;
574     }
575         
576     public boolean allowsAutoFocus() {
577         if (!inLayout) {
578             return false;
579         }
580         
581         return super.allowsAutoFocus();
582     }
583
584     /**
585      * Clears all contribution items from the contribution managers (this is done separately
586      * from dispose() since it is done after the part is disposed). This is a bit of a hack.
587      * Really, the contribution managers should be part of the site, not the PartPane. If these
588      * were moved elsewhere, then disposal of the PartPane would be atomic and this method could
589      * be removed.
590      */

591     public void removeContributions() {
592
593     }
594
595     public void addPropertyListener(IPropertyListener listener) {
596         listeners.add(listener);
597     }
598
599     public void removePropertyListener(IPropertyListener listener) {
600         listeners.remove(listener);
601     }
602  
603     public void firePropertyChange(int propertyId) {
604         Object JavaDoc listeners[] = this.listeners.getListeners();
605         for (int i = 0; i < listeners.length; i++) {
606             ((IPropertyListener) listeners[i]).propertyChanged(this, propertyId);
607         }
608     }
609     
610     public void propertyChanged(Object JavaDoc source, int propId) {
611         firePropertyChange(propId);
612     }
613     
614     public void addPartPropertyListener(IPropertyChangeListener listener) {
615         partListeners.add(listener);
616     }
617     
618     public void removePartPropertyListener(IPropertyChangeListener listener) {
619         partListeners.remove(listener);
620     }
621     
622     public void firePartPropertyChange(PropertyChangeEvent event) {
623         Object JavaDoc[] l = partListeners.getListeners();
624         for (int i = 0; i < l.length; i++) {
625             ((IPropertyChangeListener)l[i]).propertyChange(event);
626         }
627     }
628     
629     /* (non-Javadoc)
630      * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
631      */

632     public void propertyChange(PropertyChangeEvent event) {
633         firePartPropertyChange(event);
634     }
635 }
636
Popular Tags