diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/BooleanCellEditor.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/BooleanCellEditor.java deleted file mode 100644 index 8a76ed601205326b46a7d3e8e84feacbe309b7c3..0000000000000000000000000000000000000000 --- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/BooleanCellEditor.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * <copyright> - * - * Copyright (c) 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM - Initial API and implementation - * Alexander Mark Diewald, fortiss GmbH (diewald@fortiss.org) - Minor adoptions and documentation - * - * </copyright> - * - * $Id$ - */ -package org.fortiss.tooling.base.ui.annotation.editingsupport; - -import static org.eclipse.core.runtime.Platform.getBundle; - -import org.eclipse.jface.viewers.CellEditor; -import org.eclipse.jface.viewers.CheckboxCellEditor; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** - * {@link CellEditor} for manipulating boolean values within a table. Unlike the - * {@link CheckboxCellEditor}, this class actually provides a checkbox for manipulating the boolean - * value, instead of just toggling <code>true</code> and <code>false</code>. - * - * @author diewald - * @author $Author$ - * @version $Rev$ - * @ConQAT.Rating YELLOW Hash: EFD0302B4B0E12BEC467B3A359C4DFA7 - */ -public class BooleanCellEditor extends CellEditor { - - /** The checkbox button. */ - private Button button; - - /** Default constructor for {@link BooleanCellEditor}. */ - public BooleanCellEditor(Composite parent) { - super(parent); - } - - /** Constructs a new {@link BooleanCellEditor} using a given style. */ - public BooleanCellEditor(Composite parent, int style) { - super(parent, style); - } - - /** {@inheritDoc} */ - @Override - protected Control createControl(Composite parent) { - Font font = parent.getFont(); - Color bg = parent.getBackground(); - - button = new Button(parent, getStyle() | SWT.CHECK); - button.setFont(font); - button.setBackground(bg); - - return button; - } - - /** {@inheritDoc} */ - @Override - protected Object doGetValue() { - return button.getSelection(); - } - - /** {@inheritDoc} */ - @Override - protected void doSetValue(Object value) { - boolean selection = Boolean.TRUE.equals(value); - button.setSelection(selection); - } - - /** {@inheritDoc} */ - @Override - protected void doSetFocus() { - if(button != null) { - // Toggle value on first click - boolean value = Boolean.TRUE.equals(doGetValue()); - doSetValue(!(value)); - - // Set focus to button - button.setFocus(); - - // Update view, i.e. remove last visible traces of the icon - // shown by the corresponding EmulatedNativeCheckBoxLabelProvider - // (which as already been removed at the time when this method is - // called). - button.getParent().layout(); - - // For GTK-environments, the layout call is not sufficient to hide - // the cell editor. Here, it is required to unset the focus. This - // results in a NPE in windows, so restrict to gtk environments. - if(getBundle("org.eclipse.swt.gtk.linux.x86_64") != null || - getBundle("org.eclipse.swt.gtk.linux.x86") != null) { - focusLost(); - } - - // TODO (see #2268): This BooleanCellEditor widget is temporarily shown at a wrong - // position (seen best when holding mouse button down for a longer time - // when clicking the cell). - } - } -} diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/CheckBoxEditingSupport.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/CheckBoxEditingSupport.java index b9dbcb15ce14a68fccb64bd6765b32a5c7a39b4e..9b77373cdc14d6e46c9e346888c8c1b761c24d26 100644 --- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/CheckBoxEditingSupport.java +++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/editingsupport/CheckBoxEditingSupport.java @@ -18,9 +18,10 @@ $Id$ package org.fortiss.tooling.base.ui.annotation.editingsupport; import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.CheckboxCellEditor; import org.eclipse.jface.viewers.ColumnViewer; import org.eclipse.jface.viewers.EditingSupport; -import org.eclipse.swt.widgets.Composite; +import org.eclipse.jface.viewers.TableViewer; import org.fortiss.tooling.base.annotation.AnnotationEntry; import org.fortiss.tooling.base.model.element.IAnnotatedSpecification; @@ -30,21 +31,18 @@ import org.fortiss.tooling.base.model.element.IAnnotatedSpecification; * @author diewald * @author $Author$ * @version $Rev$ - * @ConQAT.Rating GREEN Hash: C42FE8EEE22E0569F39C33ACBFD27962 + * @ConQAT.Rating YELLOW Hash: 70DB817065BF424F1C51A85A018C02D1 */ public class CheckBoxEditingSupport extends AnnotationEditingSupportBase { - /** Contains the {@link BooleanCellEditor} that is displayed. */ - private BooleanCellEditor checkBoxEditor; - - /** Flag if this {@link BooleanCellEditor} is editable. */ - private boolean isEditable; + /** Placeholder for the boolean value editor (in fact, only an icon is toggled). */ + private CheckboxCellEditor checkBoxEditor; /** Constructs a new {@link CheckBoxEditingSupport}. */ public CheckBoxEditingSupport(ColumnViewer viewer, Class<? extends IAnnotatedSpecification> specClass, String instanceKey) { super(viewer, specClass, instanceKey); - checkBoxEditor = new BooleanCellEditor((Composite)getViewer().getControl()); + checkBoxEditor = new CheckboxCellEditor(((TableViewer)viewer).getTable()); } /** {@inheritDoc} */ @@ -56,25 +54,4 @@ public class CheckBoxEditingSupport extends AnnotationEditingSupportBase { return checkBoxEditor; } - - /** {@inheritDoc} */ - @Override - protected void setValue(Object element, Object box) { - if(isEditable) { - super.setValue(element, checkBoxEditor.getValue()); - } - } - - /** {@inheritDoc} */ - @Override - protected Object getValue(Object element) { - Object value = super.getValue(element); - - if(value != null) { - isEditable = ((AnnotationEntry)element).canEdit(specClass); - checkBoxEditor.setValue(value); - } - - return value; - } } diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/labelprovider/CheckBoxLabelProvider.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/labelprovider/CheckBoxLabelProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..4b7c98d089603c1cfa2d360177004d40f3a288eb --- /dev/null +++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/labelprovider/CheckBoxLabelProvider.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2006, 2014 Tom Schindl and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation + * Florian Potschka <signalrauschen@gmail.com> - Bug 260061 + * Alexander Ljungberg <siker@norwinter.com> - Bug 260061 + * Jeanderson Candido <http://jeandersonbc.github.io> - Bug 414565 + * Alexander Mark Diewald <diewald@fortiss.org> + *******************************************************************************/ +package org.fortiss.tooling.base.ui.annotation.labelprovider; + +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.graphics.Image; +import org.fortiss.tooling.base.annotation.AnnotationEntry; +import org.fortiss.tooling.base.model.element.IAnnotatedSpecification; +import org.fortiss.tooling.base.ui.annotation.view.IAnnotationViewPart; + +/** + * <p> + * A {@link ColumnLabelProvider} for annotations that displays checkboxes indicating the value of + * annotations that contain boolean values. + * </p> + * <p> + * This implementation uses 'screenshot' {@link Image}s of the checkboxes, since {@link TableViewer} + * is not able to display SWT widgets when a cell is not edited. Since the screenshots are made + * during runtime, the resulting images fit the underlying OS. + * </p> + * + * @author diewald + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 6A850011E144844D374AD1283AC48CC0 + */ +public class CheckBoxLabelProvider extends AnnotationLabelProvider { + + /** Constructor. */ + public CheckBoxLabelProvider(Class<? extends IAnnotatedSpecification> clazz, + IAnnotationViewPart viewPart, String instanceKey, EditingSupport editingSupport) { + super(clazz, viewPart, instanceKey, editingSupport); + } + + /** {@inheritDoc} */ + @Override + public String getText(Object element) { + return ""; + } + + /** {@inheritDoc} */ + @Override + public Image getImage(Object element) { + if(element instanceof AnnotationEntry) { + boolean enabled = ((AnnotationEntry)element).canEdit(clazz); + return org.fortiss.tooling.base.ui.tablecell.CheckBoxLabelProvider.getImage( + isChecked(element), enabled); + } + return null; + } + + /** + * Determines whether the boolean value is 'true' or 'false'. Used to determine the 'checked' + * status of the checkbox. + */ + protected boolean isChecked(Object element) { + if(element instanceof AnnotationEntry) { + AnnotationEntry annotationEntry = (AnnotationEntry)element; + + Object value = null; + try { + value = annotationEntry.getSpecificationValue(clazz, instanceKey); + } catch(Exception e) { + return false; + } + if(value != null) { + // It is already known that the value is a boolean. + return (Boolean)value; + } + } + return false; + } +} diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/labelprovider/EmulatedNativeCheckBoxLabelProvider.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/labelprovider/EmulatedNativeCheckBoxLabelProvider.java deleted file mode 100644 index 6f7cb57466b8a865974fba79be2e192c40eb4f78..0000000000000000000000000000000000000000 --- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/labelprovider/EmulatedNativeCheckBoxLabelProvider.java +++ /dev/null @@ -1,245 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2014 Tom Schindl and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation - * Florian Potschka <signalrauschen@gmail.com> - Bug 260061 - * Alexander Ljungberg <siker@norwinter.com> - Bug 260061 - * Jeanderson Candido <http://jeandersonbc.github.io> - Bug 414565 - * Alexander Mark Diewald <diewald@fortiss.org> - *******************************************************************************/ -package org.fortiss.tooling.base.ui.annotation.labelprovider; - -import static org.eclipse.core.runtime.Platform.getBundle; -import static org.eclipse.jface.resource.JFaceResources.getImageRegistry; - -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ColumnViewer; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.ViewerCell; -import org.eclipse.jface.viewers.ViewerRow; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableItem; -import org.fortiss.tooling.base.annotation.AnnotationEntry; -import org.fortiss.tooling.base.model.element.IAnnotatedSpecification; -import org.fortiss.tooling.base.ui.annotation.view.IAnnotationViewPart; - -/** - * <p> - * A {@link ColumnLabelProvider} for annotations that displays checkboxes indicating the value of - * annotations that contain boolean values. - * </p> - * <p> - * This is a workaround using 'screenshots' of the checkboxes, since {@link TableViewer} is not able - * to display SWT widgets when a cell is not edited. This concretely means that, when the cell is - * not being edited (e.g., if no or another cell is edited), then the checkbox would simply - * disappear and the default text-based label provider would be shown. - * </p> - * - * <p> - * Since the screenshots are made during runtime, the resulting images fit the underlying OS. - * </p> - * - * - * @author diewald - * @author $Author$ - * @version $Rev$ - * @ConQAT.Rating YELLOW Hash: BF686162C5BC9CEDC6DBBD199131F8C4 - */ -public class EmulatedNativeCheckBoxLabelProvider extends AnnotationLabelProvider { - - /** Key for the 'checked' checkbox. */ - private static final String CHECKED_KEY = "CHECKED"; - - /** Key for the 'unchecked' checkbox. */ - private static final String UNCHECKED_KEY = "UNCHECKED"; - - /** Currently referenced row. */ - ViewerRow row; - - /** Constructs a new {@link EmulatedNativeCheckBoxLabelProvider}. */ - public EmulatedNativeCheckBoxLabelProvider(Class<? extends IAnnotatedSpecification> specClass, - IAnnotationViewPart viewPart, String instanceKey, ColumnViewer viewer) { - super(specClass, viewPart, instanceKey, null); - - if(getImageRegistry().getDescriptor(CHECKED_KEY) == null) { - getImageRegistry().put(UNCHECKED_KEY, makeShot(viewer.getControl(), false)); - getImageRegistry().put(CHECKED_KEY, makeShot(viewer.getControl(), true)); - } - } - - /** {@inheritDoc} */ - @Override - public void update(final ViewerCell cell) { - super.update(cell); - - if(cell != null && cell.getViewerRow() != null) { - - // On the first invocation, register mouse listener to - // cell's control (i.e., the table) in order to remove the - // icon when the actual widget is to be shown. - // - // This cannot be achieved using a FocusListener since it - // does not provide a way to determine the cell which has been - // clicked (source and widget of the event refer to the Table itself). - if(row == null) { - cell.getControl().addMouseListener(new MouseListener() { - - @Override - public void mouseDoubleClick(MouseEvent e) { - // Nothing to do - } - - @Override - public void mouseDown(MouseEvent e) { - Point pt = new Point(e.x, e.y); - - // Registration of mouseListener ensures that row is non-null - TableItem item = ((Table)row.getControl()).getItem(pt); - - // Hide image showing the icon emulating the native check box since the - // user as clicked this cell and the check box widget is about to be - // shown. - // - // Otherwise, both the icon and the widget would be visible in parallel. - // - // After the user has finished editing, the framework will call - // getImage() in order to restore the icon emulating the native check - // box. - if(item != null) { - - // Source and widget of the event 'e' refer to the Table itself, so - // we need to iterate over all columns of the current row and check the - // coordinates to find the actual cell. - for(int col = 0; col < ((Table)row.getControl()).getColumnCount(); col++) { - Rectangle rect = item.getBounds(col); - if(rect.contains(pt)) { - row.setImage(col, null); - } - } - } - } - - @Override - public void mouseUp(MouseEvent e) { - // Nothing to do - } - }); - } - - // Later on, just update the referenced row. - row = cell.getViewerRow(); - } - super.update(cell); - } - - /** Takes a 'screenshot' of the checkbox control an stores it in the image registry. */ - private Image makeShot(Control control, boolean type) { - // Hopefully no platform uses exactly this color because we'll make - // it transparent in the image. - Color greenScreen = new Color(control.getDisplay(), 222, 223, 224); - - Shell shell = new Shell(control.getShell(), SWT.NO_TRIM); - - // otherwise we have a default gray color - shell.setBackground(greenScreen); - - Button button = new Button(shell, SWT.CHECK); - button.setBackground(greenScreen); - button.setSelection(type); - - // otherwise an image is located in a corner - button.setLocation(1, 1); - Point bsize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT); - - // otherwise an image is stretched by width - bsize.x = Math.max(bsize.x - 1, bsize.y - 1); - bsize.y = Math.max(bsize.x - 1, bsize.y - 1); - button.setSize(bsize); - shell.setSize(bsize); - - shell.open(); - - // Work around a gtk display error that causes the widgets in the - // shell not being "visible". Opening a second Shell modifies some - // internal properties of the existing shell, such that the widgets - // become visible. - if(getBundle("org.eclipse.swt.gtk.linux.x86_64") != null || - getBundle("org.eclipse.swt.gtk.linux.x86") != null) { - Shell shell2 = new Shell(control.getShell(), SWT.NO_TRIM); - shell2.open(); - shell2.close(); - } - - GC gc = new GC(shell); - Image image = new Image(control.getDisplay(), bsize.x, bsize.y); - gc.copyArea(image, 0, 0); - gc.dispose(); - shell.close(); - - ImageData imageData = image.getImageData(); - imageData.transparentPixel = imageData.palette.getPixel(greenScreen.getRGB()); - - image.dispose(); - greenScreen.dispose(); - - return new Image(control.getDisplay(), imageData); - } - - /** {@inheritDoc} */ - @Override - public String getText(Object element) { - return ""; - } - - /** {@inheritDoc} */ - @Override - public Image getImage(Object element) { - if(element instanceof AnnotationEntry && ((AnnotationEntry)element).canEdit(clazz)) { - if(isChecked(element)) { - return JFaceResources.getImageRegistry().get(CHECKED_KEY); - } - return JFaceResources.getImageRegistry().get(UNCHECKED_KEY); - } - return null; - } - - /** - * Determines whether the boolean value is 'true' or 'false'. Used to determine the 'checked' - * status of the checkbox. - */ - protected boolean isChecked(Object element) { - if(element instanceof AnnotationEntry) { - AnnotationEntry annotationEntry = (AnnotationEntry)element; - - Object value = null; - try { - value = annotationEntry.getSpecificationValue(clazz, instanceKey); - } catch(Exception e) { - return false; - } - if(value != null) { - // It is already known that the value is a boolean. - return (Boolean)value; - } - } - return false; - } -} diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/labelprovider/LabelProviderFactory.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/labelprovider/LabelProviderFactory.java index f41b301348e08a87f7b1fc97c00aa8dac829aadd..8b4cc56973eb891c2885b44393b7a5da1d0fd79d 100644 --- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/labelprovider/LabelProviderFactory.java +++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/labelprovider/LabelProviderFactory.java @@ -32,7 +32,7 @@ import org.fortiss.tooling.base.ui.annotation.view.generic.GenericAnnotationView * @author barner * @author $Author$ * @version $Rev$ - * @ConQAT.Rating GREEN Hash: BA975FC0E3ECD78ED2D3FC42B64CB7BA + * @ConQAT.Rating YELLOW Hash: 8611517FF616B8E77B42DE4D986456F1 */ public class LabelProviderFactory { @@ -63,8 +63,8 @@ public class LabelProviderFactory { throws Exception { if(valueProvider.getAnnotationValue(specification, instanceKey) instanceof Boolean) { - return new EmulatedNativeCheckBoxLabelProvider(clazz, viewPart, instanceKey, - columnViewer); + return new CheckBoxLabelProvider(clazz, viewPart, instanceKey, + editingSupport); } return new AnnotationLabelProvider(clazz, viewPart, instanceKey, editingSupport); } diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/tablecell/CheckBoxLabelProvider.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/tablecell/CheckBoxLabelProvider.java index b74bfd3a9fbb7ab4c28a98c4fd3eee1e0843e0ef..139e10ac2b022e25a0b6000ff03cd0931f96ff5c 100644 --- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/tablecell/CheckBoxLabelProvider.java +++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/tablecell/CheckBoxLabelProvider.java @@ -17,28 +17,30 @@ $Id$ +--------------------------------------------------------------------------*/ package org.fortiss.tooling.base.ui.tablecell; +import static org.eclipse.core.runtime.Platform.getBundle; import static org.eclipse.jface.resource.JFaceResources.getImageRegistry; -import static org.eclipse.swt.SWT.CHECK; -import static org.eclipse.swt.SWT.DEFAULT; -import static org.eclipse.swt.SWT.NO_TRIM; +import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; /** - * Checkbox label provider using checkbox button images as representation. This + * Checkbox label provider using screenshots of native checkbox buttons as representation. This * class supports checked and enabled state. * * @author hoelzl * @author $Author$ * @version $Rev$ - * @ConQAT.Rating GREEN Hash: C473EA62A46BAA323662C9046C2921B5 + * @ConQAT.Rating YELLOW Hash: 262C0686171A717317A4E8F6D6A2160D */ // Using drawn images may seem strange, but internet sources could not provide // any other solution to having checkbox in cell editors @@ -55,59 +57,91 @@ public abstract class CheckBoxLabelProvider extends ColumnLabelProvider { /** {@link JFaceResources} id for disabled, checked image. */ private static final String DISABLED_CHECKED_KEY = "DISABLED_CHECKED"; - /** Constructor. */ - public CheckBoxLabelProvider(ColumnViewer viewer) { - if(getImageRegistry().getDescriptor(CHECKED_KEY) == null) { - getImageRegistry().put(UNCHECKED_KEY, - makeShot(viewer.getControl().getShell(), false, true)); - getImageRegistry().put(CHECKED_KEY, - makeShot(viewer.getControl().getShell(), true, true)); - getImageRegistry().put(DISABLED_UNCHECKED_KEY, - makeShot(viewer.getControl().getShell(), false, false)); - getImageRegistry().put(DISABLED_CHECKED_KEY, - makeShot(viewer.getControl().getShell(), true, false)); + /** Creates an image of checkbox SWT control. */ + private static Image makeShot(boolean selected, boolean enabled) { + Shell shell = new Shell(SWT.NO_TRIM); + Display display = shell.getDisplay(); + + // Hopefully no platform uses exactly this color because we'll make + // it transparent in the image. + Color greenScreen = new Color(display, 222, 223, 224); + + // Otherwise we have a default gray color + shell.setBackground(greenScreen); + + Button button = new Button(shell, SWT.CHECK); + button.setBackground(greenScreen); + button.setSelection(selected); + button.setEnabled(enabled); + + // Otherwise an image is located in a corner + button.setLocation(1, 1); + Point bsize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT); + + // Otherwise an image is stretched by width + bsize.x = Math.max(bsize.x - 1, bsize.y - 1); + bsize.y = Math.max(bsize.x - 1, bsize.y - 1); + button.setSize(bsize); + shell.setSize(bsize); + + shell.open(); + + // Work around a gtk display error that causes the widgets in the + // shell not being "visible". Opening a second Shell modifies some + // internal properties of the existing shell, such that the widgets + // become visible. + if(getBundle("org.eclipse.swt.gtk.linux.x86_64") != null || + getBundle("org.eclipse.swt.gtk.linux.x86") != null) { + Shell shellGtkQuirk = new Shell(shell, SWT.NO_TRIM); + shellGtkQuirk.open(); + shellGtkQuirk.close(); } - } - /** Creates an image of checkbox SWT control. */ - private Image makeShot(Shell shell, boolean checked, boolean enabled) { - Shell s = new Shell(shell, NO_TRIM); - Button b = new Button(s, CHECK); - b.setSelection(checked); - b.setEnabled(enabled); - Point bsize = b.computeSize(DEFAULT, DEFAULT); - b.setSize(bsize); - b.setLocation(0, 0); - s.setSize(bsize); - s.open(); - - GC gc = new GC(b); - Image image = new Image(shell.getDisplay(), bsize.x, bsize.y); + GC gc = new GC(shell); + Image image = new Image(display, bsize.x, bsize.y); gc.copyArea(image, 0, 0); gc.dispose(); - s.close(); - return image; + shell.close(); + + ImageData imageData = image.getImageData(); + imageData.transparentPixel = imageData.palette.getPixel(greenScreen.getRGB()); + + image.dispose(); + greenScreen.dispose(); + + return new Image(display, imageData); } - /** {@inheritDoc} */ - @Override - public Image getImage(Object element) { - if(isEnabled(element)) { - if(isChecked(element)) { - return getImageRegistry().get(CHECKED_KEY); - } - return getImageRegistry().get(UNCHECKED_KEY); + /** + * Returns an {@link Image} representing the checkbox. + * + * @param checked + * Flag if the checkbox is checked. + * @param enabled + * Flag if the checkbox is enabled. + * + * @return {@link Image} representing the checkbox. + */ + public static Image getImage(boolean checked, boolean enabled) { + ImageRegistry imgReg = getImageRegistry(); + if(imgReg.getDescriptor(CHECKED_KEY) == null) { + imgReg.put(UNCHECKED_KEY, makeShot(false, true)); + imgReg.put(CHECKED_KEY, makeShot(true, true)); + imgReg.put(DISABLED_UNCHECKED_KEY, makeShot(false, false)); + imgReg.put(DISABLED_CHECKED_KEY, makeShot(true, false)); } - if(isChecked(element)) { - return getImageRegistry().get(DISABLED_CHECKED_KEY); + + if(enabled) { + return checked ? imgReg.get(CHECKED_KEY) : imgReg.get(UNCHECKED_KEY); } - return getImageRegistry().get(DISABLED_UNCHECKED_KEY); + + return checked ? imgReg.get(DISABLED_CHECKED_KEY) : imgReg.get(DISABLED_UNCHECKED_KEY); } /** {@inheritDoc} */ @Override - public String getText(Object element) { - return ""; + public Image getImage(Object element) { + return getImage(isChecked(element), isEnabled(element)); } /** Tests the model objects checked state. */