Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/eclipse/ui/internal/PartPane.java


1   /*******************************************************************************
2    * Copyright (c) 2000, 2004 IBM Corporation and others.
3    * All rights reserved. This program and the accompanying materials 
4    * are made available under the terms of the Common Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/cpl-v10.html
7    * 
8    * Contributors:
9    *     IBM Corporation - initial API and implementation
10   *******************************************************************************/
11  package org.eclipse.ui.internal;
12  
13  
14  import org.eclipse.core.runtime.Platform;
15  import org.eclipse.jface.action.MenuManager;
16  import org.eclipse.jface.util.IPropertyChangeListener;
17  import org.eclipse.jface.util.PropertyChangeEvent;
18  import org.eclipse.jface.util.SafeRunnable;
19  import org.eclipse.swt.SWT;
20  import org.eclipse.swt.events.FocusAdapter;
21  import org.eclipse.swt.events.FocusEvent;
22  import org.eclipse.swt.events.KeyAdapter;
23  import org.eclipse.swt.events.KeyEvent;
24  import org.eclipse.swt.events.KeyListener;
25  import org.eclipse.swt.events.SelectionAdapter;
26  import org.eclipse.swt.events.SelectionEvent;
27  import org.eclipse.swt.events.TraverseEvent;
28  import org.eclipse.swt.events.TraverseListener;
29  import org.eclipse.swt.graphics.Point;
30  import org.eclipse.swt.graphics.Rectangle;
31  import org.eclipse.swt.layout.FillLayout;
32  import org.eclipse.swt.widgets.Composite;
33  import org.eclipse.swt.widgets.Control;
34  import org.eclipse.swt.widgets.Event;
35  import org.eclipse.swt.widgets.Listener;
36  import org.eclipse.swt.widgets.Menu;
37  import org.eclipse.swt.widgets.MenuItem;
38  import org.eclipse.swt.widgets.Sash;
39  import org.eclipse.ui.IWorkbenchPart;
40  import org.eclipse.ui.IWorkbenchPartReference;
41  import org.eclipse.ui.IWorkbenchWindow;
42  import org.eclipse.ui.PlatformUI;
43  import org.eclipse.ui.internal.misc.UIStats;
44  import org.eclipse.ui.internal.presentations.PresentablePart;
45  import org.eclipse.ui.presentations.IPresentablePart;
46  
47  /**
48   * Provides the common behavior for both views
49   * and editor panes.
50   * 
51   * TODO: Delete ViewPane and EditorPane, and make this class non-abstract.
52   * 
53   * TODO: Stop subclassing LayoutPart. This class cannot be interchanged with other LayoutParts.
54   * Pointers that refer to PartPane instances should do so directly rather than referring to
55   * LayoutPart and downcasting. The getPresentablePart() method only applies to PartPanes, and
56   * should be removed from LayoutPart.
57   */
58  public abstract class PartPane extends LayoutPart
59    implements Listener
60  {
61  
62    protected PresentablePart presentableAdapter = new PresentablePart(this);
63    public static final String PROP_ZOOMED = "zoomed"; //$NON-NLS-1$
64    private boolean isZoomed = false;
65    private MenuManager paneMenuManager;
66    protected IWorkbenchPartReference partReference;
67    protected WorkbenchPage page;
68    protected Composite control;
69    
70    private TraverseListener traverseListener = new TraverseListener() {  
71      /* (non-Javadoc)
72       * @see org.eclipse.swt.events.TraverseListener#keyTraversed(org.eclipse.swt.events.TraverseEvent)
73       */
74      public void keyTraversed(TraverseEvent e) {
75        // Hack: Currently, SWT sets focus whenever we call Control.traverse. This doesn't
76        // cause too much of a problem for ctrl-pgup and ctrl-pgdn, but it is seriously unexpected
77        // for other traversal events. When (and if) it becomes possible to call traverse() without
78        // forcing a focus change, this if statement should be removed and ALL events should be
79        // forwarded to the container.
80        if (e.detail == SWT.TRAVERSE_PAGE_NEXT || e.detail == SWT.TRAVERSE_PAGE_PREVIOUS) {
81          ILayoutContainer container = getContainer();
82          if (container != null && container instanceof LayoutPart) {
83            LayoutPart parent = (LayoutPart)container;
84            Control parentControl = parent.getControl();
85            if (parentControl != null && !parentControl.isDisposed()) {
86              parentControl.traverse(e.detail);
87              e.doit = false;        
88            }
89          }  
90        }      
91      }
92      
93    };
94  
95    
96    public static class Sashes {
97      public Sash left;
98      public Sash right;
99      public Sash top;
100     public Sash bottom;
101   }
102   
103 /**
104  * Construct a pane for a part.
105  */
106 public PartPane(IWorkbenchPartReference partReference, WorkbenchPage workbenchPage) {
107   super(partReference.getId());
108   this.partReference = partReference;
109   this.page = workbenchPage;
110   ((WorkbenchPartReference)partReference).setPane(this);
111 }
112 /**
113  * Factory method for creating the SWT Control hierarchy for this Pane's child.
114  */
115 protected void createChildControl() {
116   final IWorkbenchPart part[] = new IWorkbenchPart[]{partReference.getPart(false)};
117   if(part[0] == null)
118     return;
119 
120   // must call createControl(..) first.
121   // TODO: should only really call this method from createControl()
122   if(control == null)
123     return;
124   
125   // Make sure the child control has not been created yet
126   if(control.getChildren().length != 0)
127     return;
128   
129   final Composite content = new Composite(control, SWT.NONE);
130   content.setLayout(new FillLayout());
131   
132   String error = WorkbenchMessages.format("PartPane.unableToCreate", new Object[] {partReference.getTitle()}); //$NON-NLS-1$
133   Platform.run(new SafeRunnable(error) {
134     public void run() {
135       try {
136         UIStats.start(UIStats.CREATE_PART_CONTROL,id);
137         part[0].createPartControl(content);
138         
139         Rectangle oldBounds = control.getBounds();
140         
141         ((WorkbenchPartReference)getPartReference()).refreshFromPart();
142         
143         // Unless refreshing the part has somehow triggered a layout, 
144         // we need to force a layout now. (SWT only triggers a layout if the
145         // bounds change, so check that case here).
146         if (oldBounds.equals(control.getBounds())) {
147           control.layout(true);
148         }
149       } finally {
150         UIStats.end(UIStats.CREATE_PART_CONTROL,id);
151       }
152     }
153     public void handleException(Throwable e) {
154       // Log error.
155       Workbench wb = (Workbench)PlatformUI.getWorkbench();
156       if (!wb.isStarting())
157         super.handleException(e);
158 
159       // Dispose old part.
160       Control children[] = content.getChildren();
161       for (int i = 0; i < children.length; i++){
162         children[i].dispose();
163       }
164       
165       // Create new part.
166       IWorkbenchPart newPart = createErrorPart(part[0]);
167       part[0].getSite().setSelectionProvider(null);
168       newPart.createPartControl(content);
169       ((WorkbenchPartReference)partReference).setPart(newPart);
170       part[0] = newPart;
171     }
172   });
173   page.addPart(partReference);
174   page.firePartOpened(part[0]);
175 }
176 
177 public void addSizeMenuItem (Menu menu, int index) {
178   //Add size menu
179   MenuItem item = new MenuItem(menu, SWT.CASCADE, index);
180   item.setText(WorkbenchMessages.getString("PartPane.size")); //$NON-NLS-1$
181   Menu sizeMenu = new Menu(menu);
182   item.setMenu(sizeMenu);
183   addSizeItems(sizeMenu);
184 }
185 
186 /**
187  * 
188  */
189 public void createControl(Composite parent) {
190   if (getControl() != null)
191     return;
192 
193   // Create view form.  
194   control = new Composite(parent, SWT.NONE);
195   control.setLayout(new FillLayout());
196   // the part should never be visible by default.  It will be made visible 
197   // by activation.  This allows us to have views appear in tabs without 
198   // becoming active by default.
199   control.setVisible(false);
200 
201   // Create a title bar.
202   createTitleBar();
203 
204   // Create content.
205   createChildControl();
206   
207   // When the pane or any child gains focus, notify the workbench.
208   control.addListener(SWT.Activate, this);
209   
210   control.addTraverseListener(traverseListener);
211 }
212 
213 protected abstract IWorkbenchPart createErrorPart(IWorkbenchPart oldPart);
214 /**
215  * Create a title bar for the pane if required.
216  */
217 protected abstract void createTitleBar();
218 /**
219  * @private
220  */
221 public void dispose() {
222   super.dispose();
223 
224   if ((control != null) && (!control.isDisposed())) {
225     control.removeListener(SWT.Activate, this);
226     control.removeTraverseListener(traverseListener);
227     control.dispose();
228     control = null;
229   }
230   if ((paneMenuManager != null)) {
231     paneMenuManager.dispose();  
232     paneMenuManager = null;
233   }
234 }
235 /**
236  * User has requested to close the pane.
237  * Take appropriate action depending on type.
238  */
239 abstract public void doHide();
240 
241 /**
242  * Zooms in on the part contained in this pane.
243  */
244 protected void doZoom() {
245   if (getWindow() instanceof IWorkbenchWindow)
246     page.toggleZoom(partReference);
247 }
248 /**
249  * Gets the presentation bounds.
250  */
251 public Rectangle getBounds() {
252   return getControl().getBounds();
253 }
254 /**
255  * Get the control.
256  */
257 public Control getControl() {
258   return control;
259 }
260 
261 /*
262  * @see LayoutPart#getMinimumHeight()
263  */
264 public int getMinimumHeight() {
265   if (control == null || control.isDisposed())
266     return super.getMinimumHeight();
267   
268   // account for the borders
269   return control.computeTrim(0, 0, 0, 0).height;
270 }
271 
272 /**
273  * Answer the part child.
274  */
275 public IWorkbenchPartReference getPartReference() {
276   return partReference;
277 }
278 
279 /**
280  * @see Listener
281  */
282 public void handleEvent(Event event) {
283   if (event.type == SWT.Activate)
284     requestActivation();
285 }
286 /**
287  * Return whether the pane is zoomed or not
288  */
289 public boolean isZoomed() {
290   return isZoomed;
291 }
292 /**
293  * Move the control over another one.
294  */
295 public void moveAbove(Control refControl) {
296   if (getControl() != null)
297     getControl().moveAbove(refControl);
298 }
299 /**
300  * Notify the workbook page that the part pane has
301  * been activated by the user.
302  */
303 protected void requestActivation() {
304   this.page.requestActivation(partReference.getPart(true));
305 }
306 /**
307  * Sets the parent for this part.
308  */
309 public void setContainer(ILayoutContainer container) {
310   super.setContainer(container);
311 }
312 
313 /**
314  * Shows the receiver if <code>visible</code> is true otherwise hide it.
315  */
316 public void setVisible(boolean makeVisible) {
317   super.setVisible(makeVisible);
318   if(makeVisible) //Make sure that the part is restored.
319     partReference.getPart(true);
320 }
321 /**
322  * Sets focus to this part.
323  */
324 public void setFocus() {
325   requestActivation();
326   IWorkbenchPart part = partReference.getPart(true);
327   if (part != null) {
328     part.setFocus();
329   }
330 }
331 /**
332  * Sets the workbench page of the view. 
333  */
334 public void setWorkbenchPage(WorkbenchPage workbenchPage) {
335   this.page = workbenchPage;
336 }
337 /**
338  * Set whether the pane is zoomed or not
339  */
340 public void setZoomed(boolean isZoomed) {
341   if (this.isZoomed == isZoomed)
342     return; // do nothing if we're already in the right state.
343   
344   super.setZoomed(isZoomed);
345   
346   this.isZoomed = isZoomed;
347   
348   final Object[] listeners = getPropertyListeners().getListeners();
349   if (listeners.length > 0) {
350     Boolean oldValue = isZoomed ? Boolean.FALSE : Boolean.TRUE;
351     Boolean zoomed = isZoomed ? Boolean.TRUE : Boolean.FALSE;
352     PropertyChangeEvent event = new PropertyChangeEvent(this, PROP_ZOOMED, oldValue, zoomed);
353     for (int i = 0; i < listeners.length; ++i)
354       ((IPropertyChangeListener)listeners[i]).propertyChange(event);
355   }
356 }
357 /**
358  * Informs the pane that it's window shell has
359  * been activated.
360  */
361 /* package */ abstract void shellActivated();
362 /**
363  * Informs the pane that it's window shell has
364  * been deactivated.
365  */
366 /* package */ abstract void shellDeactivated();
367 /**
368  * Indicate focus in part.
369  */
370 public abstract void showFocus(boolean inFocus);
371 /**
372  * @see IPartDropTarget::targetPartFor
373  */
374 public LayoutPart targetPartFor(LayoutPart dragSource) {
375   return this;
376 }
377 
378 /**
379  * Returns the PartStack that contains this PartPane, or null if none.
380  * 
381  * @return
382  */
383 public PartStack getStack() {
384   ILayoutContainer container = getContainer();
385   if (container instanceof PartStack) {
386     return (PartStack) container;
387   }
388   
389   return null;
390 }
391 
392 /**
393  * Show a title label menu for this pane.
394  */
395 public void showPaneMenu() {
396   PartStack folder = getStack();
397   
398   if (folder != null) {
399     folder.showSystemMenu();
400   }
401 }
402 /**
403  * Show the context menu for this part.
404  */
405 public void showViewMenu() {
406   PartStack folder = getStack();
407   
408   if (folder != null) {
409     folder.showPaneMenu();
410   }
411 }
412 
413 /**
414  * Finds and return the sashes around this part.
415  */
416 protected Sashes findSashes() {
417   Sashes result = new Sashes();
418   
419   ILayoutContainer container = getContainer();
420   
421   if (container == null) {
422     return result;
423   } 
424   
425   container.findSashes(this, result);
426   return result;
427 }
428 
429 /**
430  * Enable the user to resize this part using
431  * the keyboard to move the specified sash
432  */
433 protected void moveSash(final Sash sash) {
434   moveSash(sash, this);
435 }
436 
437 public static void moveSash(final Sash sash, final LayoutPart toGetFocusWhenDone) {
438   final KeyListener listener = new KeyAdapter() {
439     public void keyPressed(KeyEvent e) {
440       if (e.character == SWT.ESC || e.character == '\r') {
441         if(toGetFocusWhenDone != null)
442           toGetFocusWhenDone.setFocus();
443       }
444     }
445   };
446   sash.addFocusListener(new FocusAdapter() {
447     public void focusGained(FocusEvent e) {
448       sash.setBackground(sash.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION));
449       sash.addKeyListener(listener);
450     }
451     public void focusLost(FocusEvent e) {
452       sash.setBackground(null);
453       sash.removeKeyListener(listener);
454     }
455   });
456   sash.setFocus();
457   
458 }
459 
460 /**
461  * Add a menu item to the Size Menu
462  */
463 protected void addSizeItem(Menu sizeMenu, String labelMessage, final Sash sash) {
464   MenuItem item = new MenuItem(sizeMenu, SWT.NONE);
465   item.setText(labelMessage); //$NON-NLS-1$
466   item.addSelectionListener(new SelectionAdapter() {
467     public void widgetSelected(SelectionEvent e) {
468       moveSash(sash);
469     }
470   });
471   item.setEnabled(!isZoomed() && sash != null);
472 }
473 /**
474  * Returns the workbench page of this pane.
475  */
476 public WorkbenchPage getPage() {
477   return page;
478 }
479 /**
480  * Add the Left,Right,Up,Botton menu items to the Size menu.
481  */
482 protected void addSizeItems(Menu sizeMenu) {
483     Sashes sashes = findSashes();
484     addSizeItem(sizeMenu,
485             WorkbenchMessages.getString("PartPane.sizeLeft"), sashes.left); //$NON-NLS-1$
486     addSizeItem(sizeMenu,
487             WorkbenchMessages.getString("PartPane.sizeRight"), sashes.right); //$NON-NLS-1$
488     addSizeItem(sizeMenu,
489             WorkbenchMessages.getString("PartPane.sizeTop"), sashes.top); //$NON-NLS-1$
490     addSizeItem(sizeMenu,
491             WorkbenchMessages.getString("PartPane.sizeBottom"), sashes.bottom); //$NON-NLS-1$
492 }
493 
494 
495 /**
496  * Pin this part.
497  */
498 protected void doDock() {
499   // do nothing
500 }
501 
502 /**
503  * Set the busy state of the pane.
504  */
505 public void setBusy(boolean isBusy) {
506   //Do nothing by default
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  * Ensure that we are not in the zoomed before reparenting.
521  * TODO: I am certain this isn't correct but I'll be damned if I know what is.
522  */
523 public void reparent(Composite newParent) {
524     if (isZoomed())
525         setZoomed(false);
526     super.reparent(newParent);
527 }
528 
529 /**
530  * @return
531  */
532 public abstract Control getToolBar();
533 
534 /**
535  * @return
536  */
537 public boolean hasViewMenu() {
538   return false;
539 }
540 
541 /**
542  * @param location
543  */
544 public void showViewMenu(Point location) {
545   
546 }
547 
548 public boolean isBusy() {
549   return false;
550 }
551 
552 /* (non-Javadoc)
553  * @see org.eclipse.ui.internal.LayoutPart#getPresentablePart()
554  */
555 public IPresentablePart getPresentablePart() {
556   return presentableAdapter;
557 }
558 
559 }