/** * */ package org.bonitasoft.studio.properties.sections.appearance; import java.util.HashMap; import java.util.Iterator; import org.eclipse.gmf.runtime.common.ui.util.WindowUtil; import org.eclipse.gmf.runtime.diagram.ui.properties.internal.l10n.DiagramUIPropertiesMessages; import org.eclipse.gmf.runtime.draw2d.ui.figures.FigureUtilities; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.preference.ColorSelector; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; /** * @author Romain * */ public class CustomColorPalettePopup { /** variable to store previous color */ private int previousColor; private Button customColorButton; private HashMap buttonMap = new HashMap(); /** * A descirptor for an inventory color */ private static class InventoryColorDescriptor extends ImageDescriptor { /** the default preference color */ private static final RGB OUTLINE_COLOR = new RGB(192, 192, 192); public RGB rgb; public InventoryColorDescriptor(RGB colorValue) { this.rgb = colorValue; } /** * @see org.eclipse.jface.resource.ImageDescriptor#getImageData() */ public ImageData getImageData() { ImageData data = new ImageData(ICON_SIZE.x, ICON_SIZE.y, 1, new PaletteData(new RGB[] {rgb, OUTLINE_COLOR})); for (int i = 0; i < ICON_SIZE.y; i++) data.setPixel(0, i, 1); for (int i = 0; i < ICON_SIZE.y; i++) data.setPixel(ICON_SIZE.x - 1, i, 1); for (int i = 0; i < ICON_SIZE.x; i++) data.setPixel(i, 0, 1); for (int i = 0; i < ICON_SIZE.x; i++) data.setPixel(i, ICON_SIZE.y - 1, 1); return data; } /** * Creates and returns a new SWT image for this image descriptor. The * returned image must be explicitly disposed using the image's dispose * call. The image will not be automatically garbage collected. In the * even of an error, a default image is returned if * <code>returnMissingImageOnError</code> is true, otherwise * <code>null</code> is returned. * <p> * Note: Even if <code>returnMissingImageOnError</code> is true, it is * still possible for this method to return <code>null</code> in * extreme cases, for example if SWT runs out of image handles. * </p> * * @return a new image or <code>null</code> if the image could not be * created * */ public Image createImage() { Device device = Display.getCurrent(); ImageData data = getImageData(); if (data == null) data = DEFAULT_IMAGE_DATA; /* * Try to create the supplied image. If there is an SWT Exception * try and create the default image if that was requested. Return * null if this fails. */ try { if (data.transparentPixel >= 0) { ImageData maskData = data.getTransparencyMask(); return new Image(device, data, maskData); } return new Image(device, data); } catch (SWTException exception) { try { return new Image(device, DEFAULT_IMAGE_DATA); } catch (SWTException nextException) { return null; } } } } /** default color icon width */ public static final Point ICON_SIZE = new Point(IDialogConstants.BUTTON_BAR_HEIGHT, IDialogConstants.BUTTON_BAR_HEIGHT); /** inventory colors */ private static final InventoryColorDescriptor WHITE = new InventoryColorDescriptor( new RGB(255, 255, 255)); private static final InventoryColorDescriptor BLACK = new InventoryColorDescriptor( new RGB(0, 0, 0)); private static final InventoryColorDescriptor LIGHT_GRAY = new InventoryColorDescriptor( new RGB(192, 192, 192)); private static final InventoryColorDescriptor GRAY = new InventoryColorDescriptor( new RGB(128, 128, 128)); private static final InventoryColorDescriptor RED = new InventoryColorDescriptor( new RGB(227, 164, 156)); private static final InventoryColorDescriptor GREEN = new InventoryColorDescriptor( new RGB(166, 193, 152)); private static final InventoryColorDescriptor BLUE = new InventoryColorDescriptor( new RGB(152, 168, 191)); private static final InventoryColorDescriptor YELLOW = new InventoryColorDescriptor( new RGB(225, 225, 135)); private static final InventoryColorDescriptor PURPLE = new InventoryColorDescriptor( new RGB(184, 151, 192)); private static final InventoryColorDescriptor TEAL = new InventoryColorDescriptor( new RGB(155, 199, 204)); private static final InventoryColorDescriptor PINK = new InventoryColorDescriptor( new RGB(228, 179, 229)); private static final InventoryColorDescriptor ORANGE = new InventoryColorDescriptor( new RGB(237, 201, 122)); /** the inventory color list key: anRGB, value: anImage */ private static final HashMap imageColorMap = new HashMap(); private static final String DEAFULT_COLOR_STRING = DiagramUIPropertiesMessages.ColorPalettePopup_default; private static final String CUSTOM_COLOR_STRING = DiagramUIPropertiesMessages.ColorPalettePopup_custom; static { // inventory colors imageColorMap.put(WHITE.rgb, WHITE.createImage()); imageColorMap.put(BLACK.rgb, BLACK.createImage()); imageColorMap.put(LIGHT_GRAY.rgb, LIGHT_GRAY.createImage()); imageColorMap.put(GRAY.rgb, GRAY.createImage()); imageColorMap.put(RED.rgb, RED.createImage()); imageColorMap.put(GREEN.rgb, GREEN.createImage()); imageColorMap.put(BLUE.rgb, BLUE.createImage()); imageColorMap.put(YELLOW.rgb, YELLOW.createImage()); imageColorMap.put(PURPLE.rgb, PURPLE.createImage()); imageColorMap.put(TEAL.rgb, TEAL.createImage()); imageColorMap.put(PINK.rgb, PINK.createImage()); imageColorMap.put(ORANGE.rgb, ORANGE.createImage()); } private Shell shell; private RGB selectedColor = null; /** * The default color to be used if the user presses the default button. */ private boolean useDefaultColor = false; /** * Creates a PopupList above the specified shell. * * @param parent * a widget which will be the parent of the new instance (cannot * be null) * @param style * the style of widget to construct */ public CustomColorPalettePopup(Shell parent, int rowHeight) { shell = new Shell(parent, checkStyle(SWT.NONE)); shell.setLayout(new FillLayout()); GridLayout layout = new GridLayout(4, true); shell.setLayout(layout); for (Iterator e = imageColorMap.keySet().iterator(); e.hasNext();) { Button button = new Button(shell, SWT.PUSH | SWT.FLAT); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); data.heightHint = rowHeight; data.widthHint = rowHeight; button.setLayoutData(data); final RGB rgb = (RGB) e.next(); final Image image = (Image) imageColorMap.get(rgb); button.setImage(image); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e1) { selectedColor = rgb; shell.dispose(); } }); buttonMap.put(rgb , button); } Button defaultButton = new Button(shell, SWT.PUSH | SWT.FLAT); defaultButton.setText(DEAFULT_COLOR_STRING); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); data.horizontalSpan = 4; defaultButton.setLayoutData(data); defaultButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { useDefaultColor = true; shell.dispose(); } }); Button moreColors = new Button(shell, SWT.PUSH | SWT.FLAT); moreColors.setText(CUSTOM_COLOR_STRING); data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); data.horizontalSpan = 4; moreColors.setLayoutData(data); final org.eclipse.swt.widgets.Composite composite = moreColors.getParent() ; moreColors.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { ColorSelector dialog = new ColorSelector(composite); dialog.setColorValue(FigureUtilities.integerToRGB(getPreviousColor())); WindowUtil.centerDialog(composite.getShell(), Display.getCurrent().getActiveShell()); dialog.open(); selectedColor = dialog.getColorValue(); shell.dispose() ; } }); // close dialog if user selects outside of the shell Display.getCurrent().addFilter(SWT.MouseDown, new Listener() { public void handleEvent(Event event) { if(event.widget instanceof Button){ if(((Button) event.widget).getParent().equals(shell)){ return ; } } shell.dispose() ; } }) ; customColorButton = moreColors; } /** * @param style * @return */ private static int checkStyle(int style) { int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT; return style & mask; } /** * Launches the Popup List, waits for an item to be selected and then closes * PopupList. * * @param rect * the initial size and location of the PopupList; the dialog * will be positioned so that it does not run off the screen and * the largest number of items are visible * * @return the text of the selected item or null if no item is selected */ public RGB open(Point location) { Point listSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT, false); shell.setBounds(location.x, location.y, listSize.x, listSize.y); shell.open(); shell.setFocus(); Display display = shell.getDisplay(); Button prevButton = (Button)buttonMap.get(FigureUtilities.integerToRGB(getPreviousColor())); if (prevButton != null){ shell.setDefaultButton(prevButton); } else{ shell.setDefaultButton(customColorButton); } while (!shell.isDisposed() && shell.isVisible()) { if (!display.readAndDispatch()) display.sleep(); } return getSelectedColor(); } /** * Gets the color the user selected. Could be null as the user may have * cancelled the gesture or they may have selected the default color button. * See {@link #useDefaultColor()}. * * @return the selected color or null */ public RGB getSelectedColor() { return selectedColor; } /** * Returns true if the user selected to use the default color * * @return true if the default color is to be used; false otherwise */ public boolean useDefaultColor() { return useDefaultColor; } public int getPreviousColor() { return previousColor; } public void setPreviousColor(int previousColor) { this.previousColor = previousColor; } }