/******************************************************************************* * Copyright (c) 2000, 2006 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 Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.examples.graphics; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashSet; import java.util.MissingResourceException; import java.util.ResourceBundle; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Path; import org.eclipse.swt.graphics.Pattern; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.Resource; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Sash; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; /** * This class is the main class of the graphics application. Various "tabs" are created and made visible by this class. */ public class GraphicsExample { static boolean advanceGraphics, advanceGraphicsInit; static final int MARGIN = 5; static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle("examples_graphics"); //$NON-NLS-1$ static final int SASH_SPACING = 1; static final int TIMER = 30; public static void main(String[] args) { Display display = new Display(); Shell shell = new GraphicsExample().open(display); while (shell != null && !shell.isDisposed()) if (!display.readAndDispatch()) display.sleep(); display.dispose(); } /** * Creates an image based on the color provided and returns it. * * @param device - * The Device * @param color - * The color used to create the image */ static Image createImage(Device device, Color color) { Image image = new Image(device, 16, 16); GC gc = new GC(image); gc.setBackground(color); Rectangle rect = image.getBounds(); gc.fillRectangle(rect); if (color.equals(device.getSystemColor(SWT.COLOR_BLACK))) gc.setForeground(device.getSystemColor(SWT.COLOR_WHITE)); gc.drawRectangle(rect.x, rect.y, rect.width - 1, rect.height - 1); gc.dispose(); return image; } /** * Creates an image based on a gradient pattern made up of two colors. * * @param device - * The Device * @param color1 - * The first color used to create the image * @param color2 - * The second color used to create the image */ static Image createImage(Device device, Color color1, Color color2, int width, int height) { Image image = new Image(device, width, height); GC gc = new GC(image); Rectangle rect = image.getBounds(); Pattern pattern = new Pattern(device, rect.x, rect.y, rect.width - 1, rect.height - 1, color1, color2); gc.setBackgroundPattern(pattern); gc.fillRectangle(rect); gc.drawRectangle(rect.x, rect.y, rect.width - 1, rect.height - 1); gc.dispose(); pattern.dispose(); return image; } /** * Creates and returns a thumbnail image. * * @param device * a device * @param name * filename of the image */ static Image createThumbnail(Device device, String name) { Image image = new Image(device, name); Rectangle src = image.getBounds(); Image result = null; if (src.width != 16 || src.height != 16) { result = new Image(device, 16, 16); GC gc = new GC(result); Rectangle dest = result.getBounds(); gc.drawImage(image, src.x, src.y, src.width, src.height, dest.x, dest.y, dest.width, dest.height); gc.dispose(); } if (result != null) { image.dispose(); return result; } return image; } /** * Gets a string from the resource bundle. We don't want to crash because of a missing String. Returns the key if * not found. */ static String getResourceString(String key) { try { return GraphicsExample.RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return key; } catch (NullPointerException e) { return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$ } } static Image loadImage(Device device, Class clazz, String string) { InputStream stream = clazz.getResourceAsStream(string); if (stream == null) return null; Image image = null; try { image = new Image(device, stream); } catch (SWTException ex) { } finally { try { stream.close(); } catch (IOException ex) { } } return image; } // GraphicsTabs in // the order that // they appear in // the tree boolean animate = true; // whether animation // should happen GraphicsBackground background; // used to store // information about the // background ToolItem backItem, dbItem; // background, // double buffer // items Menu backMenu; // background menu // item Canvas canvas; // widget that // displays a tab // description Sash hSash, vSash; Composite parent; ArrayList resources; // stores resources // in the // application GraphicsTab tab; // the current tab Composite tabControlPanel; // tabs Text tabDesc; // multi-line text // contains backItem // and dbItem Tree tabList; // tree structure of GraphicsTab[] tabs; // tabs to be found // that will be // disposed ArrayList tabs_in_order; // stores ToolBar toolBar; // toolbar that /* * Default constructor is needed so that example launcher can create an instance. */ public GraphicsExample() { super(); } public GraphicsExample(final Composite parent) { this.parent = parent; resources = new ArrayList(); createControls(parent); setTab(tab); startAnimationTimer(); } /** * Disposes all resources created by the receiver. */ public void dispose() { if (tabs != null) for (int i = 0; i < tabs.length; i++) { GraphicsTab tab = tabs[i]; tab.dispose(); } tabs = null; if (resources != null) for (int i = 0; i < resources.size(); i++) if (resources.get(i) instanceof Resource) ((Resource) resources.get(i)).dispose(); resources = null; if (backMenu != null) { backMenu.dispose(); backMenu = null; } } /** * Gets the current tab. */ public GraphicsTab getTab() { return tab; } public Shell open(final Display display) { Shell shell = new Shell(display); shell.setText(GraphicsExample.getResourceString("AdvancedGraphics")); //$NON-NLS-1$ final GraphicsExample example = new GraphicsExample(shell); shell.addListener(SWT.Close, new Listener() { public void handleEvent(Event event) { example.dispose(); } }); shell.open(); return shell; } /** * Redraws the current tab. */ public void redraw() { canvas.redraw(); } /** * Sets wheter the canvas is double buffered or not. */ public void setDoubleBuffered(boolean doubleBuffered) { dbItem.setSelection(doubleBuffered); recreateCanvas(); } /** * Grabs input focus. */ public void setFocus() { tabList.setFocus(); } /** * Sets the current tab. */ public void setTab(GraphicsTab tab) { Control[] children = tabControlPanel.getChildren(); for (int i = 0; i < children.length; i++) { Control control = children[i]; control.dispose(); } if (this.tab != null) this.tab.dispose(); this.tab = tab; if (tab != null) { setDoubleBuffered(tab.getDoubleBuffered()); tab.createControlPanel(tabControlPanel); tabDesc.setText(tab.getDescription()); } else tabDesc.setText(""); FormData data = (FormData) tabControlPanel.getLayoutData(); children = tabControlPanel.getChildren(); if (children.length != 0) data.top = null; else data.top = new FormAttachment(100, -GraphicsExample.MARGIN); parent.layout(true, true); if (tab != null) { TreeItem[] selection = tabList.getSelection(); if (selection.length == 0 || selection[0].getData() != tab) { TreeItem item = findItemByData(tabList.getItems(), tab); if (item != null) tabList.setSelection(new TreeItem[] { item }); } } canvas.redraw(); } boolean checkAdvancedGraphics() { if (GraphicsExample.advanceGraphicsInit) return GraphicsExample.advanceGraphics; GraphicsExample.advanceGraphicsInit = true; Display display = parent.getDisplay(); try { Path path = new Path(display); path.dispose(); } catch (SWTException e) { Shell shell = display.getActiveShell(), newShell = null; if (shell == null) shell = newShell = new Shell(display); MessageBox dialog = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK); dialog.setText(GraphicsExample.RESOURCE_BUNDLE.getString("Warning")); //$NON-NLS-1$ dialog.setMessage(GraphicsExample.RESOURCE_BUNDLE.getString("LibNotFound")); //$NON-NLS-1$ dialog.open(); if (newShell != null) newShell.dispose(); return false; } return GraphicsExample.advanceGraphics = true; } void createCanvas(Composite parent) { int style = SWT.NO_BACKGROUND; if (dbItem.getSelection()) style |= SWT.DOUBLE_BUFFERED; canvas = new Canvas(parent, style); canvas.addListener(SWT.Paint, new Listener() { public void handleEvent(Event event) { GC gc = event.gc; Rectangle rect = canvas.getClientArea(); Device device = gc.getDevice(); Pattern pattern = null; if (background.getBgColor1() != null) { if (background.getBgColor2() != null) { // gradient pattern = new Pattern(device, 0, 0, rect.width, rect.height, background.getBgColor1(), background.getBgColor2()); gc.setBackgroundPattern(pattern); } else gc.setBackground(background.getBgColor1()); } else if (background.getBgImage() != null) { // image pattern = new Pattern(device, background.getBgImage()); gc.setBackgroundPattern(pattern); } gc.fillRectangle(rect); GraphicsTab tab = getTab(); if (tab != null) tab.paint(gc, rect.width, rect.height); if (pattern != null) pattern.dispose(); } }); } /** * Creates the control panel * * @param parent */ void createControlPanel(Composite parent) { Group group; tabControlPanel = group = new Group(parent, SWT.NONE); group.setText(GraphicsExample.getResourceString("Settings")); //$NON-NLS-1$ tabControlPanel.setLayout(new RowLayout()); } void createControls(final Composite parent) { tabs = createTabs(); createToolBar(parent); createTabList(parent); hSash = new Sash(parent, SWT.HORIZONTAL); createTabDesc(parent); vSash = new Sash(parent, SWT.VERTICAL); createCanvas(parent); createControlPanel(parent); FormData data; FormLayout layout = new FormLayout(); parent.setLayout(layout); data = new FormData(); data.left = new FormAttachment(0, GraphicsExample.MARGIN); data.top = new FormAttachment(0, GraphicsExample.MARGIN); data.right = new FormAttachment(100, -GraphicsExample.MARGIN); toolBar.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0, GraphicsExample.MARGIN); data.top = new FormAttachment(toolBar, GraphicsExample.MARGIN); data.right = new FormAttachment(vSash, -GraphicsExample.SASH_SPACING); data.bottom = new FormAttachment(hSash, -GraphicsExample.SASH_SPACING); tabList.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0, GraphicsExample.MARGIN); int offset = parent.getBounds().height - tabDesc.computeSize(SWT.DEFAULT, tabDesc.getLineHeight() * 10).y; data.top = new FormAttachment(null, offset); data.right = new FormAttachment(vSash, -GraphicsExample.SASH_SPACING); hSash.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(0, GraphicsExample.MARGIN); data.top = new FormAttachment(hSash, GraphicsExample.SASH_SPACING); data.right = new FormAttachment(vSash, -GraphicsExample.SASH_SPACING); data.bottom = new FormAttachment(100, -GraphicsExample.MARGIN); tabDesc.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(null, tabList.computeSize(SWT.DEFAULT, SWT.DEFAULT).x + 50); data.top = new FormAttachment(toolBar, GraphicsExample.MARGIN); data.bottom = new FormAttachment(100, -GraphicsExample.MARGIN); vSash.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(vSash, GraphicsExample.SASH_SPACING); data.top = new FormAttachment(toolBar, GraphicsExample.MARGIN); data.right = new FormAttachment(100, -GraphicsExample.MARGIN); data.bottom = new FormAttachment(tabControlPanel); canvas.setLayoutData(data); data = new FormData(); data.left = new FormAttachment(vSash, GraphicsExample.SASH_SPACING); data.right = new FormAttachment(100, -GraphicsExample.MARGIN); data.bottom = new FormAttachment(100, -GraphicsExample.MARGIN); tabControlPanel.setLayoutData(data); vSash.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { Rectangle rect = hSash.getParent().getClientArea(); event.x = Math.min(Math.max(event.x, 60), rect.width - 60); System.out.println(event.x); if (event.detail != SWT.DRAG) { FormData data = (FormData) vSash.getLayoutData(); data.left.offset = event.x; parent.layout(true); animate = true; } else animate = false; } }); hSash.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { Rectangle rect = vSash.getParent().getClientArea(); event.y = Math.min(Math.max(event.y, tabList.getLocation().y + 60), rect.height - 60); if (event.detail != SWT.DRAG) { FormData data = (FormData) hSash.getLayoutData(); data.top.offset = event.y; parent.layout(true); } } }); } /** * Creates the multi-line text widget that will contain the tab description. */ void createTabDesc(Composite parent) { tabDesc = new Text(parent, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.WRAP | SWT.BORDER); tabDesc.setEditable(false); tabDesc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE)); } void createTabList(Composite parent) { tabList = new Tree(parent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); Arrays.sort(tabs, new Comparator() { public int compare(Object tab0, Object tab1) { return ((GraphicsTab) tab0).getText().compareTo(((GraphicsTab) tab1).getText()); } }); HashSet set = new HashSet(); for (int i = 0; i < tabs.length; i++) { GraphicsTab tab = tabs[i]; set.add(tab.getCategory()); } String[] categories = new String[set.size()]; set.toArray(categories); Arrays.sort(categories); for (int i = 0; i < categories.length; i++) { String text = categories[i]; TreeItem item = new TreeItem(tabList, SWT.NONE); item.setText(text); } tabs_in_order = new ArrayList(); TreeItem[] items = tabList.getItems(); for (int i = 0; i < items.length; i++) { TreeItem item = items[i]; for (int j = 0; j < tabs.length; j++) { GraphicsTab tab = tabs[j]; if (item.getText().equals(tab.getCategory())) { TreeItem item1 = new TreeItem(item, SWT.NONE); item1.setText(tab.getText()); item1.setData(tab); tabs_in_order.add(tab); } } } tabList.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { TreeItem item = (TreeItem) event.item; if (item != null) { GraphicsTab gt = (GraphicsTab) item.getData(); if (gt == tab) return; setTab((GraphicsTab) item.getData()); } } }); } /** * Initializes the GraphicsTab instances that will be contained in GraphicsExample. */ GraphicsTab[] createTabs() { return new GraphicsTab[] { new LineTab(this), new StarPolyTab(this), tab = new IntroTab(this), new BlackHoleTab(this), new AlphaTab(this), new BallTab(this), new CountDownTab(this), new CurvesSWTTab(this), new CurvesTab(this), new CustomFontTab(this), new FontBounceTab(this), new GradientTab(this), new ImageTransformTab(this), new ShapesTab(this), new MazeTab(this), new RGBTab(this), new SpiralTab(this), new CardsTab(this), new LineCapTab(this), new InterpolationTab(this), new PathClippingTab(this), new PathClippingAnimTab(this), new LineStyleTab(this), new LineJoinTab(this), new RegionClippingTab(this), new CustomAlphaTab(this), new TextAntialiasTab(this), new GraphicAntialiasTab(this), new ImageFlipTab(this), new PathTab(this), }; } void createToolBar(final Composite parent) { final Display display = parent.getDisplay(); toolBar = new ToolBar(parent, SWT.FLAT); ToolItem back = new ToolItem(toolBar, SWT.PUSH); back.setText(GraphicsExample.getResourceString("Back")); //$NON-NLS-1$ back.setImage(loadImage(display, "back.gif")); //$NON-NLS-1$ back.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { int index = tabs_in_order.indexOf(tab) - 1; if (index < 0) index = tabs_in_order.size() - 1; setTab((GraphicsTab) tabs_in_order.get(index)); } }); ToolItem next = new ToolItem(toolBar, SWT.PUSH); next.setText(GraphicsExample.getResourceString("Next")); //$NON-NLS-1$ next.setImage(loadImage(display, "next.gif")); //$NON-NLS-1$ next.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { int index = (tabs_in_order.indexOf(tab) + 1) % tabs_in_order.size(); setTab((GraphicsTab) tabs_in_order.get(index)); } }); ColorMenu colorMenu = new ColorMenu(); // setup items to be contained in the background menu colorMenu.setColorItems(true); colorMenu.setPatternItems(checkAdvancedGraphics()); colorMenu.setGradientItems(checkAdvancedGraphics()); // create the background menu backMenu = colorMenu.createMenu(parent, new ColorListener() { public void setColor(GraphicsBackground gb) { background = gb; backItem.setImage(gb.getThumbNail()); if (canvas != null) canvas.redraw(); } }); // initialize the background to the first item in the menu background = (GraphicsBackground) backMenu.getItem(0).getData(); // background tool item backItem = new ToolItem(toolBar, SWT.PUSH); backItem.setText(GraphicsExample.getResourceString("Background")); //$NON-NLS-1$ backItem.setImage(background.getThumbNail()); backItem.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { if (event.widget == backItem) { final ToolItem toolItem = (ToolItem) event.widget; final ToolBar toolBar = toolItem.getParent(); Rectangle toolItemBounds = toolItem.getBounds(); Point point = toolBar.toDisplay(new Point(toolItemBounds.x, toolItemBounds.y)); backMenu.setLocation(point.x, point.y + toolItemBounds.height); backMenu.setVisible(true); } } }); // double buffer tool item dbItem = new ToolItem(toolBar, SWT.CHECK); dbItem.setText(GraphicsExample.getResourceString("DoubleBuffer")); //$NON-NLS-1$ dbItem.setImage(loadImage(display, "db.gif")); //$NON-NLS-1$ dbItem.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { setDoubleBuffered(dbItem.getSelection()); } }); } TreeItem findItemByData(TreeItem[] items, Object data) { for (int i = 0; i < items.length; i++) { TreeItem item = items[i]; if (item.getData() == data) return item; item = findItemByData(item.getItems(), data); if (item != null) return item; } return null; } Image loadImage(Device device, String name) { Image image = GraphicsExample.loadImage(device, GraphicsExample.class, name); if (image != null) resources.add(image); return image; } void recreateCanvas() { if (dbItem.getSelection() == ((canvas.getStyle() & SWT.DOUBLE_BUFFERED) != 0)) return; Object data = canvas.getLayoutData(); if (canvas != null) canvas.dispose(); createCanvas(parent); canvas.setLayoutData(data); parent.layout(true, true); } /** * Starts the animation if the animate flag is set. */ void startAnimationTimer() { final Display display = parent.getDisplay(); display.timerExec(GraphicsExample.TIMER, new Runnable() { public void run() { if (canvas.isDisposed()) return; int timeout = GraphicsExample.TIMER; GraphicsTab tab = getTab(); if (tab instanceof AnimatedGraphicsTab) { AnimatedGraphicsTab animTab = (AnimatedGraphicsTab) tab; if (animate && animTab.getAnimation()) { Rectangle rect = canvas.getClientArea(); animTab.next(rect.width, rect.height); canvas.redraw(); canvas.update(); } timeout = animTab.getAnimationTime(); } display.timerExec(timeout, this); } }); } }