KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > layout > TrimCommonUIHandle


1 /*******************************************************************************
2  * Copyright (c) 2005, 2006 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.layout;
12
13 import org.eclipse.jface.action.ContributionItem;
14 import org.eclipse.jface.action.MenuManager;
15 import org.eclipse.swt.SWT;
16 import org.eclipse.swt.events.ControlEvent;
17 import org.eclipse.swt.events.ControlListener;
18 import org.eclipse.swt.events.SelectionEvent;
19 import org.eclipse.swt.events.SelectionListener;
20 import org.eclipse.swt.graphics.Cursor;
21 import org.eclipse.swt.graphics.Point;
22 import org.eclipse.swt.graphics.Rectangle;
23 import org.eclipse.swt.widgets.Composite;
24 import org.eclipse.swt.widgets.Control;
25 import org.eclipse.swt.widgets.CoolBar;
26 import org.eclipse.swt.widgets.CoolItem;
27 import org.eclipse.swt.widgets.Event;
28 import org.eclipse.swt.widgets.Label;
29 import org.eclipse.swt.widgets.Listener;
30 import org.eclipse.swt.widgets.Menu;
31 import org.eclipse.swt.widgets.MenuItem;
32 import org.eclipse.ui.internal.IChangeListener;
33 import org.eclipse.ui.internal.IntModel;
34 import org.eclipse.ui.internal.RadioMenu;
35 import org.eclipse.ui.internal.WindowTrimProxy;
36 import org.eclipse.ui.internal.WorkbenchMessages;
37 import org.eclipse.ui.internal.dnd.DragUtil;
38 import org.eclipse.ui.presentations.PresentationUtil;
39
40 /**
41  * This control provides common UI functionality for trim elements. Its
42  * lifecycle is managed by the <code>TrimLayout</code> which automatically
43  * adds a UI handle to all added trim elements. It uses an instance of a
44  * CoolBar to provide the platform-specific drag affordance.
45  * <p>
46  * It provides the following features:
47  * <p>
48  * Drag affordance and handling:
49  * <ol>
50  * <li>Drag affordance is provided in the <code>paintControl</code> method</li>
51  * <li>Drag handling is provided to allow rearrangement within a trim side or
52  * to other sides, depending on the values returned by <code>IWindowTrim.getValidSides</code></li>
53  * </ol>
54  * </p>
55  * <p>
56  * Context Menu:
57  * <ol>
58  * <li>A "Dock on" menu item is provided to allow changing the side, depending on the values returned by
59  * <code>IWindowTrim.getValidSides</code></li>
60  * <li>A "Close" menu item is provided to allow the User to close (hide) the trim element,
61  * based on the value returned by <code>IWindowTrim.isCloseable</code>
62  * </ol>
63  * </p>
64  * <p>
65  * @since 3.2
66  * </p>
67  */

