package com.aptana.ide.editor.css.toolbar;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import com.aptana.ide.core.IdeLog;
import com.aptana.ide.editor.css.CSSPlugin;
import com.aptana.ide.editors.toolbar.IToolBarMember;
import com.aptana.ide.editors.unified.IUnifiedEditor;
public class EyeDropper implements IToolBarMember
{
protected int lastX;
protected int lastY;
public void execute(IUnifiedEditor editor, String string)
{
ITextSelection sel = (ITextSelection) editor.getViewer().getSelectionProvider().getSelection();
if (sel.isEmpty())
return;
try
{
String replacement = getUserColor();
if (replacement == null)
return;
int offset = sel.getOffset();
int len = sel.getLength();
IDocument doc = editor.getDocumentProvider().getDocument(editor.getEditorInput());
doc.replace(offset, len, replacement);
}
catch (BadLocationException e)
{
IdeLog.logError(CSSPlugin.getDefault(), e.getMessage());
}
}
private String getUserColor()
{
final Display display = Display.getCurrent();
final Shell shell = new Shell(display, SWT.SYSTEM_MODAL | SWT.NO_TRIM | SWT.ON_TOP);
shell.setFullScreen(true);
final Rectangle rect = display.getPrimaryMonitor().getClientArea();
shell.setBounds(rect);
shell.setLocation(rect.x - 5, rect.y - 5);
shell.addTraverseListener(new TraverseListener()
{
public void keyTraversed(TraverseEvent event)
{
switch (event.detail)
{
case SWT.TRAVERSE_ESCAPE:
shell.close();
event.detail = SWT.TRAVERSE_NONE;
event.doit = false;
break;
}
}
});
shell.setLayout(new GridLayout(1, true));
final Canvas canvas = new Canvas(shell, SWT.NONE);
canvas.setLayoutData(new GridData(rect.width, rect.height));
final Image image = takeScreenshot(display, rect);
canvas.setBackgroundImage(image);
Image cursorImage = CSSPlugin.getImage("icons/eyedropper.gif"); //$NON-NLS-1$
ImageData cursordata = cursorImage.getImageData();
Cursor cursor = new Cursor(display, cursordata, 0, 15);
canvas.setCursor(cursor);
canvas.addMouseMoveListener(new MouseMoveListener()
{
public void mouseMove(MouseEvent e)
{
final int width = 50;
final int height = 50;
final int xOffset = 10;
final int yOffset = -10 - height;
// Tell canvas to redraw/repair the last place we drew
canvas.redraw(lastX + (xOffset - 1), lastY + (yOffset - 1), width + 2, height + 2, false);
canvas.update();
lastX = e.x;
lastY = e.y;
// As user moves mouse, draw a big box of the color they're hovering over up and to the right
RGB rgb = getColor(image, e);
Color bg = new Color(display, rgb);
// Set foreground to white/black depending on what hovered color is, so text is readable!
Color fg;
int total = rgb.blue + rgb.green + rgb.red;
if (total < 384)
{
fg = new Color(display, 255, 255, 255);
}
else
{
fg = new Color(display, 0, 0, 0);
}
GC gc = new GC(canvas);
gc.setBackground(bg);
gc.setForeground(fg);
// FIXME The drawing seems slow and "jerky" can we use something like double-buffering?
gc.drawRectangle(e.x + (xOffset - 1), e.y + (yOffset - 1), width + 1, height + 1);
gc.fillRectangle(e.x + xOffset, e.y + yOffset, width, width);
gc.drawString(toHex(rgb), e.x + xOffset, e.y + ((yOffset / 2) - 12));
bg.dispose();
fg.dispose();
gc.dispose();
// FIXME First time user uses eyedropper, it only draws this box so many times before it just stops
// doing so.
}
});
final String result[] = new String[1];
canvas.addMouseListener(new MouseListener()
{
public void mouseUp(MouseEvent e)
{
}
public void mouseDown(MouseEvent e)
{
RGB rgb = getColor(image, e);
result[0] = toHex(rgb);
image.dispose();
shell.close();
}
public void mouseDoubleClick(MouseEvent e)
{
}
});
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
cursor.dispose();
if (result[0] != null)
return "#" + result[0]; //$NON-NLS-1$
return null;
}
private Image takeScreenshot(final Display display, final Rectangle rect)
{
final Image snap = new Image(display, rect);
GC gc = new GC(display);
gc.copyArea(snap, 0, 0);
gc.dispose();
return snap;
}
private String toHex(RGB selectedcolor)
{
return twoDigitHex(selectedcolor.red) + twoDigitHex(selectedcolor.green) + twoDigitHex(selectedcolor.blue);
}
private String twoDigitHex(int color)
{
return pad(Integer.toHexString(color));
}
private String pad(String str)
{
if (str.length() == 0)
return "00"; //$NON-NLS-1$
if (str.length() == 1)
return "0" + str; //$NON-NLS-1$
else
return str;
}
protected RGB getColor(final Image image, MouseEvent e)
{
return getColor(image, e.x, e.y);
}
protected RGB getColor(final Image image, int x, int y)
{
int pixel = image.getImageData().getPixel(x, y);
return image.getImageData().palette.getRGB(pixel);
}
}