import java.lang.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.applet.*; import java.net.*; import java.util.*; import PainterPalette; final class PainterCanvas extends Canvas implements KeyListener, MouseListener, MouseMotionListener, ComponentListener { int _iWidth, _iHeight; Image _image; PainterPalette _palette; PainterShape _shape = null; int _xOffset = 0, _yOffset = 0; int _xMouseDown, _yMouseDown; final public boolean imageUpdate(Image img, int infoFlags, int x, int y, int width, int height) { if ((infoFlags & ImageObserver.ALLBITS) != 0) { Image image = createImage(_iWidth, _iHeight); Graphics g = image.getGraphics(); g.drawImage(_image, 0, 0, this); g.dispose(); _image = image; repaint(); return false; } else { repaint(500); return true; } } PainterCanvas(Image image, PainterPalette palette) { _image = image; _iWidth = image.getWidth(this); _iHeight = image.getHeight(this); _palette = palette; addKeyListener(this); addMouseListener(this); addMouseMotionListener(this); addComponentListener(this); } final public void paint(Graphics g) { int xImageLeft = -_xOffset, xImageRight = xImageLeft + _iWidth, yImageTop = -_yOffset, yImageBottom = yImageTop + _iHeight; Rectangle rectUpdate = g.getClipBounds(); int xUpdateLeft = rectUpdate.x, xUpdateRight = xUpdateLeft + rectUpdate.width, yUpdateTop = rectUpdate.y, yUpdateBottom = yUpdateTop + rectUpdate.height; g.drawImage(_image, xImageLeft, yImageTop, this); if (xUpdateLeft < xImageLeft) { g.clearRect(xUpdateLeft, yUpdateTop, xImageLeft - xUpdateLeft, rectUpdate.height); } if (xUpdateRight > xImageRight) { g.clearRect(xImageRight, yUpdateTop, xUpdateRight - xImageRight, rectUpdate.height); } if (yUpdateTop < yImageTop) { g.clearRect(xUpdateLeft, yUpdateTop, rectUpdate.width, yImageTop - yUpdateTop); } if (yUpdateBottom > yImageBottom) { g.clearRect(xUpdateLeft, yImageBottom, rectUpdate.width, yUpdateBottom - yImageBottom); } if (_shape != null) { g.setColor(_palette.getColor()); _shape.draw(g); } } final public void update(Graphics g) { paint(g); } final public Dimension getPreferredSize() { return new Dimension(_iWidth, _iHeight); } final public Point getOffset() { return new Point(_xOffset, _yOffset); } final public void setOffset(int x, int y) { if (x != _xOffset || y != _yOffset) { _xOffset = x; _yOffset = y; repaint(100); } } final public void keyPressed(KeyEvent ke) { if (ke.getKeyCode() == KeyEvent.VK_ESCAPE && _shape != null) { _shape = null; repaint(); } } final public void keyTyped(KeyEvent ke) { } final public void keyReleased(KeyEvent ke) { } final public void mouseClicked(MouseEvent me) { } final public void mouseEntered(MouseEvent me) { } final public void mouseExited(MouseEvent me) { } final public void mousePressed(MouseEvent me) { PainterShape shape = _shape; if (shape == null) { shape = _palette.getShape(); } if (shape != null) { int x = me.getX(), y = me.getY(); shape.mouseDown(x, y, this); _shape = shape; _xMouseDown = x; _yMouseDown = y; } } final public void mouseMoved(MouseEvent me) { if (_shape != null) { int x = me.getX(), y = me.getY(); if (x != _xMouseDown || y != _yMouseDown) { _shape.mouseMove(x, y, this); _xMouseDown = x; _yMouseDown = y; } } } final public void mouseDragged(MouseEvent me) { mouseMoved(me); } final public void mouseReleased(MouseEvent me) { if (_shape != null) { if (_shape.mouseUp(me.getX(), me.getY(), this)) { Graphics g = _image.getGraphics(); g.setColor(_palette.getColor()); _shape.draw(g, _xOffset, _yOffset); g.dispose(); _shape = null; } } } final public void componentResized(ComponentEvent ce) { Dimension dimWindow = getSize(); _xOffset = Math.max(0, Math.min(_xOffset, _iWidth - dimWindow.width)); _yOffset = Math.max(0, Math.min(_yOffset, _iHeight - dimWindow.height)); } final public void componentMoved(ComponentEvent ce) { } final public void componentShown(ComponentEvent ce) { } final public void componentHidden(ComponentEvent ce) { } } final class PainterCanvasFrame extends Frame implements AdjustmentListener, ComponentListener, WindowListener { PainterCanvas _canvas; Painter _painter; Scrollbar _sbVert, _sbHoriz; String _strImageName; PainterCanvasFrame(Image image, String strImageName, Painter painter, PainterPalette palette) { super("Painter - " + strImageName); _painter = painter; _strImageName = strImageName; add("Center", _canvas = new PainterCanvas(image, palette)); add("East", _sbVert = new Scrollbar(Scrollbar.VERTICAL, 0, 1, 0, 0)); _sbVert.addAdjustmentListener(this); add("South", _sbHoriz = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, 0)); _sbHoriz.addAdjustmentListener(this); addComponentListener(this); addWindowListener(this); pack(); validate(); show(); } final public void adjustmentValueChanged(AdjustmentEvent ae) { _canvas.setOffset(_sbHoriz.getValue(), _sbVert.getValue()); } final public void setScrollbars(Point ptOffset, Dimension dimImage, Dimension dimWindow) { int iOffset, iVisible, iImage; iImage = dimImage.width; iVisible = Math.min(iImage, dimWindow.width); iOffset = Math.min(iImage - iVisible, ptOffset.x); _sbHoriz.setValues(iOffset, iVisible, 0, iImage); _sbHoriz.setBlockIncrement(iVisible); iImage = dimImage.height; iVisible = Math.min(iImage, dimWindow.height); iOffset = Math.min(iImage - iVisible, ptOffset.y); _sbVert.setValues(iOffset, iVisible, 0, iImage); _sbVert.setBlockIncrement(iVisible); } final public void componentResized(ComponentEvent ce) { setScrollbars(_canvas.getOffset(), _canvas.getPreferredSize(), // same as its image size _canvas.getSize()); } final public void componentMoved(ComponentEvent ce) { } final public void componentShown(ComponentEvent ce) { } final public void componentHidden(ComponentEvent ce) { } public void windowClosing(WindowEvent we) { _painter.removeFrame(this); dispose(); } public void windowOpened(WindowEvent we) { } public void windowClosed(WindowEvent we) { } public void windowIconified(WindowEvent we) { } public void windowDeiconified(WindowEvent we) { } public void windowActivated(WindowEvent we) { } public void windowDeactivated(WindowEvent we) { } } public final class Painter extends Applet implements ActionListener { PainterPalette _palette; TextField _tfFile, _tfWidth, _tfHeight; Vector _vectorFrames = new Vector(); final static String strLoad = "Load", strCreate = "Create"; final public static GridBagConstraints standardConstraints() { GridBagConstraints gbc = new GridBagConstraints(); gbc.fill = GridBagConstraints.BOTH; gbc.weightx = gbc.weighty = gbc.ipadx = gbc.ipady = 1; gbc.gridheight = GridBagConstraints.REMAINDER; gbc.gridwidth = GridBagConstraints.REMAINDER; return gbc; } final public static void createLabel(Container container, GridBagLayout gridbag, GridBagConstraints gbc, String strLabel) { Label label = new Label(strLabel, Label.RIGHT); gridbag.setConstraints(label, gbc); container.add(label); } final public static TextField createTextField(Container container, GridBagLayout gridbag, GridBagConstraints gbc) { TextField tf = new TextField(4); gridbag.setConstraints(tf, gbc); container.add(tf); return tf; } final public static Button createButton(Container container, GridBagLayout gridbag, GridBagConstraints gbc, String strButton) { Button button = new Button(strButton); gridbag.setConstraints(button, gbc); container.add(button); return button; } final public void init() { setBackground(new Color(0xcc, 0xcc, 0xcc)); GridBagLayout gridbag = new GridBagLayout(); setLayout(gridbag); GridBagConstraints gbc = standardConstraints(); gbc.gridheight = gbc.gridwidth = 1; gbc.weighty = 0; createLabel(this, gridbag, gbc, "Resource:"); gbc.gridwidth = GridBagConstraints.RELATIVE; _tfFile = createTextField(this, gridbag, gbc); gbc.gridwidth = GridBagConstraints.REMAINDER; createButton(this, gridbag, gbc, strLoad).addActionListener(this); gbc.gridwidth = 1; createLabel(this, gridbag, gbc, "Width:"); _tfWidth = createTextField(this, gridbag, gbc); _tfWidth.setText("300"); createLabel(this, gridbag, gbc, "Height:"); _tfHeight = createTextField(this, gridbag, gbc); _tfHeight.setText("300"); gbc.gridwidth = GridBagConstraints.REMAINDER; createButton(this, gridbag, gbc, strCreate).addActionListener(this); } final public void start() { _palette = new PainterPalette(); _vectorFrames.addElement(_palette); } final public void stop() { Frame frame; while (!_vectorFrames.isEmpty()) { frame = (Frame)_vectorFrames.firstElement(); _vectorFrames.removeElement(frame); frame.dispose(); } } final public void removeFrame(Frame frame) { _vectorFrames.removeElement(frame); } final public void actionPerformed(ActionEvent ae) { try { String strButton = ae.getActionCommand(); if (strButton.equals(strCreate)) { int width = Integer.parseInt(_tfWidth.getText()), height = Integer.parseInt(_tfHeight.getText()); if (width > 0 && height > 0) { Image image = createImage(width, height); if (image != null) { Graphics g = image.getGraphics(); g.setColor(Color.white); g.fillRect(0, 0, width, height); g.dispose(); _vectorFrames.addElement(new PainterCanvasFrame(image, "New Image", this, _palette)); } } } else if (strButton.equals(strLoad)) { String strURL = _tfFile.getText(); if (strURL.length() > 0) { URL url; try { url = new URL(strURL); } catch (MalformedURLException e) { url = new URL(getDocumentBase(), strURL); } Image image = getImage(url); MediaTracker media = new MediaTracker(this); media.addImage(image, 0); media.waitForAll(); if (media.isErrorAny()) { System.err.println("cannot load image: " + strURL); } else { Image imageNew = createImage(image.getWidth(this), image.getHeight(this)); Graphics g = imageNew.getGraphics(); g.drawImage(image, 0, 0, this); g.dispose(); _vectorFrames.addElement(new PainterCanvasFrame(imageNew, url.getFile(), this, _palette)); } } } } catch (Exception e) { System.err.println(e.getClass().getName() + ": " + e.getMessage()); } } }