blob: 174de42e8ddba5ec3ce09912dd2fc290f1a5fa79 [file] [log] [blame]
package org.eclipse.swt.examples.paint;
/*
* (c) Copyright IBM Corp. 2000, 2002.
* This file is made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*/
import org.eclipse.jface.action.*;
import org.eclipse.jface.resource.*;
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.*;
import org.eclipse.ui.part.*;
import java.net.*;
import java.util.*;
/**
* The view for the paint application.
* All rendering happens inside the area created by createPartControl().
*
* @see ViewPart
*/
public class PaintView extends ViewPart {
private Display workbenchDisplay;
// current active settings
private ToolSettings toolSettings;
// paint surface for drawing
private PaintSurface paintSurface;
// map action ids to useful data
private HashMap /* of String to PaintTool */ paintToolMap;
private HashMap /* of String to Integer */ paintFillTypeMap;
private HashMap /* of String to Integer */ paintLineStyleMap;
/** UI data **/
// handle of currently active tool IAction on the UI
private IAction activeToolAction;
// handle of currently active filltype IAction on the UI
private IAction activeFillTypeAction;
// handle of currently active linetype IAction on the UI
private IAction activeLineStyleAction;
// handle of active foreground color box Canvas widget
private Canvas activeForegroundColorCanvas;
// handle of active background color box Canvas widget
private Canvas activeBackgroundColorCanvas;
private static final int numPaletteRows = 3;
private static final int numPaletteCols = 50;
// shared data
private Color paintColorBlack, paintColorWhite; // alias for paintColors[0] and [1]
private Color[] paintColors;
private Font paintDefaultFont; // do not free
/**
* Constructs a Paint view.
*/
public PaintView() {
}
/**
* Cleanup
*/
public void dispose() {
if (paintSurface != null) paintSurface.dispose();
if (paintColors != null) {
for (int i = 0; i < paintColors.length; ++i) {
final Color color = paintColors[i];
if (color != null) color.dispose();
}
}
paintDefaultFont = null;
paintColors = null;
paintSurface = null;
super.dispose();
}
/**
* Called when we must grab focus.
*
* @see org.eclipse.ui.part.ViewPart#setFocus
*/
public void setFocus() {
paintSurface.setFocus();
}
/**
* Creates the example.
*
* @see ViewPart#createPartControl
*/
public void createPartControl(Composite parent) {
/*** Initialize shared data ***/
workbenchDisplay = parent.getDisplay();
paintColorWhite = new Color(workbenchDisplay, 255, 255, 255);
paintColorBlack = new Color(workbenchDisplay, 0, 0, 0);
paintDefaultFont = workbenchDisplay.getSystemFont();
paintColors = new Color[numPaletteCols * numPaletteRows];
paintColors[0] = paintColorBlack;
paintColors[1] = paintColorWhite;
for (int i = 2; i < paintColors.length; i++) {
paintColors[i] = new Color(workbenchDisplay,
((i*7)%255),((i*23)%255), ((i*51)%255));
}
toolSettings = new ToolSettings();
toolSettings.commonForegroundColor = paintColorBlack;
toolSettings.commonBackgroundColor = paintColorWhite;
toolSettings.commonFont = paintDefaultFont;
/*** Add toolbar contributions ***/
final IActionBars actionBars = getViewSite().getActionBars();
IToolBarManager toolbarManager = actionBars.getToolBarManager();
toolbarManager.add(new GroupMarker("group.tools"));
toolbarManager.appendToGroup("group.tools", new SelectPaintToolAction("tool.Pencil"));
toolbarManager.appendToGroup("group.tools", new SelectPaintToolAction("tool.Airbrush"));
toolbarManager.appendToGroup("group.tools", new SelectPaintToolAction("tool.Line"));
toolbarManager.appendToGroup("group.tools", new SelectPaintToolAction("tool.PolyLine"));
toolbarManager.appendToGroup("group.tools", new SelectPaintToolAction("tool.Rectangle"));
toolbarManager.appendToGroup("group.tools", new SelectPaintToolAction("tool.RoundedRectangle"));
toolbarManager.appendToGroup("group.tools", new SelectPaintToolAction("tool.Ellipse"));
toolbarManager.appendToGroup("group.tools", new SelectPaintToolAction("tool.Text"));
toolbarManager.add(new Separator());
toolbarManager.add(new GroupMarker("group.options.fill"));
toolbarManager.appendToGroup("group.options.fill", new SelectFillTypeAction("fill.None"));
toolbarManager.appendToGroup("group.options.fill", new SelectFillTypeAction("fill.Outline"));
toolbarManager.appendToGroup("group.options.fill", new SelectFillTypeAction("fill.Solid"));
toolbarManager.add(new Separator());
toolbarManager.add(new GroupMarker("group.options.linestyle"));
toolbarManager.appendToGroup("group.options.linestyle", new SelectLineStyleAction("linestyle.Solid"));
toolbarManager.appendToGroup("group.options.linestyle", new SelectLineStyleAction("linestyle.Dash"));
toolbarManager.appendToGroup("group.options.linestyle", new SelectLineStyleAction("linestyle.Dot"));
toolbarManager.appendToGroup("group.options.linestyle", new SelectLineStyleAction("linestyle.DashDot"));
toolbarManager.add(new Separator());
toolbarManager.add(new GroupMarker("group.options"));
toolbarManager.appendToGroup("group.options", new SelectFontAction("options.Font"));
actionBars.updateActionBars();
/*** Build GUI ***/
createGUI(parent);
/*** Set defaults ***/
setPaintToolByID("tool.Pencil");
setFillTypeByID("fill.None");
setLineStyleByID("linestyle.Solid");
setForegroundColor(paintColorBlack);
setBackgroundColor(paintColorWhite);
}
/**
* Creates the GUI.
*/
private void createGUI(Composite parent) {
GridLayout gridLayout;
GridData gridData;
/*** Create principal GUI layout elements ***/
Composite displayArea = new Composite(parent, SWT.NONE);
gridLayout = new GridLayout();
gridLayout.numColumns = 1;
displayArea.setLayout(gridLayout);
// Creating these elements here avoids the need to instantiate the GUI elements
// in strict layout order. The natural layout ordering is an artifact of using
// SWT layouts, but unfortunately it is not the same order as that required to
// instantiate all of the non-GUI application elements to satisfy referential
// dependencies. It is possible to reorder the initialization to some extent, but
// this can be very tedious.
// paint canvas
final Canvas paintCanvas = new Canvas(displayArea, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL |
SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND);
gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
paintCanvas.setLayoutData(gridData);
paintCanvas.setBackground(paintColorWhite);
// color selector frame
final Composite colorFrame = new Composite(displayArea, SWT.NONE);
gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL);
colorFrame.setLayoutData(gridData);
// tool settings frame
final Composite toolSettingsFrame = new Composite(displayArea, SWT.NONE);
gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL);
toolSettingsFrame.setLayoutData(gridData);
// status text
final Text statusText = new Text(displayArea, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);
gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL);
statusText.setLayoutData(gridData);
/*** Create the remaining application elements inside the principal GUI layout elements ***/
// paintSurface
paintSurface = new PaintSurface(paintCanvas, statusText, paintColorWhite);
// paintToolMap
paintToolMap = new HashMap();
paintToolMap.put("tool.Pencil", new PencilTool(toolSettings, paintSurface));
paintToolMap.put("tool.Airbrush", new AirbrushTool(toolSettings, paintSurface));
paintToolMap.put("tool.Line", new LineTool(toolSettings, paintSurface));
paintToolMap.put("tool.PolyLine", new PolyLineTool(toolSettings, paintSurface));
paintToolMap.put("tool.Rectangle", new RectangleTool(toolSettings, paintSurface));
paintToolMap.put("tool.RoundedRectangle", new RoundedRectangleTool(toolSettings, paintSurface));
paintToolMap.put("tool.Ellipse", new EllipseTool(toolSettings, paintSurface));
paintToolMap.put("tool.Text", new TextTool(toolSettings, paintSurface));
paintToolMap.put("tool.Null", null);
// paintFillTypeMap
paintFillTypeMap = new HashMap();
paintFillTypeMap.put("fill.None", new Integer(ToolSettings.ftNone));
paintFillTypeMap.put("fill.Outline", new Integer(ToolSettings.ftOutline));
paintFillTypeMap.put("fill.Solid", new Integer(ToolSettings.ftSolid));
// paintLineStyleMap
paintLineStyleMap = new HashMap();
paintLineStyleMap.put("linestyle.Solid", new Integer(SWT.LINE_SOLID));
paintLineStyleMap.put("linestyle.Dash", new Integer(SWT.LINE_DASH));
paintLineStyleMap.put("linestyle.Dot", new Integer(SWT.LINE_DOT));
paintLineStyleMap.put("linestyle.DashDot", new Integer(SWT.LINE_DASHDOT));
// colorFrame
gridLayout = new GridLayout();
gridLayout.numColumns = 3;
gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0;
colorFrame.setLayout(gridLayout);
// activeForegroundColorCanvas, activeBackgroundColorCanvas
activeForegroundColorCanvas = new Canvas(colorFrame, SWT.BORDER);
gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gridData.heightHint = 24;
gridData.widthHint = 24;
activeForegroundColorCanvas.setLayoutData(gridData);
activeBackgroundColorCanvas = new Canvas(colorFrame, SWT.BORDER);
gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gridData.heightHint = 24;
gridData.widthHint = 24;
activeBackgroundColorCanvas.setLayoutData(gridData);
// paletteCanvas
final Canvas paletteCanvas = new Canvas(colorFrame, SWT.BORDER | SWT.NO_BACKGROUND);
gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.heightHint = 24;
paletteCanvas.setLayoutData(gridData);
paletteCanvas.addListener(SWT.MouseDown, new Listener() {
public void handleEvent(Event e) {
Rectangle bounds = paletteCanvas.getClientArea();
Color color = getColorAt(bounds, e.x, e.y);
if (e.button == 1) setForegroundColor(color);
else setBackgroundColor(color);
}
private Color getColorAt(Rectangle bounds, int x, int y) {
if (bounds.height <= 1 && bounds.width <= 1) return paintColorWhite;
final int row = (y - bounds.y) * numPaletteRows / bounds.height;
final int col = (x - bounds.x) * numPaletteCols / bounds.width;
return paintColors[Math.min(Math.max(row * numPaletteCols + col, 0), paintColors.length - 1)];
}
});
Listener refreshListener = new Listener() {
public void handleEvent(Event e) {
if (e.gc == null) return;
Rectangle bounds = paletteCanvas.getClientArea();
for (int row = 0; row < numPaletteRows; ++row) {
for (int col = 0; col < numPaletteCols; ++col) {
final int x = bounds.width * col / numPaletteCols;
final int y = bounds.height * row / numPaletteRows;
final int width = Math.max(bounds.width * (col + 1) / numPaletteCols - x, 1);
final int height = Math.max(bounds.height * (row + 1) / numPaletteRows - y, 1);
e.gc.setBackground(paintColors[row * numPaletteCols + col]);
e.gc.fillRectangle(bounds.x + x, bounds.y + y, width, height);
}
}
}
};
paletteCanvas.addListener(SWT.Resize, refreshListener);
paletteCanvas.addListener(SWT.Paint, refreshListener);
//paletteCanvas.redraw();
// toolSettingsFrame
gridLayout = new GridLayout();
gridLayout.numColumns = 4;
gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0;
toolSettingsFrame.setLayout(gridLayout);
Label label = new Label(toolSettingsFrame, SWT.NONE);
label.setText(PaintPlugin.getResourceString("settings.AirbrushRadius.text"));
final Scale airbrushRadiusScale = new Scale(toolSettingsFrame, SWT.HORIZONTAL);
airbrushRadiusScale.setMinimum(5);
airbrushRadiusScale.setMaximum(50);
airbrushRadiusScale.setSelection(toolSettings.airbrushRadius);
airbrushRadiusScale.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
airbrushRadiusScale.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
toolSettings.airbrushRadius = airbrushRadiusScale.getSelection();
updateToolSettings();
}
});
label = new Label(toolSettingsFrame, SWT.NONE);
label.setText(PaintPlugin.getResourceString("settings.AirbrushIntensity.text"));
final Scale airbrushIntensityScale = new Scale(toolSettingsFrame, SWT.HORIZONTAL);
airbrushIntensityScale.setMinimum(1);
airbrushIntensityScale.setMaximum(100);
airbrushIntensityScale.setSelection(toolSettings.airbrushIntensity);
airbrushIntensityScale.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
airbrushIntensityScale.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
toolSettings.airbrushIntensity = airbrushIntensityScale.getSelection();
updateToolSettings();
}
});
}
/**
* Notifies the tool that its settings have changed.
*/
private void updateToolSettings() {
final PaintTool activePaintTool = paintSurface.getPaintTool();
if (activePaintTool == null) return;
activePaintTool.endSession();
activePaintTool.set(toolSettings);
activePaintTool.beginSession();
}
/**
* Sets the tool foreground color.
*
* @param color the new color to use
*/
public void setForegroundColor(Color color) {
if (activeForegroundColorCanvas != null)
activeForegroundColorCanvas.setBackground(color);
toolSettings.commonForegroundColor = color;
updateToolSettings();
}
/**
* Set the tool background color.
*
* @param color the new color to use
*/
public void setBackgroundColor(Color color) {
if (activeBackgroundColorCanvas != null)
activeBackgroundColorCanvas.setBackground(color);
toolSettings.commonBackgroundColor = color;
updateToolSettings();
}
/**
* Selects a tool given its ID.
*/
public void setPaintToolByID(String id) {
activeToolAction = handleRadioAction(activeToolAction, id);
final PaintTool paintTool = (PaintTool) paintToolMap.get(id);
paintSurface.setPaintSession(paintTool);
updateToolSettings();
}
/**
* Selects a filltype given its ID.
*/
public void setFillTypeByID(String id) {
activeFillTypeAction = handleRadioAction(activeFillTypeAction, id);
final Integer fillType = (Integer) paintFillTypeMap.get(id);
toolSettings.commonFillType = fillType.intValue();
updateToolSettings();
}
/**
* Selects line type given its ID.
*/
public void setLineStyleByID(String id) {
activeLineStyleAction = handleRadioAction(activeLineStyleAction, id);
final Integer lineType = (Integer) paintLineStyleMap.get(id);
toolSettings.commonLineStyle = lineType.intValue();
updateToolSettings();
}
/**
* Gets the IAction for an ID belonging to a set of mutually exclusive actions, and
* toggles the old action off if necessary.
*/
private IAction handleRadioAction(IAction oldAction, String id) {
IAction action = getActionByID(id);
if (action != null) {
if (oldAction != null) oldAction.setChecked(false);
if (! action.isChecked()) action.setChecked(true);
return action;
}
return oldAction;
}
/**
* Gets the IAction representing the UI toolbar button with the specified ID.
*/
private IAction getActionByID(String id) {
final IActionBars actionBars = getViewSite().getActionBars();
IToolBarManager toolbarManager = actionBars.getToolBarManager();
ActionContributionItem contributionItem = (ActionContributionItem) toolbarManager.find(id);
if (contributionItem == null) return null;
return contributionItem.getAction();
}
/**
* Returns the Display.
*
* @return the display we're using
*/
public Display getDisplay() {
return workbenchDisplay;
}
/**
* Action set glue.
*/
abstract class PaintAction extends Action {
public PaintAction(String id) {
super();
setId(id);
try {
final URL installUrl = PaintPlugin.getDefault().getDescriptor().getInstallURL();
final URL imageUrl = new URL(installUrl, PaintPlugin.getResourceString(id + ".image"));
setImageDescriptor(ImageDescriptor.createFromURL(imageUrl));
} catch (MalformedURLException e) {
PaintPlugin.logError("", e);
}
setText(PaintPlugin.getResourceString(id + ".label"));
setToolTipText(PaintPlugin.getResourceString(id + ".tooltip"));
setDescription(PaintPlugin.getResourceString(id + ".description"));
}
}
class SelectPaintToolAction extends PaintAction {
public SelectPaintToolAction(String id) { super(id); }
public int getStyle() { return IAction.AS_CHECK_BOX; }
public void run() { setPaintToolByID(getId()); }
}
class SelectFillTypeAction extends PaintAction {
public SelectFillTypeAction(String id) { super(id); }
public int getStyle() { return IAction.AS_CHECK_BOX; }
public void run() { setFillTypeByID(getId()); }
}
class SelectLineStyleAction extends PaintAction {
public SelectLineStyleAction(String id) { super(id); }
public int getStyle() { return IAction.AS_CHECK_BOX; }
public void run() { setLineStyleByID(getId()); }
}
class SelectFontAction extends PaintAction {
public SelectFontAction(String id) { super(id); }
public int getStyle() { return IAction.AS_PUSH_BUTTON; }
public void run() {
FontDialog fontDialog = new FontDialog(paintSurface.getShell(), SWT.PRIMARY_MODAL);
FontData[] fontDatum = toolSettings.commonFont.getFontData();
if (fontDatum != null && fontDatum.length > 0) {
fontDialog.setFontData(fontDatum[0]);
}
fontDialog.setText(PaintPlugin.getResourceString("options.Font.dialog.title"));
paintSurface.hideRubberband();
FontData fontData = fontDialog.open();
paintSurface.showRubberband();
if (fontData != null) {
try {
Font font = new Font(workbenchDisplay, fontData);
toolSettings.commonFont = font;
updateToolSettings();
} catch (SWTException e) {
}
}
}
}
}