Introducing YippieMove '09. Easy email transfers. Now open for all destinations.
Dec
19.
Comments Off
Comments
Category: Uncategorized

Tom over at the eclipse-dev blog posted this useful snippet for putting native looking checkboxes in SWT JFace TableViewer tables. Unfortunately the checkboxes ended up with a gray background in OS X, as seen in the picture below.

Gray Checkbox Background
An unsightly gray checkbox background.

I came up with this hack to hack the hack to work.

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();
	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());

	return new Image(control.getDisplay(), imageData);
}

The result now looks like the picture below.

Normal Checkbox
It’s not pixel perfect but closer.

It’s based on Florian Potschka’s version of makeShot as found in the comments to the original post. Replacing your makeShot method with the one above makes the background of the checkbox transparent. It’s not perfect: we use a random near white background color as our ‘green screen’ color in order to get the right antialias color in the edges. But this will also make any pixels with exactly this color inside of the widget shine through. Hopefully there won’t be many. Given enough time somebody will add checkbox support to arbitrary table cells in SWT and this hack will be made obsolete.

Here’s the complete snippet (untested):

package de.fhmracing.glasseye.canexplorer.gui.transmit;

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.Point;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;

public abstract class EmulatedNativeCheckBoxLabelProvider extends
    ColumnLabelProvider {
  private static final String CHECKED_KEY = "CHECKED";
  private static final String UNCHECK_KEY = "UNCHECKED";

  public EmulatedNativeCheckBoxLabelProvider(ColumnViewer viewer) {
    if (JFaceResources.getImageRegistry().getDescriptor(CHECKED_KEY) == null) {
      JFaceResources.getImageRegistry().put(UNCHECK_KEY,
          makeShot(viewer.getControl(), false));
      JFaceResources.getImageRegistry().put(CHECKED_KEY,
          makeShot(viewer.getControl(), true));
    }
  }

  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();
    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());

    return new Image(control.getDisplay(), imageData);
  }

  public Image getImage(Object element) {
    if (isChecked(element)) {
      return JFaceResources.getImageRegistry().get(CHECKED_KEY);
    } else {
      return JFaceResources.getImageRegistry().get(UNCHECK_KEY);
    }
  }

  protected abstract boolean isChecked(Object element);
}

Hope it’ll help somebody.

Author: Tags: , , ,

© 2006-2009 WireLoad, LLC.
Logo photo by William Picard. Theme based on BlueMod © 2005 - 2009 FrederikM.de, based on blueblog_DE by Oliver Wunder.
Sitemap