001: /***************************************************************************************************
002: * Copyright (c) 2005, 2006 IBM Corporation and others. All rights reserved. This program and the
003: * accompanying materials are made available under the terms of the Eclipse Public License v1.0
004: * which accompanies this distribution, and is available at
005: * http://www.eclipse.org/legal/epl-v10.html
006: *
007: * Contributors: IBM Corporation - initial API and implementation
008: **************************************************************************************************/package org.eclipse.ui.internal.intro.impl.presentations;
009:
010: import java.util.Map;
011:
012: import org.eclipse.jface.action.Action;
013: import org.eclipse.jface.action.IMenuListener;
014: import org.eclipse.jface.action.IMenuManager;
015: import org.eclipse.jface.action.IToolBarManager;
016: import org.eclipse.jface.action.MenuManager;
017: import org.eclipse.jface.action.Separator;
018: import org.eclipse.jface.action.ToolBarManager;
019: import org.eclipse.jface.dialogs.IDialogSettings;
020: import org.eclipse.jface.util.Geometry;
021: import org.eclipse.swt.SWT;
022: import org.eclipse.swt.events.PaintEvent;
023: import org.eclipse.swt.events.PaintListener;
024: import org.eclipse.swt.graphics.Color;
025: import org.eclipse.swt.graphics.GC;
026: import org.eclipse.swt.graphics.Point;
027: import org.eclipse.swt.graphics.RGB;
028: import org.eclipse.swt.graphics.Rectangle;
029: import org.eclipse.swt.widgets.Composite;
030: import org.eclipse.swt.widgets.Control;
031: import org.eclipse.swt.widgets.Display;
032: import org.eclipse.swt.widgets.Layout;
033: import org.eclipse.swt.widgets.Menu;
034: import org.eclipse.swt.widgets.ToolBar;
035: import org.eclipse.ui.IWorkbenchPreferenceConstants;
036: import org.eclipse.ui.IWorkbenchWindow;
037: import org.eclipse.ui.PlatformUI;
038: import org.eclipse.ui.internal.RectangleAnimation;
039: import org.eclipse.ui.internal.WorkbenchMessages;
040: import org.eclipse.ui.internal.WorkbenchWindow;
041: import org.eclipse.ui.internal.dnd.DragUtil;
042: import org.eclipse.ui.internal.intro.impl.IntroPlugin;
043: import org.eclipse.ui.internal.intro.impl.Messages;
044: import org.eclipse.ui.internal.intro.impl.model.IntroLaunchBarElement;
045: import org.eclipse.ui.internal.intro.impl.model.IntroLaunchBarShortcut;
046: import org.eclipse.ui.internal.intro.impl.model.IntroTheme;
047: import org.eclipse.ui.internal.intro.impl.swt.SharedStyleManager;
048: import org.eclipse.ui.internal.intro.impl.util.ImageUtil;
049: import org.eclipse.ui.internal.layout.ITrimManager;
050: import org.eclipse.ui.internal.layout.IWindowTrim;
051: import org.eclipse.ui.intro.IIntroPart;
052: import org.eclipse.ui.intro.config.CustomizableIntroPart;
053: import org.eclipse.ui.intro.config.IIntroURL;
054: import org.eclipse.ui.intro.config.IntroURLFactory;
055:
056: /**
057: * This class is responsible for creating the intro launch bar in the provided parent. It creates
058: * 'restore' and 'close' actions, as well as actions for each shortcut element contributed in the
059: * extension point.
060: *
061: * @since 3.1
062: */
063: public class IntroLaunchBar implements IWindowTrim {
064:
065: private Composite container;
066:
067: protected ToolBarManager toolBarManager;
068:
069: protected int orientation;
070:
071: protected int location;
072:
073: protected String lastPageId;
074:
075: protected Action closeAction = null;
076:
077: private IntroLaunchBarElement element;
078:
079: protected boolean simple;
080:
081: private String presentationId;
082:
083: private IntroTheme theme;
084:
085: static final int[] TOP_LEFT_CORNER = new int[] { 0, 6, 1, 5, 1, 4,
086: 4, 1, 5, 1, 6, 0 };
087:
088: static final int[] TOP_RIGHT_CORNER = new int[] { -6, 0, -5, 1, -4,
089: 1, -1, 4, -1, 5, 0, 6 };
090:
091: static final int[] BOTTOM_LEFT_CORNER = new int[] { 0, -6, 1, -5,
092: 1, -4, 4, -1, 5, -1, 6, 0 };
093:
094: static final int[] BOTTOM_RIGHT_CORNER = new int[] { -6, 0, -5, -1,
095: -4, -1, -1, -4, -1, -5, 0, -6 };
096:
097: static final int[] SIMPLE_TOP_LEFT_CORNER = new int[] { 0, 2, 1, 1,
098: 2, 0 };
099:
100: static final int[] SIMPLE_TOP_RIGHT_CORNER = new int[] { -2, 0, -1,
101: 1, 0, 2 };
102:
103: static final int[] SIMPLE_BOTTOM_LEFT_CORNER = new int[] { 0, -2,
104: 1, -1, 2, 0 };
105:
106: static final int[] SIMPLE_BOTTOM_RIGHT_CORNER = new int[] { -2, 0,
107: -1, -1, 0, -2 };
108:
109: static final String S_STORED_LOCATION = "introLaunchBar.location"; //$NON-NLS-1$
110:
111: private final static String LAUNCH_COMMAND_BASE = "http://org.eclipse.ui.intro/showPage?id="; //$NON-NLS-1$
112:
113: private Color fg;
114:
115: private Color bg;
116:
117: class BarLayout extends Layout {
118:
119: protected Point computeSize(Composite composite, int wHint,
120: int hHint, boolean changed) {
121: boolean vertical = (orientation & SWT.VERTICAL) != 0;
122: int marginWidth = vertical | isPlain() ? 1 : simple ? 3 : 7;
123: int marginHeight = !vertical | isPlain() ? 1 : simple ? 3
124: : 7;
125: int width = 0;
126: int height = 0;
127:
128: Point tsize = toolBarManager.getControl().computeSize(
129: SWT.DEFAULT, SWT.DEFAULT, changed);
130:
131: if (vertical) {
132: width = tsize.x;
133: height = tsize.y;
134: } else {
135: height = tsize.y;
136: width = tsize.x;
137: }
138: if (vertical) {
139: width += marginWidth;
140: height += marginHeight + marginHeight;
141: } else {
142: width += marginWidth + marginWidth;
143: height += marginHeight;
144: }
145: return new Point(width, height);
146: }
147:
148: protected void layout(Composite composite, boolean changed) {
149: boolean vertical = (orientation & SWT.VERTICAL) != 0;
150: int marginWidth = vertical | isPlain() ? 1 : simple ? 4 : 7;
151: int marginHeight = !vertical | isPlain() ? 1 : simple ? 4
152: : 7;
153:
154: Point tsize = toolBarManager.getControl().computeSize(
155: SWT.DEFAULT, SWT.DEFAULT, changed);
156: Rectangle carea = composite.getClientArea();
157: int x = carea.x + (location == SWT.LEFT ? 0 : marginWidth);
158: int y = carea.y + marginHeight;
159:
160: if (vertical) {
161: toolBarManager.getControl().setBounds(x, y,
162: carea.width - marginWidth, tsize.y);
163: } else {
164: toolBarManager.getControl().setBounds(x, y, tsize.x,
165: carea.height - marginHeight);
166: }
167: }
168: }
169:
170: public IntroLaunchBar(int orientation, String lastPageId,
171: IntroLaunchBarElement element, IntroTheme theme) {
172: this .orientation = orientation;
173: this .location = element.getLocation();
174: this .lastPageId = lastPageId;
175: this .element = element;
176: this .theme = theme;
177:
178: simple = true;
179: presentationId = PlatformUI.getPreferenceStore().getString(
180: IWorkbenchPreferenceConstants.PRESENTATION_FACTORY_ID);
181: loadStoredLocation();
182: }
183:
184: private void loadStoredLocation() {
185: IDialogSettings settings = IntroPlugin.getDefault()
186: .getDialogSettings();
187: try {
188: int storedLocation = settings.getInt(S_STORED_LOCATION);
189: if (storedLocation > 0)
190: setLocation(storedLocation);
191: } catch (NumberFormatException e) {
192: // The stored value either does not exist or
193: // is corrupted - just pick the default silently.
194: }
195: }
196:
197: private void storeLocation() {
198: IDialogSettings settings = IntroPlugin.getDefault()
199: .getDialogSettings();
200: settings.put(S_STORED_LOCATION, this .location);
201: }
202:
203: /**
204: * This method now calls dock(location) and then adds itself to the window trim. This is to
205: * support the re-ordering of IWindowTrim lifecycle related to dock().
206: */
207: public void createInActiveWindow() {
208: IWorkbenchWindow window = PlatformUI.getWorkbench()
209: .getActiveWorkbenchWindow();
210:
211: dock(location);
212:
213: ITrimManager trimManager = getTrimManager();
214: trimManager.addTrim(location, this );
215: window.getShell().layout();
216: }
217:
218: /**
219: * Get the trim manager from the default workbench window. If the current
220: * workbench window is -not- the <code>WorkbenchWindow</code> then return null.
221: *
222: * @return The trim manager for the current workbench window
223: */
224: private ITrimManager getTrimManager() {
225: IWorkbenchWindow window = PlatformUI.getWorkbench()
226: .getActiveWorkbenchWindow();
227: if (window instanceof WorkbenchWindow)
228: return ((WorkbenchWindow) window).getTrimManager();
229:
230: return null; // not using the default workbench window
231: }
232:
233: protected boolean isPlain() {
234: return !"org.eclipse.ui.presentations.default".equals(presentationId); //$NON-NLS-1$
235: }
236:
237: public void createControl(Composite parent) {
238: container = new Composite(parent, SWT.NULL);
239: computeColors(parent.getDisplay());
240: container.setLayout(new BarLayout());
241: // boolean vertical = (orientation & SWT.VERTICAL) != 0;
242: toolBarManager = new ToolBarManager(SWT.FLAT | orientation);
243:
244: fillToolBar();
245: // coolBar = new CoolBar(container, SWT.NULL);
246: // CoolItem coolItem = new CoolItem(coolBar, SWT.NULL);
247: // toolBarManager.createControl(coolBar);
248: toolBarManager.createControl(container);
249: ToolBar toolBar = toolBarManager.getControl();
250:
251: // coolItem.setControl(toolBar);
252: // Point toolBarSize = toolBar.computeSize(SWT.DEFAULT,
253: // SWT.DEFAULT);
254: // Set the preffered size to the size of the toolbar plus trim
255: // Point preferredSize = coolItem.computeSize(toolBarSize.x,
256: // toolBarSize.y);
257: // coolItem.setPreferredSize(preferredSize);
258:
259: if (bg != null) {
260: toolBar.setBackground(bg);
261: // coolBar.setBackground(bg);
262: }
263: container.addPaintListener(new PaintListener() {
264:
265: public void paintControl(PaintEvent e) {
266: onPaint(e);
267: }
268: });
269: MenuManager manager = new MenuManager();
270: IMenuListener listener = new IMenuListener() {
271:
272: public void menuAboutToShow(IMenuManager manager) {
273: contextMenuAboutToShow(manager);
274: }
275: };
276: manager.setRemoveAllWhenShown(true);
277: manager.addMenuListener(listener);
278: Menu contextMenu = manager.createContextMenu(toolBarManager
279: .getControl());
280: toolBarManager.getControl().setMenu(contextMenu);
281: IntroPlugin.getDefault().setLaunchBar(this );
282: }
283:
284: protected void startDragging(Point position, boolean usingKeyboard) {
285: Rectangle dragRect = DragUtil.getDisplayBounds(getControl());
286: startDrag(this , dragRect, position, usingKeyboard);
287: }
288:
289: private void startDrag(Object toDrag, Rectangle dragRect,
290: Point position, boolean usingKeyboard) {
291:
292: DragUtil
293: .performDrag(toDrag, dragRect, position, !usingKeyboard);
294: }
295:
296: protected void onPaint(PaintEvent e) {
297: GC gc = e.gc;
298: Color color = fg;
299: if (color == null) {
300: color = e.display
301: .getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
302: }
303: gc.setForeground(color);
304: if (bg != null)
305: gc.setBackground(bg);
306: if (isPlain()) {
307: Point size = container.getSize();
308: gc.fillRectangle(0, 0, size.x, size.y);
309: gc.drawRectangle(0, 0, size.x - 1, size.y - 1);
310: } else {
311: switch (location) {
312: case SWT.LEFT:
313: paintLeft(gc);
314: break;
315: case SWT.RIGHT:
316: paintRight(gc);
317: break;
318: case SWT.BOTTOM:
319: paintBottom(gc);
320: break;
321: }
322: }
323: }
324:
325: private void paintLeft(GC gc) {
326: int[] top = simple ? SIMPLE_TOP_RIGHT_CORNER : TOP_RIGHT_CORNER;
327: int[] bot = simple ? SIMPLE_BOTTOM_RIGHT_CORNER
328: : BOTTOM_RIGHT_CORNER;
329: int[] shape = new int[top.length + bot.length + 4];
330: int index = 0;
331: Point size = container.getSize();
332: int x = size.x - 1;
333: int y = 0;
334: index = fillShape(shape, top, index, x, y, false);
335: y = size.y - 1;
336: index = fillShape(shape, bot, index, x, y, true);
337: shape[index++] = -1;
338: shape[index++] = size.y - 1;
339: shape[index++] = -1;
340: shape[index++] = 0;
341: gc.fillPolygon(shape);
342: gc.drawPolygon(shape);
343: }
344:
345: private void paintBottom(GC gc) {
346: int[] left = simple ? SIMPLE_TOP_LEFT_CORNER : TOP_LEFT_CORNER;
347: int[] right = simple ? SIMPLE_TOP_RIGHT_CORNER
348: : TOP_RIGHT_CORNER;
349: int[] shape = new int[left.length + right.length + 4];
350: int index = 0;
351: Point size = container.getSize();
352: int x = 0;
353: int y = 0;
354: index = fillShape(shape, left, index, x, y, false);
355: x = size.x - 1;
356: index = fillShape(shape, right, index, x, y, false);
357: shape[index++] = size.x - 1;
358: shape[index++] = size.y;
359: shape[index++] = 0;
360: shape[index++] = size.y;
361: gc.fillPolygon(shape);
362: gc.drawPolygon(shape);
363: }
364:
365: private void paintRight(GC gc) {
366: int[] top = simple ? SIMPLE_TOP_LEFT_CORNER : TOP_LEFT_CORNER;
367: int[] bot = simple ? SIMPLE_BOTTOM_LEFT_CORNER
368: : BOTTOM_LEFT_CORNER;
369: int[] shape = new int[top.length + bot.length + 4];
370: int index = 0;
371: Point size = container.getSize();
372: int x = 0;
373: int y = 0;
374: index = fillShape(shape, top, index, x, y, false);
375: shape[index++] = size.x;
376: shape[index++] = 0;
377: shape[index++] = size.x;
378: shape[index++] = size.y - 1;
379: x = 0;
380: y = size.y - 1;
381: fillShape(shape, bot, index, x, y, true);
382: gc.fillPolygon(shape);
383: gc.drawPolygon(shape);
384: }
385:
386: private int fillShape(int[] shape, int[] points, int index, int x,
387: int y, boolean reverse) {
388: int fill = points.length;
389: for (int i = 0; i < points.length / 2; i++) {
390: if (!reverse) {
391: shape[index++] = x + points[2 * i];
392: shape[index++] = y + points[2 * i + 1];
393: } else {
394: shape[index + fill - 2 - 2 * i] = x + points[2 * i];
395: shape[index + fill - 1 - 2 * i] = y + points[2 * i + 1];
396: }
397: }
398: if (reverse) {
399: index += fill;
400: }
401: return index;
402: }
403:
404: private void computeColors(Display display) {
405: if (element.getBackground() != null) {
406: String value = resolveColor(element.getBackground());
407: if (value != null) {
408: RGB r = SharedStyleManager.parseRGB(value);
409: if (r != null)
410: bg = new Color(display, r);
411: }
412: }
413: if (element.getForeground() != null) {
414: String value = resolveColor(element.getForeground());
415: if (value != null) {
416: RGB r = SharedStyleManager.parseRGB(value);
417: if (r != null)
418: fg = new Color(display, r);
419: }
420: }
421: }
422:
423: private String resolveColor(String value) {
424: if (value.indexOf('$') == -1)
425: return value;
426: if (value.charAt(0) == '$'
427: && value.charAt(value.length() - 1) == '$'
428: && theme != null) {
429: Map properties = theme.getProperties();
430: if (properties != null) {
431: String key = value.substring(1, value.length() - 1);
432: return (String) properties.get(key);
433: }
434: }
435: return value;
436: }
437:
438: public Control getControl() {
439: return container;
440: }
441:
442: public void dispose() {
443: if (container != null) {
444: container.dispose();
445: }
446: if (toolBarManager != null) {
447: toolBarManager.dispose();
448: toolBarManager.removeAll();
449: }
450:
451: toolBarManager = null;
452: container = null;
453:
454: if (bg != null)
455: bg.dispose();
456: if (fg != null)
457: fg.dispose();
458: }
459:
460: private void fillToolBar() {
461: Action action;
462:
463: closeAction = new Action("close") { //$NON-NLS-1$
464:
465: public void run() {
466: closeLaunchBar(false);
467: }
468: };
469: closeAction.setText(Messages.IntroLaunchBar_close_label);
470: closeAction
471: .setToolTipText(Messages.IntroLaunchBar_close_tooltip);
472: /*
473: * closeAction.setImageDescriptor(ImageUtil
474: * .createImageDescriptor("full/elcl16/close_view.gif")); //$NON-NLS-1$
475: */
476:
477: action = new Action("restore") { //$NON-NLS-1$
478:
479: public void run() {
480: openPage(lastPageId);
481: }
482: };
483: action.setToolTipText(Messages.IntroLaunchBar_restore_tooltip);
484: action
485: .setImageDescriptor(ImageUtil
486: .createImageDescriptor("full/etool16/restore_welcome.gif")); //$NON-NLS-1$
487: // toolBarManager.add(closeAction);
488: toolBarManager.add(action);
489: toolBarManager.add(new Separator());
490: if (element == null)
491: return;
492: IntroLaunchBarShortcut[] shortcuts = element.getShortcuts();
493: for (int i = 0; i < shortcuts.length; i++) {
494: IntroLaunchBarShortcut shortcut = shortcuts[i];
495: addShortcut(shortcut, toolBarManager);
496: }
497: }
498:
499: private void addShortcut(final IntroLaunchBarShortcut shortcut,
500: IToolBarManager toolBarManager) {
501: Action action = new Action(shortcut.getToolTip()) {
502:
503: public void run() {
504: executeShortcut(shortcut.getURL());
505: }
506: };
507: action.setImageDescriptor(shortcut.getImageDescriptor());
508: action.setToolTipText(shortcut.getToolTip());
509: toolBarManager.add(action);
510: }
511:
512: public void close() {
513: closeLaunchBar(false);
514: }
515:
516: protected IIntroPart closeLaunchBar(boolean restore) {
517:
518: IntroPlugin.getDefault().setLaunchBar(null);
519: IWorkbenchWindow window = PlatformUI.getWorkbench()
520: .getActiveWorkbenchWindow();
521:
522: // if we've already been removed, this won't hurt us
523: getTrimManager().removeTrim(this );
524:
525: IIntroPart intro = null;
526: if (restore) {
527: intro = PlatformUI.getWorkbench().getIntroManager()
528: .showIntro(window, false);
529: CustomizableIntroPart cpart = (CustomizableIntroPart) intro;
530: Rectangle startBounds = Geometry.toDisplay(getControl()
531: .getParent(), getControl().getBounds());
532: Rectangle endBounds = Geometry.toDisplay(cpart.getControl()
533: .getParent(), cpart.getControl().getBounds());
534:
535: RectangleAnimation animation = new RectangleAnimation(
536: window.getShell(), startBounds, endBounds);
537: animation.schedule();
538: }
539: dispose();
540: window.getShell().layout();
541: return intro;
542: }
543:
544: protected void executeShortcut(String url) {
545: IIntroURL introURL = IntroURLFactory.createIntroURL(url);
546: if (introURL != null) {
547: IIntroPart intro = closeLaunchBar(true);
548: if (intro == null)
549: return;
550: introURL.execute();
551: }
552: }
553:
554: protected void openPage(String id) {
555: IIntroPart intro = closeLaunchBar(true);
556: if (intro == null)
557: return;
558: StringBuffer url = new StringBuffer();
559: url.append(LAUNCH_COMMAND_BASE);
560: url.append(id);
561: IIntroURL introURL = IntroURLFactory.createIntroURL(url
562: .toString());
563: if (introURL != null)
564: introURL.execute();
565: }
566:
567: protected void contextMenuAboutToShow(IMenuManager manager) {
568: manager.add(closeAction);
569: }
570:
571: public void dock(int side) {
572: dispose();
573: setLocation(side);
574: storeLocation();
575: IWorkbenchWindow window = PlatformUI.getWorkbench()
576: .getActiveWorkbenchWindow();
577: createControl(window.getShell());
578: }
579:
580: private void setLocation(int location) {
581: this .orientation = (location == SWT.LEFT || location == SWT.RIGHT) ? SWT.VERTICAL
582: : SWT.HORIZONTAL;
583: this .location = location;
584: }
585:
586: public int getValidSides() {
587: return SWT.LEFT | SWT.RIGHT | SWT.BOTTOM;
588: }
589:
590: /*
591: * (non-Javadoc)
592: *
593: * @see org.eclipse.ui.internal.IWindowTrim#getId()
594: */
595: public String getId() {
596: return "org.eclipse.ui.internal.intro.impl.presentations.IntroLaunchBar"; //$NON-NLS-1$
597: }
598:
599: /*
600: * (non-Javadoc)
601: *
602: * @see org.eclipse.ui.internal.IWindowTrim#getDisplayName()
603: */
604: public String getDisplayName() {
605: return WorkbenchMessages.TrimCommon_IntroBar_TrimName;
606: }
607:
608: /*
609: * (non-Javadoc)
610: *
611: * @see org.eclipse.ui.internal.IWindowTrim#isCloseable()
612: */
613: public boolean isCloseable() {
614: return element.getClose();
615: }
616:
617: /*
618: * (non-Javadoc)
619: *
620: * @see org.eclipse.ui.internal.IWindowTrim#handleClose()
621: */
622: public void handleClose() {
623: closeLaunchBar(false);
624: }
625:
626: /*
627: * (non-Javadoc)
628: *
629: * @see org.eclipse.ui.IWindowTrim#getWidthHint()
630: */
631: public int getWidthHint() {
632: return SWT.DEFAULT;
633: }
634:
635: /*
636: * (non-Javadoc)
637: *
638: * @see org.eclipse.ui.IWindowTrim#getHeightHint()
639: */
640: public int getHeightHint() {
641: return SWT.DEFAULT;
642: }
643:
644: /*
645: * (non-Javadoc)
646: *
647: * @see org.eclipse.ui.IWindowTrim#isResizeable()
648: */
649: public boolean isResizeable() {
650: return false;
651: }
652:
653: }
|