| /******************************************************************************* |
| * Copyright (c) 2000, 2005 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.*; |
| import java.util.*; |
| |
| import org.eclipse.swt.*; |
| import org.eclipse.swt.graphics.*; |
| import org.eclipse.swt.layout.*; |
| import org.eclipse.swt.widgets.*; |
| |
| /** |
| * This class is the main class of the graphics application. Various "tabs" are |
| * created and made visible by this class. |
| */ |
| public class GraphicsExample { |
| |
| Composite parent; |
| GraphicsTab[] tabs; // tabs to be found in the application |
| GraphicsTab tab; // the current tab |
| GraphicsBackground background; // used to store information about the background |
| |
| ToolBar toolBar; // toolbar that contains backItem and dbItem |
| Tree tabList; // tree structure of tabs |
| Text tabDesc; // multi-line text widget that displays a tab description |
| Sash hSash, vSash; |
| Canvas canvas; |
| Composite tabControlPanel; |
| ToolItem backItem, dbItem; // background, double buffer items |
| Menu backMenu; // background menu item |
| |
| ArrayList resources; // stores resources that will be disposed |
| ArrayList tabs_in_order; // stores GraphicsTabs in the order that they appear in the tree |
| boolean animate = true; // whether animation should happen |
| |
| static boolean advanceGraphics, advanceGraphicsInit; |
| |
| static final int MARGIN = 5; |
| static final int SASH_SPACING = 1; |
| static final int TIMER = 30; |
| static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle("examples_graphics"); //$NON-NLS-1$ |
| |
| /* |
| * 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(); |
| } |
| |
| boolean checkAdvancedGraphics() { |
| if (advanceGraphicsInit) return advanceGraphics; |
| 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(RESOURCE_BUNDLE.getString("Warning")); //$NON-NLS-1$ |
| dialog.setMessage(RESOURCE_BUNDLE.getString("LibNotFound")); //$NON-NLS-1$ |
| dialog.open(); |
| if (newShell != null) newShell.dispose(); |
| return false; |
| } |
| return advanceGraphics = true; |
| } |
| |
| 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, MARGIN); |
| data.top = new FormAttachment(0, MARGIN); |
| data.right = new FormAttachment(100, -MARGIN); |
| toolBar.setLayoutData(data); |
| |
| data = new FormData(); |
| data.left = new FormAttachment(0, MARGIN); |
| data.top = new FormAttachment(toolBar, MARGIN); |
| data.right = new FormAttachment(vSash, -SASH_SPACING); |
| data.bottom = new FormAttachment(hSash, -SASH_SPACING); |
| tabList.setLayoutData(data); |
| |
| data = new FormData(); |
| data.left = new FormAttachment(0, 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, -SASH_SPACING); |
| hSash.setLayoutData(data); |
| |
| data = new FormData(); |
| data.left = new FormAttachment(0, MARGIN); |
| data.top = new FormAttachment(hSash, SASH_SPACING); |
| data.right = new FormAttachment(vSash, -SASH_SPACING); |
| data.bottom = new FormAttachment(100, -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, MARGIN); |
| data.bottom = new FormAttachment(100, -MARGIN); |
| vSash.setLayoutData(data); |
| |
| data = new FormData(); |
| data.left = new FormAttachment(vSash, SASH_SPACING); |
| data.top = new FormAttachment(toolBar, MARGIN); |
| data.right = new FormAttachment(100, -MARGIN); |
| data.bottom = new FormAttachment(tabControlPanel); |
| canvas.setLayoutData(data); |
| |
| data = new FormData(); |
| data.left = new FormAttachment(vSash, SASH_SPACING); |
| data.right = new FormAttachment(100, -MARGIN); |
| data.bottom = new FormAttachment(100, -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); |
| } |
| } |
| }); |
| } |
| |
| 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 { // solid color |
| 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(); |
| } |
| }); |
| } |
| |
| 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); |
| } |
| |
| /** |
| * Creates the control panel |
| * @param parent |
| */ |
| void createControlPanel(Composite parent) { |
| Group group; |
| tabControlPanel = group = new Group(parent, SWT.NONE); |
| group.setText(getResourceString("Settings")); //$NON-NLS-1$ |
| tabControlPanel.setLayout(new RowLayout()); |
| } |
| |
| 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(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(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(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(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()); |
| } |
| }); |
| } |
| |
| /** |
| * 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; |
| } |
| |
| /** |
| * 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 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; |
| } |
| |
| 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()); |
| } |
| } |
| }); |
| } |
| |
| /** |
| * 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)); |
| } |
| |
| /** |
| * 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), |
| }; |
| } |
| |
| /** |
| * 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; |
| } |
| } |
| |
| 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; |
| } |
| |
| /** |
| * Gets the current tab. |
| */ |
| public GraphicsTab getTab() { |
| return tab; |
| } |
| |
| /** |
| * 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 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; |
| } |
| |
| Image loadImage(Device device, String name) { |
| Image image = loadImage(device, GraphicsExample.class, name); |
| if (image != null) resources.add(image); |
| return image; |
| } |
| |
| public Shell open(final Display display) { |
| Shell shell = new Shell(display); |
| shell.setText(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, -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(); |
| } |
| |
| /** |
| * Starts the animation if the animate flag is set. |
| */ |
| void startAnimationTimer() { |
| final Display display = parent.getDisplay(); |
| display.timerExec(TIMER, new Runnable() { |
| public void run() { |
| if (canvas.isDisposed()) return; |
| int timeout = 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); |
| } |
| }); |
| } |
| |
| 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(); |
| } |
| } |