// ================================================================== // ShelfStackPresentation.java // ================================================================== // IBM Confidential // OCO Source Materials // � Copyright IBM Corp. 2005 // ================================================================== package org.eclipse.swt.nebula.presentations.shelf; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.nebula.widgets.pshelf.PShelf; import org.eclipse.swt.nebula.widgets.pshelf.PShelfItem; import org.eclipse.swt.nebula.widgets.pshelf.RedmondShelfRenderer; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.ui.IPropertyListener; import org.eclipse.ui.presentations.IPresentablePart; import org.eclipse.ui.presentations.IStackPresentationSite; import org.eclipse.ui.presentations.PresentationUtil; import org.eclipse.ui.presentations.StackDropResult; import org.eclipse.ui.presentations.StackPresentation; import java.net.URL; /** * * * @author chris.gross@us.ibm.com * @since 2.0.0 */ public class PShelfStackPresentation extends StackPresentation { private static final String DATAKEY_MENUBUTTONFLAG = "hasMenuButton"; private static final String DATAKEY_MENUTOOL = "Menu Toolbar"; private static final String DATAKEY_DESCLABEL = "Description Label"; private static final String DATAKEY_PART = "IPresentablePart"; private static final String DATAKEY_SEPHEIGHT = "Separator Height"; private static final String DATAKEY_ANIMATION = "Busy Anim Player"; private static final String DATAKEY_CLOSEBUTTONFLAG = "hasCloseButton"; private PShelf shelf; private Composite partParent; private boolean ignoreSelection = false; private Color toolbarBackground; private Color border; private Image menuTBImage; private Image closeTBImage; private Image[] busyImages; /** * @param stackSite */ public PShelfStackPresentation(IStackPresentationSite stackSite, Composite parent) { super(stackSite); partParent = parent; shelf = new PShelf(parent,SWT.SIMPLE | SWT.BORDER); shelf.setRenderer(new RedmondShelfRenderer()); shelf.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { if (event.item == null) return; if (!ignoreSelection) getSite().selectPart((IPresentablePart)event.item.getData(DATAKEY_PART)); } }); RGB sel = parent.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION).getRGB(); RGB blendwith = new RGB(255,255,255); RGB blended = blend(sel,blendwith,20); toolbarBackground = new Color(parent.getDisplay(),blended); blended = blend(sel,blendwith,60); border = new Color(parent.getDisplay(),blended); URL imageURL = Platform.getBundle("org.eclipse.swt.nebula.presentations.shelf").getResource("icons/view_menu.gif"); menuTBImage = ImageDescriptor.createFromURL(imageURL).createImage(); imageURL = Platform.getBundle("org.eclipse.swt.nebula.presentations.shelf").getResource("icons/close_view.gif"); closeTBImage = ImageDescriptor.createFromURL(imageURL).createImage(); PresentationUtil.addDragListener(shelf,new Listener() { public void handleEvent(Event event) { PShelfItem item = shelf.getItem(new Point(event.x,event.y)); if (item == null) return; IPresentablePart part = (IPresentablePart)item.getData(DATAKEY_PART); getSite().selectPart(part); getSite().dragStart(part, new Point(event.x, event.y), false); } }); //init busy images busyImages = new Image[8]; for (int i = 0; i < 8; i++) { URL imgURL = Platform.getBundle("org.eclipse.swt.nebula.presentations.shelf").getResource("icons/busy" + (i + 1) + ".gif"); Image img = ImageDescriptor.createFromURL(imgURL).createImage(); busyImages[i] = img; } } private static int blend(int v1, int v2, int ratio) { return (ratio * v1 + (100 - ratio) * v2) / 100; } private static RGB blend(RGB c1, RGB c2, int ratio) { int r = blend(c1.red, c2.red, ratio); int g = blend(c1.green, c2.green, ratio); int b = blend(c1.blue, c2.blue, ratio); return new RGB(r, g, b); } /** * {@inheritDoc} */ @Override public void addPart(final IPresentablePart newPart, Object cookie) { ignoreSelection = true; final PShelfItem item = new PShelfItem(shelf,SWT.NONE); ignoreSelection = false; item.setData(DATAKEY_PART,newPart); item.getBody().setLayout(null); item.getBody().addListener(SWT.Paint, new Listener() { public void handleEvent(Event e) { Integer separatorY = (Integer)item.getBody().getData(DATAKEY_SEPHEIGHT); if (separatorY == null) return; e.gc.setForeground(border); e.gc.drawLine(0,separatorY.intValue(),item.getBody().getSize().x,separatorY.intValue()); } }); CLabel descLabel = new CLabel(item.getBody(),SWT.WRAP); item.setData(DATAKEY_DESCLABEL,descLabel); descLabel.setBackground(toolbarBackground); ToolBar tb = new ToolBar(item.getBody(),SWT.NONE); item.setData(DATAKEY_MENUTOOL,tb); tb.setBackground(toolbarBackground); updateItem(newPart); newPart.addPropertyListener(new IPropertyListener() { public void propertyChanged(Object source, int propId) { updateItem(newPart); } }); } private void updateItem(final IPresentablePart part) { PShelfItem item = getItem(part); String dirty = ""; if (part.isDirty()) dirty = "*"; item.setText(dirty + part.getName()); item.setImage(part.getTitleImage()); CLabel descLabel = (CLabel)item.getData(DATAKEY_DESCLABEL); descLabel.setText(part.getTitleStatus()); final ToolBar menuTB = (ToolBar)item.getData(DATAKEY_MENUTOOL); if (part.getMenu() != null && menuTB.getData(DATAKEY_MENUBUTTONFLAG) == null) { final ToolItem ti = new ToolItem(menuTB,0,SWT.NONE); ti.setImage(menuTBImage); ti.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { Point loc = new Point(ti.getBounds().x,ti.getBounds().y + ti.getBounds().height); loc = ti.getDisplay().map(menuTB, null, loc); part.getMenu().showMenu(loc); } }); ti.setToolTipText("Show Menu"); menuTB.setData(DATAKEY_MENUBUTTONFLAG,"AnyValue"); } if (part.isCloseable() && menuTB.getData(DATAKEY_CLOSEBUTTONFLAG) == null) { final ToolItem ti = new ToolItem(menuTB,SWT.NONE); ti.setImage(closeTBImage); ti.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { getSite().close(new IPresentablePart[]{part}); } }); ti.setToolTipText("Close"); menuTB.setData(DATAKEY_CLOSEBUTTONFLAG,"AnyValue"); } Control partTB = part.getToolBar(); if (partTB != null) { partTB.setBackground(toolbarBackground); } resizeSelectedPart(); if (part.isBusy() && item.getData(DATAKEY_ANIMATION) == null) { BusyItemAnimation busyAnim = new BusyItemAnimation(item); busyAnim.setImages(busyImages); item.setData(DATAKEY_ANIMATION,busyAnim); busyAnim.start(); } else if (!part.isBusy() && item.getData(DATAKEY_ANIMATION) != null) { BusyItemAnimation busyAnim = (BusyItemAnimation)item.getData(DATAKEY_ANIMATION); busyAnim.stop(); item.setData(DATAKEY_ANIMATION,null); item.setImage(part.getTitleImage()); } } /** * {@inheritDoc} */ @Override public void dispose() { shelf.dispose(); toolbarBackground.dispose(); border.dispose(); menuTBImage.dispose(); for (int i = 0; i < busyImages.length; i++) { busyImages[i].dispose(); } } /** * {@inheritDoc} */ @Override public StackDropResult dragOver(Control currentControl, Point location) { // TODO Auto-generated method stub return null; } /** * {@inheritDoc} */ @Override public Control getControl() { return shelf; } /** * {@inheritDoc} */ @Override public Control[] getTabList(IPresentablePart part) { // TODO Auto-generated method stub return null; } /** * {@inheritDoc} */ @Override public void removePart(IPresentablePart oldPart) { getItem(oldPart).dispose(); resizeSelectedPart(); oldPart.setVisible(false); if (oldPart.getToolBar() != null) oldPart.getToolBar().setVisible(false); } private PShelfItem getItem(IPresentablePart part) { PShelfItem[] items = shelf.getItems(); for (int i = 0; i < items.length; i++) { if (items[i].getData(DATAKEY_PART) == part) { return items[i]; } } return null; } /** * {@inheritDoc} */ @Override public void selectPart(IPresentablePart toSelect) { shelf.setSelection(getItem(toSelect)); IPresentablePart[] parts = getSite().getPartList(); for (int i = 0; i < parts.length; i++) { parts[i].setVisible(parts[i] == toSelect); } updateItem(toSelect); resizeSelectedPart(); } /** * {@inheritDoc} */ @Override public void setActive(int newState) { } /** * {@inheritDoc} */ @Override public void setBounds(Rectangle bounds) { shelf.setBounds(bounds); shelf.getDisplay().asyncExec(new Runnable() { public void run() { // TODO Auto-generated method stub resizeSelectedPart(); } }); resizeSelectedPart(); } private void resizeSelectedPart() { IPresentablePart part = getSite().getSelectedPart(); if (part == null) return; PShelfItem item = getItem(part); if (item == null) return; CLabel descLabel = (CLabel)item.getData(DATAKEY_DESCLABEL); ToolBar menuTB = (ToolBar)item.getData(DATAKEY_MENUTOOL); Control partTB = part.getToolBar(); Point partTBSize = new Point(0,0); if (partTB != null) partTBSize = partTB.computeSize(SWT.DEFAULT,SWT.DEFAULT); Point menuTBSize = menuTB.computeSize(SWT.DEFAULT,SWT.DEFAULT); if (menuTB.getItemCount() == 0) menuTBSize = new Point(0,0); Rectangle bounds = item.getBody().getBounds(); int maxWidth = bounds.width - menuTBSize.x; boolean partTBonLine1 = (partTB == null? true : (partTBSize.x <= maxWidth)); int height = 0; if (partTBonLine1) { height = Math.max(menuTBSize.y, partTBSize.y); menuTB.setBounds(bounds.width - menuTBSize.x,0,menuTBSize.x,height); if (partTB != null) { Rectangle toolBounds = new Rectangle(bounds.width - menuTBSize.x - partTBSize.x,0,partTBSize.x,height); toolBounds = shelf.getDisplay().map(item.getBody(), partTB.getParent(), toolBounds); toolBounds.height = Math.min(item.getBody().getSize().y, toolBounds.height); partTB.setBounds(toolBounds); } descLabel.setBounds(0,0,bounds.width - menuTBSize.x - partTBSize.x,height); } else { menuTB.setBounds(bounds.width - menuTBSize.x,0,menuTBSize.x,menuTBSize.y); descLabel.setBounds(0,0,bounds.width - menuTBSize.x,menuTBSize.y); partTBSize = partTB.computeSize(bounds.width,SWT.DEFAULT); Rectangle toolBounds = new Rectangle(0,menuTBSize.y,bounds.width,partTBSize.y); height = menuTBSize.y + toolBounds.height; toolBounds.height = Math.min(toolBounds.height, item.getBody().getSize().y - toolBounds.y); toolBounds = shelf.getDisplay().map(item.getBody(), partTB.getParent(), toolBounds); partTB.setBounds(toolBounds); } if (height > 0) { //add space for the separator height += 1; item.getBody().setData(DATAKEY_SEPHEIGHT,new Integer(height -1)); item.getBody().redraw(); } bounds.height -= height; bounds.y += height; bounds = shelf.getDisplay().map(shelf.getSelection().getBody().getParent(), partParent, bounds); part.setBounds(bounds); } /** * {@inheritDoc} */ @Override public void setState(int state) { } /** * {@inheritDoc} */ @Override public void setVisible(boolean isVisible) { shelf.setVisible(isVisible); if (getSite().getSelectedPart() == null) return; getSite().getSelectedPart().setVisible(isVisible); if (getSite().getSelectedPart().getToolBar() != null) getSite().getSelectedPart().getToolBar().setVisible(isVisible); } /** * {@inheritDoc} */ @Override public void showPaneMenu() { } /** * {@inheritDoc} */ @Override public void showSystemMenu() { } }