68 public class TrimCommonUIHandle extends Composite {
69     /*
70      * Fields
71      */

72     private TrimLayout layout;
73     private IWindowTrim trim;
74     private Control toDrag;
75     private int orientation;
76
77     // CoolBar handling
78
private CoolBar cb = null;
79     private CoolItem ci = null;
80     private static int horizontalHandleSize = -1;
81     private static int verticalHandleSize = -1;
82     
83     /*
84      * Context Menu
85      */

86     private MenuManager dockMenuManager;
87     private ContributionItem dockContributionItem = null;
88     private Menu sidesMenu;
89     private MenuItem dockCascade;
90     private RadioMenu radioButtons;
91     private IntModel radioVal = new IntModel(0);
92 // private Menu showMenu;
93
// private MenuItem showCascade;
94

95     /*
96      * Listeners...
97      */

98     
99     /**
100      * This listener starts a drag operation when
101      * the Drag and Drop manager tells it to
102      */

103     private Listener dragListener = new Listener() {
104         public void handleEvent(Event event) {
105             // Only allow 'left mouse' drags...
106
if (event.button != 3) {
107                 Point position = DragUtil.getEventLoc(event);
108                 startDraggingTrim(position);
109             }
110         }
111     };
112
113     /**
114      * This listener brings up the context menu
115      */

116     private Listener menuListener = new Listener() {
117         public void handleEvent(Event event) {
118             Point loc = new Point(event.x, event.y);
119             if (event.type == SWT.MenuDetect) {
120                 showDockTrimPopup(loc);
121             }
122         }
123     };
124
125     /**
126      * Listen to size changes in the control so we can adjust the
127      * Coolbar and CoolItem to match.
128      */

129     private ControlListener controlListener = new ControlListener() {
130         public void controlMoved(ControlEvent e) {
131         }
132
133         public void controlResized(ControlEvent e) {
134             if (e.widget instanceof TrimCommonUIHandle) {
135                 TrimCommonUIHandle ctrl = (TrimCommonUIHandle) e.widget;
136                 Point size = ctrl.getSize();
137
138                 // Set the CoolBar and item to match the handle's size
139
cb.setSize(size);
140                 ci.setSize(size);
141                 ci.setPreferredSize(size);
142                 cb.layout(true);
143             }
144         }
145     };
146
147     /**
148      * Create a new trim UI handle for a particular IWindowTrim item
149      *
150      * @param layout the TrimLayout we're being used in
151      * @param trim the IWindowTrim we're acting on behalf of
152      * @param curSide the SWT side that the trim is currently on
153      */

154     public TrimCommonUIHandle(TrimLayout layout, IWindowTrim trim, int curSide) {
155         super(trim.getControl().getParent(), SWT.NONE);
156         
157         // Set the control up with all its various hooks, cursor...
158
setup(layout, trim, curSide);
159         
160         // Listen to size changes to keep the CoolBar synched
161
addControlListener(controlListener);
162     }
163
164     /**
165      * Set up the trim with its cursor, drag listener, context menu and menu listener.
166      * This method can also be used to 'recycle' a trim handle as long as the new handle
167      * is for trim under the same parent as it was originally used for.
168      */

169     public void setup(TrimLayout layout, IWindowTrim trim, int curSide) {
170         this.layout = layout;
171         this.trim = trim;
172         this.toDrag = trim.getControl();
173         this.radioVal.set(curSide);
174         
175         // remember the orientation to use
176
orientation = (curSide == SWT.LEFT || curSide == SWT.RIGHT) ? SWT.VERTICAL : SWT.HORIZONTAL;
177         
178         // Insert a CoolBar and extras in order to provide the drag affordance
179
insertCoolBar(orientation);
180         
181         // Create a window trim proxy for the handle
182
createWindowTrimProxy();
183         
184         // Set the cursor affordance
185
setDragCursor();
186         
187         // Set up the dragging behaviour
188
PresentationUtil.addDragListener(cb, dragListener);
189         
190         // Create the docking context menu
191
dockMenuManager = new MenuManager();
192         dockContributionItem = getDockingContribution();
193         dockMenuManager.add(dockContributionItem);
194
195         cb.addListener(SWT.MenuDetect, menuListener);
196         
197         setVisible(true);
198     }
199
200     /**
201      * Handle the event generated when a User selects a new side to
202      * dock this trim on using the context menu
203      */

204     private void handleShowOnChange() {
205         layout.removeTrim(trim);
206         trim.dock(radioVal.get());
207         layout.addTrim(radioVal.get(), trim, null);
208         
209         // perform an optimized layout to show the trim in its new location
210
LayoutUtil.resize(trim.getControl());
211     }
212
213     /**
214      * Create and format the IWindowTrim for the handle, ensuring that the
215      * handle will be 'wide' enough to display the drag affordance.
216      */

217     private void createWindowTrimProxy() {
218         // Create a window trim proxy for the handle
219
WindowTrimProxy proxy = new WindowTrimProxy(this, "NONE", "NONE", //$NON-NLS-1$ //$NON-NLS-2$
220
SWT.TOP | SWT.BOTTOM | SWT.LEFT | SWT.RIGHT, false);
221
222         // Set up the handle's hints based on the computed size that
223
// the handle has to be (i.e. if it's HORIZONTAL then the
224
// 'width' is determined by the space required to show the
225
// CB's drag affordance).
226
if (orientation == SWT.HORIZONTAL) {
227             proxy.setWidthHint(getHandleSize());
228             proxy.setHeightHint(0);
229         }
230         else {
231             proxy.setWidthHint(0);
232             proxy.setHeightHint(getHandleSize());
233         }
234         
235         setLayoutData(proxy);
236     }
237     
238     /**
239      * Calculate a size for the handle that will be large enough to show
240      * the CoolBar's drag affordance.
241      *
242      * @return The size that the handle has to be, based on the orientation
243      */

244     private int getHandleSize() {
245         // Do we already have a 'cached' value?
246
if (orientation == SWT.HORIZONTAL && horizontalHandleSize != -1) {
247             return horizontalHandleSize;
248         }
249                 
250         if (orientation == SWT.VERTICAL && verticalHandleSize != -1) {
251             return verticalHandleSize;
252         }
253                 
254         // Must be the first time, calculate the value
255
CoolBar bar = new CoolBar (trim.getControl().getParent(), orientation);
256         
257         CoolItem item = new CoolItem (bar, SWT.NONE);
258         
259         Label ctrl = new Label (bar, SWT.PUSH);
260         ctrl.setText ("Button 1"); //$NON-NLS-1$
261
Point size = ctrl.computeSize (SWT.DEFAULT, SWT.DEFAULT);
262         
263         Point ps = item.computeSize (size.x, size.y);
264         item.setPreferredSize (ps);
265         item.setControl (ctrl);
266
267         bar.pack ();
268
269         // OK, now the difference between the location of the CB and the
270
// location of the
271
Point bl = ctrl.getLocation();
272         Point cl = bar.getLocation();
273
274         // Toss them now...
275
ctrl.dispose();
276         item.dispose();
277         bar.dispose();
278     
279         // The 'size' is the difference between the start of teh CoolBar and
280
// start of its first control
281
int length;
282         if (orientation == SWT.HORIZONTAL) {
283             length = bl.x - cl.x;
284             horizontalHandleSize = length;
285         }
286         else {
287             length = bl.y - cl.y;
288             verticalHandleSize = length;
289         }
290         
291         return length;
292     }
293     
294     /**
295      * Place a CoolBar / CoolItem / Control inside the current
296      * UI handle. These elements will maintain thier size based on
297      * the size of their 'parent' (this).
298      *
299      * @param parent
300      * @param orientation
301      */

302     public void insertCoolBar(int orientation) {
303         // Clean up the previous info in case we've changed orientation
304
if (cb != null) {
305             ci.dispose();
306             PresentationUtil.removeDragListener(cb, dragListener);
307             cb.dispose();
308         }
309         
310         // Create the necessary parts...
311
cb = new CoolBar(this, orientation | SWT.FLAT);
312         cb.setLocation(0,0);
313         ci = new CoolItem(cb, SWT.FLAT);
314         
315         // Create a composite in order to get the handles to appear
316
Composite comp = new Composite(cb, SWT.NONE);
317         ci.setControl(comp);
318     }
319     
320     /**
321      * Set the cursor to the four-way arrow to indicate that the
322      * trim can be dragged
323      */

324     private void setDragCursor() {
325         Cursor dragCursor = toDrag.getDisplay().getSystemCursor(SWT.CURSOR_SIZEALL);
326         setCursor(dragCursor);
327     }
328     
329     /* (non-Javadoc)
330      * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
331      */

332     public Point computeSize(int wHint, int hHint, boolean changed) {
333         Point ctrlPrefSize = trim.getControl().computeSize(wHint, hHint);
334         if (orientation == SWT.HORIZONTAL) {
335             return new Point(getHandleSize(), ctrlPrefSize.y);
336         }
337         
338         // Must be vertical....
339
return new Point(ctrlPrefSize.x, getHandleSize());
340     }
341     
342     /**
343      * Construct (if necessary) a context menu contribution item and return it. This
344      * is explicitly <code>public</code> so that trim elements can retrieve the item
345      * and add it into their own context menus if desired.
346      *
347      * @return The contribution item for the handle's context menu.
348      */

349     public ContributionItem getDockingContribution() {
350         if (dockContributionItem == null) {
351             dockContributionItem = new ContributionItem() {
352                 public void fill(Menu menu, int index) {
353                     // populate from superclass
354
super.fill(menu, index);
355                     
356                     // Add a 'Close' menu entry if the trim supports the operation
357
if (trim.isCloseable()) {
358                         MenuItem closeItem = new MenuItem(menu, SWT.PUSH, index++);
359                         closeItem.setText(WorkbenchMessages.TrimCommon_Close);
360                         
361                         closeItem.addSelectionListener(new SelectionListener() {
362                             public void widgetSelected(SelectionEvent e) {
363                                 handleCloseTrim();
364                             }
365
366                             public void widgetDefaultSelected(SelectionEvent e) {
367                             }
368                         });
369
370                         new MenuItem(menu, SWT.SEPARATOR, index++);
371                     }
372                     
373                     // Test Hook: add a menu entry that brings up a dialog to allow
374
// testing with various GUI prefs.
375
// MenuItem closeItem = new MenuItem(menu, SWT.PUSH, index++);
376
// closeItem.setText("Change Preferences"); //$NON-NLS-1$
377
//
378
// closeItem.addSelectionListener(new SelectionListener() {
379
// public void widgetSelected(SelectionEvent e) {
380
// handleChangePreferences();
381
// }
382
//
383
// public void widgetDefaultSelected(SelectionEvent e) {
384
// }
385
// });
386
//
387
// new MenuItem(menu, SWT.SEPARATOR, index++);
388

389                     // Create a cascading menu to allow the user to dock the trim
390
dockCascade = new MenuItem(menu, SWT.CASCADE, index++);
391                     {
392                         dockCascade.setText(WorkbenchMessages.TrimCommon_DockOn);
393                         
394                         sidesMenu = new Menu(dockCascade);
395                         radioButtons = new RadioMenu(sidesMenu, radioVal);
396                         
397                         radioButtons.addMenuItem(WorkbenchMessages.TrimCommon_Top, new Integer JavaDoc(SWT.TOP));
398                         radioButtons.addMenuItem(WorkbenchMessages.TrimCommon_Bottom, new Integer JavaDoc(SWT.BOTTOM));
399                         radioButtons.addMenuItem(WorkbenchMessages.TrimCommon_Left, new Integer JavaDoc(SWT.LEFT));
400                         radioButtons.addMenuItem(WorkbenchMessages.TrimCommon_Right, new Integer JavaDoc(SWT.RIGHT));
401                         
402                         dockCascade.setMenu(sidesMenu);
403                     }
404
405                     // if the radioVal changes it means that the User wants to change the docking location
406
radioVal.addChangeListener(new IChangeListener() {
407                         public void update(boolean changed) {
408                             if (changed) {
409                                 handleShowOnChange();
410                             }
411                         }
412                     });
413                     
414                     // Provide Show / Hide trim capabilities
415
// showCascade = new MenuItem(menu, SWT.CASCADE, index++);
416
// {
417
// showCascade.setText(WorkbenchMessages.TrimCommon_ShowTrim);
418
//
419
// showMenu = new Menu(dockCascade);
420
//
421
// // Construct a 'hide/show' cascade from -all- the existing trim...
422
// List trimItems = layout.getAllTrim();
423
// Iterator d = trimItems.iterator();
424
// while (d.hasNext()) {
425
// IWindowTrim trimItem = (IWindowTrim) d.next();
426
// MenuItem item = new MenuItem(showMenu, SWT.CHECK);
427
// item.setText(trimItem.getDisplayName());
428
// item.setSelection(trimItem.getControl().getVisible());
429
// item.setData(trimItem);
430
//
431
// // TODO: Make this work...wire it off for now
432
// item.setEnabled(false);
433
//
434
// item.addSelectionListener(new SelectionListener() {
435
//
436
// public void widgetSelected(SelectionEvent e) {
437
// IWindowTrim trim = (IWindowTrim) e.widget.getData();
438
// layout.setTrimVisible(trim, !trim.getControl().getVisible());
439
// }
440
//
441
// public void widgetDefaultSelected(SelectionEvent e) {
442
// }
443
//
444
// });
445
// }
446
//
447
// showCascade.setMenu(showMenu);
448
// }
449
}
450             };
451         }
452         return dockContributionItem;
453     }
454
455     /**
456      * Test Hook: Bring up a dialog that allows the user to
457      * modify the trimdragging GUI preferences.
458      */

459 // private void handleChangePreferences() {
460
// TrimDragPreferenceDialog dlg = new TrimDragPreferenceDialog(getShell());
461
// dlg.open();
462
// }
463

464     /**
465      * Handle the event generated when the "Close" item is
466      * selected on the context menu. This removes the associated
467      * trim and calls back to the IWidnowTrim to inform it that
468      * the User has closed the trim.
469      */

470     private void handleCloseTrim() {
471         layout.removeTrim(trim);
472         trim.handleClose();
473     }
474     
475     /* (non-Javadoc)
476      * @see org.eclipse.swt.widgets.Widget#dispose()
477      */

478     public void dispose() {
479         if (radioButtons != null) {
480             radioButtons.dispose();
481         }
482
483         // tidy up...
484
removeControlListener(controlListener);
485         removeListener(SWT.MenuDetect, menuListener);
486         
487         super.dispose();
488     }
489
490     /**
491      * Begins dragging the trim
492      *
493      * @param position initial mouse position
494      */

495     protected void startDraggingTrim(Point position) {
496         Rectangle fakeBounds = new Rectangle(100000, 0,0,0);
497         DragUtil.performDrag(trim, fakeBounds, position, true);
498     }
499
500     /**
501      * Shows the popup menu for an item in the fast view bar.
502      */

503     private void showDockTrimPopup(Point pt) {
504         Menu menu = dockMenuManager.createContextMenu(toDrag);
505         menu.setLocation(pt.x, pt.y);
506         menu.setVisible(true);
507     }
508 }
509
Popular Tags