/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 2000-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine is distributed in the hope that it will * * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.ui; import totalcross.sys.*; import totalcross.ui.event.*; import totalcross.ui.gfx.*; import totalcross.ui.image.*; /** This is a whiteboard that can be used to draw something. * It uses a special event flag in order to improve the accuracy. */ public class Whiteboard extends Control { //to draw Lines private int oldX; private int oldY; private Image img; private Graphics gImg; private Graphics gScr; /** Set this to some color so a frame can be drawn around the image */ public int borderColor=-1; /** Set to true to enable antialiase on the line drawing. It must be set right after the constructor. * @deprecated This field is useless in OpenGL platforms */ public boolean useAA; private boolean isEmpty=true; /** Set to true to draw a thick line. * @since TotalCross 1.14 */ public boolean thick; // guich@tc114_78 private int desiredPenColor = -1; /** Constructs a new whiteboard, setting the back color to white. */ public Whiteboard() { backColor = Color.WHITE; focusTraversable = false; // guich@tc123_13 } /** Now that we know our bounds, we can create the image that will hold the drawing */ public void onBoundsChanged(boolean screenChanged) { //if (!screenChanged) if (isEmpty) try { setImage(null); // resize to width and height } catch (ImageException e) { Vm.alert("Not enough memory to resize the whiteboard"); } } /** Returns the image where the drawing is taking place. */ public Image getImage() { return this.img; } /** Returns the preferred width: FILL */ public int getPreferredWidth() { return FILL; } /** Returns the preferred height: FILL */ public int getPreferredHeight() { return FILL; } /** * Sets the image for this WhiteBoard. Pass null to create an empty image. * * @throws ImageException */ public void setImage(Image image) throws ImageException { isEmpty = image == null; this.img = image == null ? new Image(width, height) : image; this.gImg = img.getGraphics(); gImg.foreColor = desiredPenColor != -1 ? desiredPenColor : Color.BLACK; //gImg.useAA = useAA; int lastColor = gImg.foreColor; if (image == null) { gImg.backColor = backColor; gImg.fillRect(0, 0, width, height); } if (borderColor != -1) { gImg.foreColor = borderColor; gImg.drawRect(0, 0, width, height); } gImg.foreColor = lastColor; Window.needsPaint = true; } /** Clears the WhiteBoard to the current background color. */ public void clear() { try {setImage(null);} catch (Exception e) {} } /** Sets the drawing pen color */ public void setPenColor(int c) // guich@300_65 { desiredPenColor = c; if (gImg != null) gImg.foreColor = c; if (gScr != null) gScr.foreColor = c; } /** Returns the drawing pen color. */ public int getPenColor() { return desiredPenColor; } public void onPaint(Graphics g) { if (!Settings.isOpenGL && gScr == null) { gScr = getGraphics(); // create the graphics object that will be used to repaint the image gScr.setClip(0,0,width,height); //gScr.useAA = useAA; if (desiredPenColor != -1) gScr.foreColor = desiredPenColor; } g.drawImage(img,0,0); // draw the image... } TimerEvent te; private void drawTo(Graphics g, int pex, int pey) { g.drawLine(oldX,oldY,pex,pey); // guich@580_34: draw directly on screen if (thick) { g.drawLine(oldX+1,oldY+1,pex+1,pey+1); g.drawLine(oldX-1,oldY-1,pex-1,pey-1); g.drawLine(oldX+1,oldY+1,pex-1,pey-1); g.drawLine(oldX-1,oldY-1,pex+1,pey+1); } } public void onEvent(Event event) { PenEvent pe; switch (event.type) { case TimerEvent.TRIGGERED: if (te != null && te.triggered) Window.needsPaint = true; break; case PenEvent.PEN_DOWN: pe = (PenEvent)event; oldX = pe.x; oldY = pe.y; drawTo(gImg, pe.x,pe.y); // after if (gScr != null) drawTo(gScr,pe.x,pe.y); getParentWindow().setGrabPenEvents(this); // guich@tc100: redirect all pen events to here, bypassing other processings if (Settings.isOpenGL) te = addTimer(100); break; case PenEvent.PEN_DRAG: pe = (PenEvent)event; drawTo(gImg, pe.x,pe.y); // before if (gScr != null) drawTo(gScr,pe.x,pe.y); oldX = pe.x; oldY = pe.y; if (!Settings.isOpenGL) Window.safeUpdateScreen(); // important at desktop! break; case PenEvent.PEN_UP: getParentWindow().setGrabPenEvents(null); removeTimer(te); Window.needsPaint = true; break; } } }