diff options
author | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
commit | f911ba985aa7fe0096c386c5be385ac5825ea527 (patch) | |
tree | a0b991cf5866ae1d616639b906ac001811d74508 /libjava/classpath/java/awt | |
parent | 6f4434b39b261de5317dc81ddfdd94d2e1d62b11 (diff) | |
download | gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.zip gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.gz gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.bz2 |
Initial revision
From-SVN: r102074
Diffstat (limited to 'libjava/classpath/java/awt')
352 files changed, 98340 insertions, 0 deletions
diff --git a/libjava/classpath/java/awt/AWTError.java b/libjava/classpath/java/awt/AWTError.java new file mode 100644 index 0000000..80356ee --- /dev/null +++ b/libjava/classpath/java/awt/AWTError.java @@ -0,0 +1,64 @@ +/* AWTError.java -- A serious AWT error occurred. + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This error is thrown when a critical Abstract Window Toolkit (AWT) error + * occurs. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @status updated to 1.4 + */ +public class AWTError extends Error +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -1819846354050686206L; + + /** + * Create a new instance with the specified descriptive error message. + * + * @param message the descriptive error message + */ + public AWTError(String message) + { + super(message); + } +} // class AWTError diff --git a/libjava/classpath/java/awt/AWTEvent.java b/libjava/classpath/java/awt/AWTEvent.java new file mode 100644 index 0000000..ad9533f --- /dev/null +++ b/libjava/classpath/java/awt/AWTEvent.java @@ -0,0 +1,278 @@ + +/* AWTEvent.java -- the root event in AWT + Copyright (C) 1999, 2000, 2002, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.util.EventObject; + +/** + * AWTEvent is the root event class for all AWT events in the JDK 1.1 event + * model. It supersedes the Event class from JDK 1.0. Subclasses outside of + * the java.awt package should have IDs greater than RESERVED_ID_MAX. + * + * <p>Event masks defined here are used by components in + * <code>enableEvents</code> to select event types not selected by registered + * listeners. Event masks are appropriately set when registering on + * components. + * + * @author Warren Levy (warrenl@cygnus.com) + * @author Aaron M. Renn (arenn@urbanophile.com) + * @since 1.1 + * @status updated to 1.4 + */ +public abstract class AWTEvent extends EventObject +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -1825314779160409405L; + + /** + * The ID of the event. + * + * @see #getID() + * @see #AWTEvent(Object, int) + * @serial the identifier number of this event + */ + protected int id; + + /** + * Indicates if the event has been consumed. False mean it is passed to + * the peer, true means it has already been processed. Semantic events + * generated by low-level events always have the value true. + * + * @see #consume() + * @see #isConsumed() + * @serial whether the event has been consumed + */ + protected boolean consumed; + + /** + * Who knows? It's in the serial version. + * + * @serial No idea what this is for. + */ + byte[] bdata; + + /** Mask for selecting component events. */ + public static final long COMPONENT_EVENT_MASK = 0x00001; + + /** Mask for selecting container events. */ + public static final long CONTAINER_EVENT_MASK = 0x00002; + + /** Mask for selecting component focus events. */ + public static final long FOCUS_EVENT_MASK = 0x00004; + + /** Mask for selecting keyboard events. */ + public static final long KEY_EVENT_MASK = 0x00008; + + /** Mask for mouse button events. */ + public static final long MOUSE_EVENT_MASK = 0x00010; + + /** Mask for mouse motion events. */ + public static final long MOUSE_MOTION_EVENT_MASK = 0x00020; + + /** Mask for window events. */ + public static final long WINDOW_EVENT_MASK = 0x00040; + + /** Mask for action events. */ + public static final long ACTION_EVENT_MASK = 0x00080; + + /** Mask for adjustment events. */ + public static final long ADJUSTMENT_EVENT_MASK = 0x00100; + + /** Mask for item events. */ + public static final long ITEM_EVENT_MASK = 0x00200; + + /** Mask for text events. */ + public static final long TEXT_EVENT_MASK = 0x00400; + + /** + * Mask for input method events. + * @since 1.3 + */ + public static final long INPUT_METHOD_EVENT_MASK = 0x00800; + + /** + * Mask if input methods are enabled. Package visible only. + */ + static final long INPUT_ENABLED_EVENT_MASK = 0x01000; + + /** + * Mask for paint events. + * @since 1.3 + */ + public static final long PAINT_EVENT_MASK = 0x02000; + + /** + * Mask for invocation events. + * @since 1.3 + */ + public static final long INVOCATION_EVENT_MASK = 0x04000; + + /** + * Mask for hierarchy events. + * @since 1.3 + */ + public static final long HIERARCHY_EVENT_MASK = 0x08000; + + /** + * Mask for hierarchy bounds events. + * @since 1.3 + */ + public static final long HIERARCHY_BOUNDS_EVENT_MASK = 0x10000; + + /** + * Mask for mouse wheel events. + * @since 1.4 + */ + public static final long MOUSE_WHEEL_EVENT_MASK = 0x20000; + + /** + * Mask for window state events. + * @since 1.4 + */ + public static final long WINDOW_STATE_EVENT_MASK = 0x40000; + + /** + * Mask for window focus events. + * @since 1.4 + */ + public static final long WINDOW_FOCUS_EVENT_MASK = 0x80000; + + /** + * This is the highest number for event ids that are reserved for use by + * the AWT system itself. Subclasses outside of java.awt should use higher + * ids. + */ + public static final int RESERVED_ID_MAX = 1999; + + + /** + * Initializes a new AWTEvent from the old Java 1.0 event object. + * + * @param event the old-style event + * @throws NullPointerException if event is null + */ + public AWTEvent(Event event) + { + this(event.target, event.id); + consumed = event.consumed; + } + + /** + * Create an event on the specified source object and id. + * + * @param source the object that caused the event + * @param id the event id + * @throws IllegalArgumentException if source is null + */ + public AWTEvent(Object source, int id) + { + super(source); + this.id = id; + } + + /** + * Retarget the event, such as converting a heavyweight component to a + * lightweight child of the original. This is not for general use, but + * is for event targeting systems like KeyboardFocusManager. + * + * @param source the new source + */ + public void setSource(Object source) + { + this.source = source; + } + + /** + * Returns the event type id. + * + * @return the id number of this event + */ + public int getID() + { + return id; + } + + /** + * Create a string that represents this event in the format + * <code>classname[eventstring] on sourcecomponentname</code>. + * + * @return a string representing this event + */ + public String toString () + { + String string = getClass ().getName () + "[" + paramString () + "] on " + + source; + + return string; + } + + /** + * Returns a string representation of the state of this event. It may be + * empty, but must not be null; it is implementation defined. + * + * @return a string representation of this event + */ + public String paramString() + { + return ""; + } + + /** + * Consumes this event so that it will not be processed in the default + * manner. + */ + protected void consume() + { + consumed = true; + } + + /** + * Tests whether not not this event has been consumed. A consumed event + * is not processed in the default manner. + * + * @return true if this event has been consumed + */ + protected boolean isConsumed() + { + return consumed; + } +} // class AWTEvent diff --git a/libjava/classpath/java/awt/AWTEventMulticaster.java b/libjava/classpath/java/awt/AWTEventMulticaster.java new file mode 100644 index 0000000..f7b9163 --- /dev/null +++ b/libjava/classpath/java/awt/AWTEventMulticaster.java @@ -0,0 +1,1209 @@ +/* AWTEventMulticaster.java -- allows multicast chaining of listeners + Copyright (C) 1999, 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.HierarchyBoundsListener; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; +import java.awt.event.InputMethodEvent; +import java.awt.event.InputMethodListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.event.TextEvent; +import java.awt.event.TextListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.awt.event.WindowListener; +import java.awt.event.WindowStateListener; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.EventListener; + +/** + * This class is used to implement a chain of event handlers. Dispatching + * using this class is thread safe. Here is a quick example of how to + * add and delete listeners using this class. For this example, we will + * assume are firing <code>AdjustmentEvent</code>'s. However, this + * same approach is useful for all events in the <code>java.awt.event</code> + * package, and more if this class is subclassed. + * + * <p><code> + * AdjustmentListener al; + * public void addAdjustmentListener(AdjustmentListener listener) + * { + * al = AWTEventMulticaster.add(al, listener); + * } + * public void removeAdjustmentListener(AdjustmentListener listener) + * { + * al = AWTEventMulticaster.remove(al, listener); + * } + * </code> + * + * <p>When it come time to process an event, simply call <code>al</code>, + * assuming it is not <code>null</code>, and all listeners in the chain will + * be fired. + * + * <p>The first time <code>add</code> is called it is passed + * <code>null</code> and <code>listener</code> as its arguments. This + * starts building the chain. This class returns <code>listener</code> + * which becomes the new <code>al</code>. The next time, <code>add</code> + * is called with <code>al</code> and <code>listener</code> and the + * new listener is then chained to the old. + * + * @author Bryce McKinlay + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.1 + * @status updated to 1.4 + */ +public class AWTEventMulticaster + implements ComponentListener, ContainerListener, FocusListener, KeyListener, + MouseListener, MouseMotionListener, WindowListener, + WindowFocusListener, WindowStateListener, ActionListener, + ItemListener, AdjustmentListener, TextListener, + InputMethodListener, HierarchyListener, HierarchyBoundsListener, + MouseWheelListener +{ + /** + * A variable in the event chain. + */ + protected final EventListener a; + + /** + * A variable in the event chain. + */ + protected final EventListener b; + + /** + * Initializes a new instance of <code>AWTEventMulticaster</code> with + * the specified event listener parameters. The parameters should not be + * null, although it is not required to enforce this with a + * NullPointerException. + * + * @param a the "a" listener object + * @param b the "b" listener object + */ + protected AWTEventMulticaster(EventListener a, EventListener b) + { + this.a = a; + this.b = b; + } + + /** + * Removes one instance of the specified listener from this multicaster + * chain. This descends recursively if either child is a multicaster, and + * returns a multicaster chain with the old listener removed. + * + * @param oldl the object to remove from this multicaster + * @return the resulting multicaster with the specified listener removed + */ + protected EventListener remove(EventListener oldl) + { + // If oldl is an immediate child, return the other child. + if (a == oldl) + return b; + if (b == oldl) + return a; + // If a and/or b are Multicaster's, search them recursively. + if (a instanceof AWTEventMulticaster) + { + EventListener newa = ((AWTEventMulticaster) a).remove(oldl); + if (newa != a) + return new AWTEventMulticaster(newa, b); + } + if (b instanceof AWTEventMulticaster) + { + EventListener newb = ((AWTEventMulticaster) b).remove(oldl); + if (newb != b) + return new AWTEventMulticaster(a, newb); + } + // oldl was not found. + return this; + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void componentResized(ComponentEvent e) + { + ((ComponentListener) a).componentResized(e); + ((ComponentListener) b).componentResized(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void componentMoved(ComponentEvent e) + { + ((ComponentListener) a).componentMoved(e); + ((ComponentListener) b).componentMoved(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void componentShown(ComponentEvent e) + { + ((ComponentListener) a).componentShown(e); + ((ComponentListener) b).componentShown(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void componentHidden(ComponentEvent e) + { + ((ComponentListener) a).componentHidden(e); + ((ComponentListener) b).componentHidden(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void componentAdded(ContainerEvent e) + { + ((ContainerListener) a).componentAdded(e); + ((ContainerListener) b).componentAdded(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void componentRemoved(ContainerEvent e) + { + ((ContainerListener) a).componentRemoved(e); + ((ContainerListener) b).componentRemoved(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void focusGained(FocusEvent e) + { + ((FocusListener) a).focusGained(e); + ((FocusListener) b).focusGained(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void focusLost(FocusEvent e) + { + ((FocusListener) a).focusLost(e); + ((FocusListener) b).focusLost(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void keyTyped(KeyEvent e) + { + ((KeyListener) a).keyTyped(e); + ((KeyListener) b).keyTyped(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void keyPressed(KeyEvent e) + { + ((KeyListener) a).keyPressed(e); + ((KeyListener) b).keyPressed(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void keyReleased(KeyEvent e) + { + ((KeyListener) a).keyReleased(e); + ((KeyListener) b).keyReleased(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void mouseClicked(MouseEvent e) + { + ((MouseListener) a).mouseClicked(e); + ((MouseListener) b).mouseClicked(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void mousePressed(MouseEvent e) + { + ((MouseListener) a).mousePressed(e); + ((MouseListener) b).mousePressed(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void mouseReleased(MouseEvent e) + { + ((MouseListener) a).mouseReleased(e); + ((MouseListener) b).mouseReleased(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void mouseEntered(MouseEvent e) + { + ((MouseListener) a).mouseEntered(e); + ((MouseListener) b).mouseEntered(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void mouseExited(MouseEvent e) + { + ((MouseListener) a).mouseExited(e); + ((MouseListener) b).mouseExited(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void mouseDragged(MouseEvent e) + { + ((MouseMotionListener) a).mouseDragged(e); + ((MouseMotionListener) b).mouseDragged(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void mouseMoved(MouseEvent e) + { + ((MouseMotionListener) a).mouseMoved(e); + ((MouseMotionListener) b).mouseMoved(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void windowOpened(WindowEvent e) + { + ((WindowListener) a).windowOpened(e); + ((WindowListener) b).windowOpened(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void windowClosing(WindowEvent e) + { + ((WindowListener) a).windowClosing(e); + ((WindowListener) b).windowClosing(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void windowClosed(WindowEvent e) + { + ((WindowListener) a).windowClosed(e); + ((WindowListener) b).windowClosed(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void windowIconified(WindowEvent e) + { + ((WindowListener) a).windowIconified(e); + ((WindowListener) b).windowIconified(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void windowDeiconified(WindowEvent e) + { + ((WindowListener) a).windowDeiconified(e); + ((WindowListener) b).windowDeiconified(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void windowActivated(WindowEvent e) + { + ((WindowListener) a).windowActivated(e); + ((WindowListener) b).windowActivated(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void windowDeactivated(WindowEvent e) + { + ((WindowListener) a).windowDeactivated(e); + ((WindowListener) b).windowDeactivated(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + * @since 1.4 + */ + public void windowStateChanged(WindowEvent e) + { + ((WindowStateListener) a).windowStateChanged(e); + ((WindowStateListener) b).windowStateChanged(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + * @since 1.4 + */ + public void windowGainedFocus(WindowEvent e) + { + ((WindowFocusListener) a).windowGainedFocus(e); + ((WindowFocusListener) b).windowGainedFocus(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + * @since 1.4 + */ + public void windowLostFocus(WindowEvent e) + { + ((WindowFocusListener) a).windowLostFocus(e); + ((WindowFocusListener) b).windowLostFocus(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void actionPerformed(ActionEvent e) + { + ((ActionListener) a).actionPerformed(e); + ((ActionListener) b).actionPerformed(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void itemStateChanged(ItemEvent e) + { + ((ItemListener) a).itemStateChanged(e); + ((ItemListener) b).itemStateChanged(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void adjustmentValueChanged(AdjustmentEvent e) + { + ((AdjustmentListener) a).adjustmentValueChanged(e); + ((AdjustmentListener) b).adjustmentValueChanged(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + */ + public void textValueChanged(TextEvent e) + { + ((TextListener) a).textValueChanged(e); + ((TextListener) b).textValueChanged(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + * @since 1.2 + */ + public void inputMethodTextChanged(InputMethodEvent e) + { + ((InputMethodListener) a).inputMethodTextChanged(e); + ((InputMethodListener) b).inputMethodTextChanged(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + * @since 1.2 + */ + public void caretPositionChanged(InputMethodEvent e) + { + ((InputMethodListener) a).caretPositionChanged(e); + ((InputMethodListener) b).caretPositionChanged(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + * @since 1.3 + */ + public void hierarchyChanged(HierarchyEvent e) + { + ((HierarchyListener) a).hierarchyChanged(e); + ((HierarchyListener) b).hierarchyChanged(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + * @since 1.3 + */ + public void ancestorMoved(HierarchyEvent e) + { + ((HierarchyBoundsListener) a).ancestorMoved(e); + ((HierarchyBoundsListener) b).ancestorMoved(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + * @since 1.3 + */ + public void ancestorResized(HierarchyEvent e) + { + ((HierarchyBoundsListener) a).ancestorResized(e); + ((HierarchyBoundsListener) b).ancestorResized(e); + } + + /** + * Handles this event by dispatching it to the "a" and "b" listener + * instances. + * + * @param e the event to handle + * @since 1.4 + */ + public void mouseWheelMoved(MouseWheelEvent e) + { + ((MouseWheelListener) a).mouseWheelMoved(e); + ((MouseWheelListener) b).mouseWheelMoved(e); + } + + /** + * Chain <code>ComponentListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + public static ComponentListener add(ComponentListener a, ComponentListener b) + { + return (ComponentListener) addInternal(a, b); + } + + /** + * Chain <code>ContainerListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + public static ContainerListener add(ContainerListener a, ContainerListener b) + { + return (ContainerListener) addInternal(a, b); + } + + /** + * Chain <code>FocusListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + public static FocusListener add(FocusListener a, FocusListener b) + { + return (FocusListener) addInternal(a, b); + } + + /** + * Chain <code>KeyListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + public static KeyListener add(KeyListener a, KeyListener b) + { + return (KeyListener) addInternal(a, b); + } + + /** + * Chain <code>MouseListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + public static MouseListener add(MouseListener a, MouseListener b) + { + return (MouseListener) addInternal(a, b); + } + + /** + * Chain <code>MouseMotionListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + public static MouseMotionListener add(MouseMotionListener a, + MouseMotionListener b) + { + return (MouseMotionListener) addInternal(a, b); + } + + /** + * Chain <code>WindowListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + public static WindowListener add(WindowListener a, WindowListener b) + { + return (WindowListener) addInternal(a, b); + } + + /** + * Chain <code>WindowStateListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + * @since 1.4 + */ + public static WindowStateListener add(WindowStateListener a, + WindowStateListener b) + { + return (WindowStateListener) addInternal(a, b); + } + + /** + * Chain <code>WindowFocusListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + * @since 1.4 + */ + public static WindowFocusListener add(WindowFocusListener a, + WindowFocusListener b) + { + return (WindowFocusListener) addInternal(a, b); + } + + /** + * Chain <code>ActionListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + public static ActionListener add(ActionListener a, ActionListener b) + { + return (ActionListener) addInternal(a, b); + } + + /** + * Chain <code>ItemListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + public static ItemListener add(ItemListener a, ItemListener b) + { + return (ItemListener) addInternal(a, b); + } + + /** + * Chain <code>AdjustmentListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + public static AdjustmentListener add(AdjustmentListener a, + AdjustmentListener b) + { + return (AdjustmentListener) addInternal(a, b); + } + + /** + * Chain <code>AdjustmentListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + public static TextListener add(TextListener a, TextListener b) + { + return (TextListener) addInternal(a, b); + } + + /** + * Chain <code>InputMethodListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + * @since 1.2 + */ + public static InputMethodListener add(InputMethodListener a, + InputMethodListener b) + { + return (InputMethodListener) addInternal(a, b); + } + + /** + * Chain <code>HierarchyListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + * @since 1.3 + */ + public static HierarchyListener add(HierarchyListener a, HierarchyListener b) + { + return (HierarchyListener) addInternal(a, b); + } + + /** + * Chain <code>HierarchyBoundsListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + * @since 1.3 + */ + public static HierarchyBoundsListener add(HierarchyBoundsListener a, + HierarchyBoundsListener b) + { + return (HierarchyBoundsListener) addInternal(a, b); + } + + /** + * Chain <code>MouseWheelListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + * @since 1.4 + */ + public static MouseWheelListener add(MouseWheelListener a, + MouseWheelListener b) + { + return (MouseWheelListener) addInternal(a, b); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + public static ComponentListener remove(ComponentListener l, + ComponentListener oldl) + { + return (ComponentListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + public static ContainerListener remove(ContainerListener l, + ContainerListener oldl) + { + return (ContainerListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + public static FocusListener remove(FocusListener l, FocusListener oldl) + { + return (FocusListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + public static KeyListener remove(KeyListener l, KeyListener oldl) + { + return (KeyListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + public static MouseListener remove(MouseListener l, MouseListener oldl) + { + return (MouseListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + public static MouseMotionListener remove(MouseMotionListener l, + MouseMotionListener oldl) + { + return (MouseMotionListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + public static WindowListener remove(WindowListener l, WindowListener oldl) + { + return (WindowListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + * @since 1.4 + */ + public static WindowStateListener remove(WindowStateListener l, + WindowStateListener oldl) + { + return (WindowStateListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + * @since 1.4 + */ + public static WindowFocusListener remove(WindowFocusListener l, + WindowFocusListener oldl) + { + return (WindowFocusListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + public static ActionListener remove(ActionListener l, ActionListener oldl) + { + return (ActionListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + public static ItemListener remove(ItemListener l, ItemListener oldl) + { + return (ItemListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + public static AdjustmentListener remove(AdjustmentListener l, + AdjustmentListener oldl) + { + return (AdjustmentListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + public static TextListener remove(TextListener l, TextListener oldl) + { + return (TextListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + * @since 1.2 + */ + public static InputMethodListener remove(InputMethodListener l, + InputMethodListener oldl) + { + return (InputMethodListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + * @since 1.3 + */ + public static HierarchyListener remove(HierarchyListener l, + HierarchyListener oldl) + { + return (HierarchyListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + * @since 1.3 + */ + public static HierarchyBoundsListener remove(HierarchyBoundsListener l, + HierarchyBoundsListener oldl) + { + return (HierarchyBoundsListener) removeInternal(l, oldl); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + * @since 1.4 + */ + public static MouseWheelListener remove(MouseWheelListener l, + MouseWheelListener oldl) + { + return (MouseWheelListener) removeInternal(l, oldl); + } + + /** + * Chain <code>EventListener</code> a and b. + * + * @param a the "a" listener, may be null + * @param b the "b" listener, may be null + * @return latest entry in the chain + */ + protected static EventListener addInternal(EventListener a, EventListener b) + { + if (a == null) + return b; + if (b == null) + return a; + return new AWTEventMulticaster(a, b); + } + + /** + * Removes the listener <code>oldl</code> from the listener <code>l</code>. + * + * @param l the listener chain to reduce + * @param oldl the listener to remove + * @return the resulting listener chain + */ + protected static EventListener removeInternal(EventListener l, + EventListener oldl) + { + if (l == oldl) + return null; + if (l instanceof AWTEventMulticaster) + return ((AWTEventMulticaster) l).remove(oldl); + return l; + } + + /** + * Saves all Serializable listeners to a serialization stream. + * + * @param s the stream to save to + * @param k a prefix stream put before each serializable listener + * @throws IOException if serialization fails + */ + protected void saveInternal(ObjectOutputStream s, String k) + throws IOException + { + // This is not documented by Sun, but I think it is correct. + if (a instanceof AWTEventMulticaster) + ((AWTEventMulticaster) a).saveInternal(s, k); + else if (a instanceof Serializable) + { + s.writeObject(k); + s.writeObject(a); + } + if (b instanceof AWTEventMulticaster) + ((AWTEventMulticaster) b).saveInternal(s, k); + else if (b instanceof Serializable) + { + s.writeObject(k); + s.writeObject(b); + } + } + + /** + * Saves a Serializable listener chain to a serialization stream. + * + * @param s the stream to save to + * @param k a prefix stream put before each serializable listener + * @param l the listener chain to save + * @throws IOException if serialization fails + */ + protected static void save(ObjectOutputStream s, String k, EventListener l) + throws IOException + { + // This is not documented by Sun, but I think it is correct. + if (l instanceof AWTEventMulticaster) + ((AWTEventMulticaster) l).saveInternal(s, k); + else if (l instanceof Serializable) + { + s.writeObject(k); + s.writeObject(l); + } + } + + /** + * Returns an array of all chained listeners of the specified type in the + * given chain. A null listener returns an empty array, and a listener + * which is not an AWTEventMulticaster returns an array of one element. If + * no listeners in the chain are of the specified type, an empty array is + * returned. + * + * @param l the listener chain to convert to an array + * @param type the type of listeners to collect + * @return an array of the listeners of that type in the chain + * @throws ClassCastException if type is not assignable from EventListener + * @throws NullPointerException if type is null + * @throws IllegalArgumentException if type is Void.TYPE + * @since 1.4 + */ + public static EventListener[] getListeners(EventListener l, Class type) + { + ArrayList list = new ArrayList(); + if (l instanceof AWTEventMulticaster) + ((AWTEventMulticaster) l).getListeners(list, type); + else if (type.isInstance(l)) + list.add(l); + EventListener[] r = (EventListener[]) Array.newInstance(type, list.size()); + list.toArray(r); + return r; + } + + /** + * Collects all instances of the given type in the chain into the list. + * + * @param l the list to collect into + * @param type the type of listeners to collect + * @throws NullPointerException if type is null + * @see #getListeners(EventListener, Class) + */ + private void getListeners(ArrayList l, Class type) + { + if (a instanceof AWTEventMulticaster) + ((AWTEventMulticaster) a).getListeners(l, type); + else if (type.isInstance(a)) + l.add(a); + if (b instanceof AWTEventMulticaster) + ((AWTEventMulticaster) b).getListeners(l, type); + else if (type.isInstance(b)) + l.add(b); + } +} // class AWTEventMulticaster diff --git a/libjava/classpath/java/awt/AWTException.java b/libjava/classpath/java/awt/AWTException.java new file mode 100644 index 0000000..2df3dd8 --- /dev/null +++ b/libjava/classpath/java/awt/AWTException.java @@ -0,0 +1,64 @@ +/* AWTException.java -- Generic AWT exception + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This is a generic exception that indicates an exception occurred in the + * Abstract Window Toolkit (AWT) system. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @status updated to 1.4 + */ +public class AWTException extends Exception +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -1900414231151323879L; + + /** + * Create a new instance with the specified detailed error message. + * + * @param message the detailed error message + */ + public AWTException(String message) + { + super(message); + } +} // class AWTException diff --git a/libjava/classpath/java/awt/AWTKeyStroke.java b/libjava/classpath/java/awt/AWTKeyStroke.java new file mode 100644 index 0000000..c10d53e --- /dev/null +++ b/libjava/classpath/java/awt/AWTKeyStroke.java @@ -0,0 +1,660 @@ +/* AWTKeyStroke.java -- an immutable key stroke + Copyright (C) 2002, 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * This class mirrors KeyEvents, representing both low-level key presses and + * key releases, and high level key typed inputs. However, this class forms + * immutable strokes, and can be efficiently reused via the factory methods + * for creating them. + * + * <p>For backwards compatibility with Swing, this supports a way to build + * instances of a subclass, using reflection, provided the subclass has a + * no-arg constructor (of any accessibility). + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see #getAWTKeyStroke(char) + * @since 1.4 + * @status updated to 1.4 + */ +public class AWTKeyStroke implements Serializable +{ + /** + * Compatible with JDK 1.4+. + */ + private static final long serialVersionUID = -6430539691155161871L; + + /** The mask for modifiers. */ + private static final int MODIFIERS_MASK = 0x3fef; + + /** + * The cache of recently created keystrokes. This maps KeyStrokes to + * KeyStrokes in a cache which removes the least recently accessed entry, + * under the assumption that garbage collection of a new keystroke is + * easy when we find the old one that it matches in the cache. + */ + private static final LinkedHashMap cache = new LinkedHashMap(11, 0.75f, true) + { + /** The largest the keystroke cache can grow. */ + private static final int MAX_CACHE_SIZE = 2048; + + /** Prune stale entries. */ + protected boolean removeEldestEntry(Map.Entry eldest) + { // XXX - FIXME Use Map.Entry, not just Entry as gcj 3.1 workaround. + return size() > MAX_CACHE_SIZE; + } + }; + + /** The most recently generated keystroke, or null. */ + private static AWTKeyStroke recent; + + /** + * The no-arg constructor of a subclass, or null to use AWTKeyStroke. Note + * that this will be left accessible, to get around private access; but + * it should not be a security risk as it is highly unlikely that creating + * protected instances of the subclass via reflection will do much damage. + */ + private static Constructor ctor; + + /** + * A table of keyCode names to values. This is package-private to + * avoid an accessor method. + * + * @see #getAWTKeyStroke(String) + */ + static final HashMap vktable = new HashMap(); + static + { + // Using reflection saves the hassle of keeping this in sync with KeyEvent, + // at the price of an expensive initialization. + AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + Field[] fields = KeyEvent.class.getFields(); + int i = fields.length; + try + { + while (--i >= 0) + { + Field f = fields[i]; + String name = f.getName(); + if (name.startsWith("VK_")) + vktable.put(name.substring(3), f.get(null)); + } + } + catch (Exception e) + { + throw (Error) new InternalError().initCause(e); + } + return null; + } + }); + } + + /** + * The typed character, or CHAR_UNDEFINED for key presses and releases. + * + * @serial the keyChar + */ + private char keyChar; + + /** + * The virtual key code, or VK_UNDEFINED for key typed. Package visible for + * use by Component. + * + * @serial the keyCode + */ + int keyCode; + + /** + * The modifiers in effect. To match Sun, this stores the old style masks + * for shift, control, alt, meta, and alt-graph (but not button1); as well + * as the new style of extended modifiers for all modifiers. + * + * @serial bitwise or of the *_DOWN_MASK modifiers + */ + private int modifiers; + + /** + * True if this is a key release; should only be true if keyChar is + * CHAR_UNDEFINED. + * + * @serial true to distinguish key pressed from key released + */ + private boolean onKeyRelease; + + /** + * Construct a keystroke with default values: it will be interpreted as a + * key typed event with an invalid character and no modifiers. Client code + * should use the factory methods instead. + * + * @see #getAWTKeyStroke(char) + * @see #getAWTKeyStroke(Character, int) + * @see #getAWTKeyStroke(int, int, boolean) + * @see #getAWTKeyStroke(int, int) + * @see #getAWTKeyStrokeForEvent(KeyEvent) + * @see #getAWTKeyStroke(String) + */ + protected AWTKeyStroke() + { + keyChar = KeyEvent.CHAR_UNDEFINED; + } + + /** + * Construct a keystroke with the given values. Client code should use the + * factory methods instead. + * + * @param keyChar the character entered, if this is a key typed + * @param keyCode the key pressed or released, or VK_UNDEFINED for key typed + * @param modifiers the modifier keys for the keystroke, in old or new style + * @param onKeyRelease true if this is a key release instead of a press + * @see #getAWTKeyStroke(char) + * @see #getAWTKeyStroke(Character, int) + * @see #getAWTKeyStroke(int, int, boolean) + * @see #getAWTKeyStroke(int, int) + * @see #getAWTKeyStrokeForEvent(KeyEvent) + * @see #getAWTKeyStroke(String) + */ + protected AWTKeyStroke(char keyChar, int keyCode, int modifiers, + boolean onKeyRelease) + { + this.keyChar = keyChar; + this.keyCode = keyCode; + // No need to call extend(), as only trusted code calls this constructor. + this.modifiers = modifiers; + this.onKeyRelease = onKeyRelease; + } + + /** + * Registers a new subclass as being the type of keystrokes to generate in + * the factory methods. This operation flushes the cache of stored keystrokes + * if the class differs from the current one. The new class must be + * AWTKeyStroke or a subclass, and must have a no-arg constructor (which may + * be private). + * + * @param subclass the new runtime type of generated keystrokes + * @throws IllegalArgumentException subclass doesn't have no-arg constructor + * @throws ClassCastException subclass doesn't extend AWTKeyStroke + */ + protected static void registerSubclass(final Class subclass) + { + if (subclass == null) + throw new IllegalArgumentException(); + if (subclass.equals(ctor == null ? AWTKeyStroke.class + : ctor.getDeclaringClass())) + return; + if (subclass.equals(AWTKeyStroke.class)) + { + cache.clear(); + recent = null; + ctor = null; + return; + } + try + { + ctor = (Constructor) AccessController.doPrivileged + (new PrivilegedExceptionAction() + { + public Object run() + throws NoSuchMethodException, InstantiationException, + IllegalAccessException, InvocationTargetException + { + Constructor c = subclass.getDeclaredConstructor(null); + c.setAccessible(true); + // Create a new instance, to make sure that we can, and + // to cause any ClassCastException. + AWTKeyStroke dummy = (AWTKeyStroke) c.newInstance(null); + return c; + } + }); + } + catch (PrivilegedActionException e) + { + // e.getCause() will not ever be ClassCastException; that should + // escape on its own. + throw (RuntimeException) + new IllegalArgumentException().initCause(e.getCause()); + } + cache.clear(); + recent = null; + } + + /** + * Returns a keystroke representing a typed character. + * + * @param keyChar the typed character + * @return the specified keystroke + */ + public static AWTKeyStroke getAWTKeyStroke(char keyChar) + { + return getAWTKeyStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false); + } + + /** + * Returns a keystroke representing a typed character with the given + * modifiers. Note that keyChar is a <code>Character</code> instead of a + * <code>char</code> to avoid accidental ambiguity with + * <code>getAWTKeyStroke(int, int)</code>. The modifiers are the bitwise + * or of the masks found in {@link InputEvent}; the new style (*_DOWN_MASK) + * is preferred, but the old style will work. + * + * @param keyChar the typed character + * @param modifiers the modifiers, or 0 + * @return the specified keystroke + * @throws IllegalArgumentException if keyChar is null + */ + public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers) + { + if (keyChar == null) + throw new IllegalArgumentException(); + return getAWTKeyStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED, + extend(modifiers), false); + } + + /** + * Returns a keystroke representing a pressed or released key event, with + * the given modifiers. The "virtual key" should be one of the VK_* + * constants in {@link KeyEvent}. The modifiers are the bitwise or of the + * masks found in {@link InputEvent}; the new style (*_DOWN_MASK) is + * preferred, but the old style will work. + * + * @param keyCode the virtual key + * @param modifiers the modifiers, or 0 + * @param release true if this is a key release instead of a key press + * @return the specified keystroke + */ + public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers, + boolean release) + { + return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode, + extend(modifiers), release); + } + + /** + * Returns a keystroke representing a pressed key event, with the given + * modifiers. The "virtual key" should be one of the VK_* constants in + * {@link KeyEvent}. The modifiers are the bitwise or of the masks found + * in {@link InputEvent}; the new style (*_DOWN_MASK) is preferred, but the + * old style will work. + * + * @param keyCode the virtual key + * @param modifiers the modifiers, or 0 + * @return the specified keystroke + */ + public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers) + { + return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode, + extend(modifiers), false); + } + + /** + * Returns a keystroke representing what caused the key event. + * + * @param event the key event to convert + * @return the specified keystroke, or null if the event is invalid + * @throws NullPointerException if event is null + */ + public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent event) + { + switch (event.id) + { + case KeyEvent.KEY_TYPED: + return getAWTKeyStroke(event.getKeyChar(), KeyEvent.VK_UNDEFINED, + extend(event.getModifiersEx()), false); + case KeyEvent.KEY_PRESSED: + return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, event.getKeyCode(), + extend(event.getModifiersEx()), false); + case KeyEvent.KEY_RELEASED: + return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, event.getKeyCode(), + extend(event.getModifiersEx()), true); + default: + return null; + } + } + + /** + * Parses a string and returns the keystroke that it represents. The syntax + * for keystrokes is listed below, with tokens separated by an arbitrary + * number of spaces: + * <pre> + * keyStroke := <modifiers>* ( <typedID> | <codeID> ) + * modifiers := ( shift | control | ctrl | meta | alt + * | button1 | button2 | button3 ) + * typedID := typed <single Unicode character> + * codeID := ( pressed | released )? <name> + * name := <the KeyEvent field name less the leading "VK_"> + * </pre> + * + * <p>Note that the grammar is rather weak, and not all valid keystrokes + * can be generated in this manner (for example, a typed space, or anything + * with the alt-graph modifier!). The output of AWTKeyStroke.toString() + * will not meet the grammar. If pressed or released is not specified, + * pressed is assumed. Examples:<br> + * <code> + * "INSERT" => getAWTKeyStroke(KeyEvent.VK_INSERT, 0);<br> + * "control DELETE" => + * getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);<br> + * "alt shift X" => getAWTKeyStroke(KeyEvent.VK_X, + * InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);<br> + * "alt shift released X" => getAWTKeyStroke(KeyEvent.VK_X, + * InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);<br> + * "typed a" => getAWTKeyStroke('a'); + * </code> + * + * @param s the string to parse + * @throws IllegalArgumentException if s is null or cannot be parsed + * @return the specified keystroke + */ + public static AWTKeyStroke getAWTKeyStroke(String s) + { + if (s == null) + throw new IllegalArgumentException("null argument"); + StringTokenizer t = new StringTokenizer(s, " "); + if (! t.hasMoreTokens()) + throw new IllegalArgumentException("no tokens '" + s + "'"); + int modifiers = 0; + boolean released = false; + String token = null; + do + { + token = t.nextToken(); + if ("shift".equals(token)) + modifiers |= KeyEvent.SHIFT_DOWN_MASK; + else if ("ctrl".equals(token) || "control".equals(token)) + modifiers |= KeyEvent.CTRL_DOWN_MASK; + else if ("meta".equals(token)) + modifiers |= KeyEvent.META_DOWN_MASK; + else if ("alt".equals(token)) + modifiers |= KeyEvent.ALT_DOWN_MASK; + else if ("button1".equals(token)) + modifiers |= KeyEvent.BUTTON1_DOWN_MASK; + else if ("button2".equals(token)) + modifiers |= KeyEvent.BUTTON2_DOWN_MASK; + else if ("button3".equals(token)) + modifiers |= KeyEvent.BUTTON3_DOWN_MASK; + else if ("typed".equals(token)) + { + if (t.hasMoreTokens()) + { + token = t.nextToken(); + if (! t.hasMoreTokens() && token.length() == 1) + return getAWTKeyStroke(token.charAt(0), + KeyEvent.VK_UNDEFINED, modifiers, + false); + } + throw new IllegalArgumentException("Invalid 'typed' argument '" + + s + "'"); + } + else if ("pressed".equals(token)) + { + if (t.hasMoreTokens()) + token = t.nextToken(); + break; + } + else if ("released".equals(token)) + { + released = true; + if (t.hasMoreTokens()) + token = t.nextToken(); + break; + } + else + break; + } + while (t.hasMoreTokens()); + // Now token contains the VK name we must parse. + Integer code = (Integer) vktable.get(token); + if (code == null) + throw new IllegalArgumentException("Unknown token '" + token + + "' in '" + s + "'"); + if (t.hasMoreTokens()) + throw new IllegalArgumentException("Too many tokens: " + s); + return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, code.intValue(), + modifiers, released); + } + + /** + * Returns the character of this keystroke, if it was typed. + * + * @return the character value, or CHAR_UNDEFINED + * @see #getAWTKeyStroke(char) + */ + public final char getKeyChar() + { + return keyChar; + } + + /** + * Returns the virtual key code of this keystroke, if it was pressed or + * released. This will be a VK_* constant from KeyEvent. + * + * @return the virtual key code value, or VK_UNDEFINED + * @see #getAWTKeyStroke(int, int) + */ + public final int getKeyCode() + { + return keyCode; + } + + /** + * Returns the modifiers for this keystroke. This will be a bitwise or of + * constants from InputEvent; it includes the old style masks for shift, + * control, alt, meta, and alt-graph (but not button1); as well as the new + * style of extended modifiers for all modifiers. + * + * @return the modifiers + * @see #getAWTKeyStroke(Character, int) + * @see #getAWTKeyStroke(int, int) + */ + public final int getModifiers() + { + return modifiers; + } + + /** + * Tests if this keystroke is a key release. + * + * @return true if this is a key release + * @see #getAWTKeyStroke(int, int, boolean) + */ + public final boolean isOnKeyRelease() + { + return onKeyRelease; + } + + /** + * Returns the AWT event type of this keystroke. This is one of + * {@link KeyEvent#KEY_TYPED}, {@link KeyEvent#KEY_PRESSED}, or + * {@link KeyEvent#KEY_RELEASED}. + * + * @return the key event type + */ + public final int getKeyEventType() + { + return keyCode == KeyEvent.VK_UNDEFINED ? KeyEvent.KEY_TYPED + : onKeyRelease ? KeyEvent.KEY_RELEASED : KeyEvent.KEY_PRESSED; + } + + /** + * Returns a hashcode for this key event. It is not documented, but appears + * to be: <code>(getKeyChar() + 1) * (getKeyCode() + 1) + * * (getModifiers() + 1) * 2 + (isOnKeyRelease() ? 1 : 2)</code>. + * + * @return the hashcode + */ + public int hashCode() + { + return (keyChar + 1) * (keyCode + 1) * (modifiers + 1) * 2 + + (onKeyRelease ? 1 : 2); + } + + /** + * Tests two keystrokes for equality. + * + * @param o the object to test + * @return true if it is equal + */ + public final boolean equals(Object o) + { + if (! (o instanceof AWTKeyStroke)) + return false; + AWTKeyStroke s = (AWTKeyStroke) o; + return this == o || (keyChar == s.keyChar && keyCode == s.keyCode + && modifiers == s.modifiers + && onKeyRelease == s.onKeyRelease); + } + + /** + * Returns a string representation of this keystroke. For typed keystrokes, + * this is <code>"keyChar " + KeyEvent.getKeyModifiersText(getModifiers()) + + getKeyChar()</code>; for pressed and released keystrokes, this is + * <code>"keyCode " + KeyEvent.getKeyModifiersText(getModifiers()) + * + KeyEvent.getKeyText(getKeyCode()) + * + (isOnKeyRelease() ? "-R" : "-P")</code>. + * + * @return a string representation + */ + public String toString() + { + if (keyCode == KeyEvent.VK_UNDEFINED) + return "keyChar " + KeyEvent.getKeyModifiersText(modifiers) + keyChar; + return "keyCode " + KeyEvent.getKeyModifiersText(modifiers) + + KeyEvent.getKeyText(keyCode) + (onKeyRelease ? "-R" : "-P"); + } + + /** + * Returns a cached version of the deserialized keystroke, if available. + * + * @return a cached replacement + * @throws ObjectStreamException if something goes wrong + */ + protected Object readResolve() throws ObjectStreamException + { + AWTKeyStroke s = (AWTKeyStroke) cache.get(this); + if (s != null) + return s; + cache.put(this, this); + return this; + } + + /** + * Gets the appropriate keystroke, creating one if necessary. + * + * @param keyChar the keyChar + * @param keyCode the keyCode + * @param modifiers the modifiers + * @param release true for key release + * @return the specified keystroke + */ + private static AWTKeyStroke getAWTKeyStroke(char keyChar, int keyCode, + int modifiers, boolean release) + { + // Check level 0 cache. + AWTKeyStroke stroke = recent; // Avoid thread races. + if (stroke != null && stroke.keyChar == keyChar + && stroke.keyCode == keyCode && stroke.modifiers == modifiers + && stroke.onKeyRelease == release) + return stroke; + // Create a new object, on the assumption that if it has a match in the + // cache, the VM can easily garbage collect it as it is temporary. + Constructor c = ctor; // Avoid thread races. + if (c == null) + stroke = new AWTKeyStroke(keyChar, keyCode, modifiers, release); + else + try + { + stroke = (AWTKeyStroke) c.newInstance(null); + stroke.keyChar = keyChar; + stroke.keyCode = keyCode; + stroke.modifiers = modifiers; + stroke.onKeyRelease = release; + } + catch (Exception e) + { + throw (Error) new InternalError().initCause(e); + } + // Check level 1 cache. + AWTKeyStroke cached = (AWTKeyStroke) cache.get(stroke); + if (cached == null) + cache.put(stroke, stroke); + else + stroke = cached; + return recent = stroke; + } + + /** + * Converts the modifiers to the appropriate format. + * + * @param mod the modifiers to convert + * @return the adjusted modifiers + */ + private static int extend(int mod) + { + if ((mod & (KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK)) != 0) + mod |= KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK; + if ((mod & (KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK)) != 0) + mod |= KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK; + if ((mod & (KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK)) != 0) + mod |= KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK; + if ((mod & (KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK)) != 0) + mod |= KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK; + if ((mod & (KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK)) != 0) + mod |= KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK; + if ((mod & KeyEvent.BUTTON1_MASK) != 0) + mod |= KeyEvent.BUTTON1_DOWN_MASK; + return mod & MODIFIERS_MASK; + } +} // class AWTKeyStroke diff --git a/libjava/classpath/java/awt/AWTPermission.java b/libjava/classpath/java/awt/AWTPermission.java new file mode 100644 index 0000000..3e50c05 --- /dev/null +++ b/libjava/classpath/java/awt/AWTPermission.java @@ -0,0 +1,121 @@ +/* AWTPermission.java -- AWT related permissions + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.security.BasicPermission; + +/** + * This class implements permissions for AWT. This is a named + * permission. No actions are defined. + * + * <p>The following table provides a list of all the possible AWTPermission + * permission names with a description of what that permission allows.<br> + * <table border=1> + * <tr><th>Permission Name</th><th>Permission Allows</th><th>Risks</th</tr> + * <tr> + * <td><code>accessClipboard</code></td> + * <td>posting and reading the AWT clipboard</td> + * <td>the clipboard may contain sensitive data</td></tr> + * <tr> + * <td><code>accessEventQueue</code></td> + * <td>access to the AWT event queue</td> + * <td>malicious code could remove real events and replace them with bogus + * ones, including simulating the user granting permission</td></tr> + * <tr> + * <td><code>listenToAllAWTEvents</code></td> + * <td>listen to system-wide AWT events</td> + * <td>malicious code can read passwords entered in an AWT event, and in + * combination with accessEventQueue, could fake system events</td></tr> + * <tr> + * <td><code>showWindowWithoutWarningBanner</code></td> + * <td>display a window without a banner notification of insecurity</td> + * <td>malicious code could install a Trojan horse applet that looks like + * a normal window, and thus steal data like passwords</td></tr> + * <tr> + * <td><code>readDisplayPixels</code></td> + * <td>read back pixels from the display screen</td> + * <td>malicious code could snoop on the user's actions</td></tr> + * <tr> + * <td><code>createRobot</code></td> + * <td>create an instance of java.awt.Robot</td> + * <td>these objects can generate events as though they were the user; so + * malicious code could control the system</td></tr> + * <tr> + * <td><code>fullScreenExclusive</code></td> + * <td>enter full-screen exclusive mode</td> + * <td>malicious code could masquerade as a trusted program</td></tr> + * </table> + * + * @author Tom Tromey (tromey@redhat.com) + * @since 1.2 + * @status updated to 1.4 + */ +public final class AWTPermission extends BasicPermission +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 8890392402588814465L; + + /** + * Construct a AWTPermission with the given name. + * + * @param name the permission name + * @throws NullPointerException if name is null + * @throws IllegalArgumentException if name is invalid + */ + public AWTPermission(String name) + { + super(name); + } + + /** + * Create a new permission with the specified name. The actions argument + * is ignored, as AWT permissions have no actions. + * + * @param name the permission name + * @param actions ignored + * @throws NullPointerException if name is null + * @throws IllegalArgumentException if name is invalid + */ + public AWTPermission(String name, String actions) + { + super(name); + } +} // class AWTPermission diff --git a/libjava/classpath/java/awt/ActiveEvent.java b/libjava/classpath/java/awt/ActiveEvent.java new file mode 100644 index 0000000..e42959f --- /dev/null +++ b/libjava/classpath/java/awt/ActiveEvent.java @@ -0,0 +1,61 @@ +/* ActiveEvent.java -- a self-dispatching event + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * An interface for events which can dispatch themselves in another thread. + * This has two uses: first, if your code is in a critical section, calling a + * synchronized method might deadlock. But by using an ActiveEvent to call + * the second section, it will not obtain the lock until you have left the + * critical section, avoiding deadlock. The second use is for calling + * untrusted code. For example, system code should use an ActiveEvent to + * invoke user code securely. + * + * @author Tom Tromey (tromey@cygnus.com) + * @since 1.2 + * @status updated to 1.4 + */ +public interface ActiveEvent +{ + /** + * Dispatch the event, according to what the event needs done. Invoked + * automatically if this is placed on the <code>EventDispatchQueue</code>. + */ + void dispatch(); +} // interface ActiveEvent diff --git a/libjava/classpath/java/awt/Adjustable.java b/libjava/classpath/java/awt/Adjustable.java new file mode 100644 index 0000000..8f633e9 --- /dev/null +++ b/libjava/classpath/java/awt/Adjustable.java @@ -0,0 +1,171 @@ +/* Adjustable.java -- Objects with a numeric adjustment scale + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.AdjustmentListener; + +/** + * This interface is for objects that take a numeric value that can be + * adjusted within a bounded range. For example, a scroll bar. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @since 1.0 + * @status updated to 1.4 + */ +public interface Adjustable +{ + /** Constant for an adjustable object with horizontal orientation. */ + int HORIZONTAL = 0; + + /** Constant for an adjustable object with vertical orientation. */ + int VERTICAL = 1; + + /** Constant for an adjustable object with no orientation. */ + int NO_ORIENTATION = 2; + + /** + * Returns a constant representing the orientation of the object. + * + * @return the orientation of this object + * @see #HORIZONTAL + * @see #VERTICAL + * @see #NO_ORIENTATION + */ + int getOrientation(); + + /** + * Sets the minimum value this object can have. + * + * @param minimum the new minimum value + */ + void setMinimum(int minimum); + + /** + * Returns the minimum value this object can have. + * + * @return the minimum value + */ + int getMinimum(); + + /** + * Sets the maximum value this object can have. + * + * @param maximum the new maximum value + */ + void setMaximum(int maximum); + + /** + * Returns the maximum value this object can have. + * + * @return the maximum value + */ + int getMaximum(); + + /** + * Sets the increment value for incrementing the value by units. + * + * @param increment the unit increment value + */ + void setUnitIncrement(int increment); + + /** + * Returns the increment value for incrementing the value by units. + * + * @return the unit increment value + */ + int getUnitIncrement(); + + /** + * Sets the increment value for incrementing the value by blocks. + * + * @param increment the block increment value + */ + void setBlockIncrement(int increment); + + /** + * Returns the increment value for incrementing the value by blocks. + * + * @return the block increment value + */ + int getBlockIncrement(); + + /** + * Sets the length of the indicator for this object to the specified value. + * + * @param length the indicator length + */ + void setVisibleAmount(int length); + + /** + * Returns the length of the indicator for this object. + * + * @return the indicator length + */ + int getVisibleAmount(); + + /** + * Sets the current value of the object. + * + * @param value the new value + */ + void setValue(int value); + + /** + * Returns the current value of the object. + * + * @return the current value + */ + int getValue(); + + /** + * Adds a listener that will receive adjustment events for this object. + * + * @param listener the adjustment listener to add + * @see java.awt.event.AdjustmentEvent + */ + void addAdjustmentListener(AdjustmentListener listener); + + /** + * Removes an adjustment listener from this object. + * + * @param listener the adjustment listener to remove + * @see java.awt.event.AdjustmentEvent + */ + void removeAdjustmentListener(AdjustmentListener listener); +} // interface Adjustable diff --git a/libjava/classpath/java/awt/AlphaComposite.java b/libjava/classpath/java/awt/AlphaComposite.java new file mode 100644 index 0000000..435cfd0 --- /dev/null +++ b/libjava/classpath/java/awt/AlphaComposite.java @@ -0,0 +1,167 @@ +/* AlphaComposite.java -- provides a context for performing alpha compositing + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.image.ColorModel; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see Composite + * @see CompositeContext + * @since 1.3 + * @status updated to 1.4 except for createContext, needs documentation + */ +public final class AlphaComposite implements Composite +{ + /** Map Long to AlphaComposites. See getInstance for details. */ + private static final LinkedHashMap cache = new LinkedHashMap(11, 0.75f, true) + { + /** The largest the alpha composite cache can grow. */ + private static final int MAX_CACHE_SIZE = 2048; + + /** Prune stale entries. */ + protected boolean removeEldestEntry(Map.Entry eldest) + { // XXX - FIXME Use Map.Entry, not just Entry as gcj 3.1 workaround. + return size() > MAX_CACHE_SIZE; + } + }; + + public static final int CLEAR = 1; + public static final int SRC = 2; + public static final int DST = 9; + public static final int SRC_OVER = 3; + public static final int DST_OVER = 4; + public static final int SRC_IN = 5; + public static final int DST_IN = 6; + public static final int SRC_OUT = 7; + public static final int DST_OUT = 8; + public static final int SRC_ATOP = 10; + public static final int DST_ATOP = 11; + public static final int XOR = 12; + public static final AlphaComposite Clear = getInstance(CLEAR); + public static final AlphaComposite Src = getInstance(SRC); + public static final AlphaComposite Dst = getInstance(DST); + public static final AlphaComposite SrcOver = getInstance(SRC_OVER); + public static final AlphaComposite DstOver = getInstance(DST_OVER); + public static final AlphaComposite SrcIn = getInstance(SRC_IN); + public static final AlphaComposite DstIn = getInstance(DST_IN); + public static final AlphaComposite SrcOut = getInstance(SRC_OUT); + public static final AlphaComposite DstOut = getInstance(DST_OUT); + public static final AlphaComposite SrcAtop = getInstance(SRC_ATOP); + public static final AlphaComposite DstAtop = getInstance(DST_ATOP); + public static final AlphaComposite Xor = getInstance(XOR); + + private final int rule; + private final float alpha; + private AlphaComposite(int rule, float alpha) + { + this.rule = rule; + this.alpha = alpha; + } + + /** + * Creates an AlphaComposite object with the specified rule. + * + * @param rule The compositing rule. + * + * @exception IllegalArgumentException If rule is not one of the following: + * CLEAR, SRC, DST, SRC_OVER, DST_OVER, SRC_IN, DST_IN, SRC_OUT, DST_OUT, + * SRC_ATOP, DST_ATOP, or XOR. + */ + public static AlphaComposite getInstance(int rule) + { + return getInstance(rule, 1); + } + + /** + * Creates an AlphaComposite object with the specified rule and the constant + * alpha to multiply with the alpha of the source. The source is multiplied + * with the specified alpha before being composited with the destination. + * + * @param rule The compositing rule. + * + * @exception IllegalArgumentException If rule is not one of the following: + * CLEAR, SRC, DST, SRC_OVER, DST_OVER, SRC_IN, DST_IN, SRC_OUT, DST_OUT, + * SRC_ATOP, DST_ATOP, or XOR. + */ + public static AlphaComposite getInstance(int rule, float alpha) + { + if (rule < CLEAR || rule > XOR || ! (alpha >= 0 && alpha <= 1)) + throw new IllegalArgumentException(); + // This long is guaranteed unique for all valid alpha composites. + Long l = new Long(rule + Double.doubleToLongBits(alpha)); + AlphaComposite a = (AlphaComposite) cache.get(l); + if (a == null) + { + a = new AlphaComposite(rule, alpha); + cache.put(l, a); + } + return a; + } + public CompositeContext createContext(ColorModel srcColorModel, + ColorModel dstColorModel, + RenderingHints hints) + { + // XXX Implement. Sun uses undocumented implementation class + // sun.java2d.SunCompositeContext. + throw new Error("not implemented"); + } + public float getAlpha() + { + return alpha; + } + public int getRule() + { + return rule; + } + public int hashCode() + { + return 31 * Float.floatToIntBits(alpha) + rule; + } + public boolean equals(Object o) + { + if (! (o instanceof AlphaComposite)) + return false; + AlphaComposite a = (AlphaComposite) o; + return rule == a.rule && alpha == a.alpha; + } +} // class AlphaComposite diff --git a/libjava/classpath/java/awt/AttributeValue.java b/libjava/classpath/java/awt/AttributeValue.java new file mode 100644 index 0000000..080e92e --- /dev/null +++ b/libjava/classpath/java/awt/AttributeValue.java @@ -0,0 +1,98 @@ +/* AttributeValue.java -- parent of type-safe enums of attributes + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This class is undocumented by Sun, but it is the parent of several other + * classes, all of which are type-safe enumerations. This takes care of + * <code>equals</code>, <code>toString</code>, and <code>hashCode</code>, so + * that you don't have to (although hashCode is commonly overridden). + * + * @author Eric Blake (ebb9@email.byu.edu) + */ +class AttributeValue +{ + /** The value of the enumeration. Package visible for speed. */ + final int value; + + /** The list of enumeration names for the given subclass. */ + private final String[] names; + + /** + * Construct a type-safe enumeration element. For example,<br> + * <pre> + * class Foo extends AttributeValue + * { + * private static final String[] names = { "one", "two" } + * public static final Foo ONE = new Foo(0); + * public static final Foo TWO = new Foo(1); + * private Foo(int value) { super(value, names); } + * } + * </pre> + * + * @param value the position of this enumeration element, consecutive from 0 + * @param names the constant list of enumeration names for the subclass + */ + AttributeValue(int value, String[] names) + { + this.value = value; + this.names = names; + } + + /** + * Returns the hashcode of this element. This is the index of the element + * in the enumeration. Note that equals defaults to the == relation. + * + * @return the hashcode + */ + public int hashCode() + { + return value; + } + + /** + * Returns the name of this enumeration element. + * + * @return the element name + */ + public String toString() + { + return names[value]; + } +} // class AttributeValue diff --git a/libjava/classpath/java/awt/BasicStroke.java b/libjava/classpath/java/awt/BasicStroke.java new file mode 100644 index 0000000..bb008e4 --- /dev/null +++ b/libjava/classpath/java/awt/BasicStroke.java @@ -0,0 +1,248 @@ +/* BasicStroke.java -- + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.util.Arrays; + +/** + * STUB CLASS ONLY + */ +public class BasicStroke implements Stroke +{ + public static final int JOIN_MITER = 0; + public static final int JOIN_ROUND = 1; + public static final int JOIN_BEVEL = 2; + + public static final int CAP_BUTT = 0; + public static final int CAP_ROUND = 1; + public static final int CAP_SQUARE = 2; + + private final float width; + private final int cap; + private final int join; + private final float limit; + private final float[] dash; + private final float phase; + + /** + * Creates a basic stroke. + * + * @param width May not be negative . + * @param cap May be either CAP_BUTT, CAP_ROUND or CAP_SQUARE. + * @param join May be either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER. + * @param miterlimit the limit to trim the miter join. The miterlimit must be + * greater than or equal to 1.0f. + * @param dash The array representing the dashing pattern. There must be at + * least one non-zero entry. + * @param dashPhase is negative and dash is not null. + * + * @exception IllegalArgumentException If one input parameter doesn't meet + * its needs. + */ + public BasicStroke(float width, int cap, int join, float miterlimit, + float[] dash, float dashPhase) + { + if (width < 0.0f ) + throw new IllegalArgumentException("width " + width + " < 0"); + else if (cap < CAP_BUTT || cap > CAP_SQUARE) + throw new IllegalArgumentException("cap " + cap + " out of range [" + + CAP_BUTT + ".." + CAP_SQUARE + "]"); + else if (miterlimit < 1.0f && join == JOIN_MITER) + throw new IllegalArgumentException("miterlimit " + miterlimit + + " < 1.0f while join == JOIN_MITER"); + else if (join < JOIN_MITER || join > JOIN_BEVEL) + throw new IllegalArgumentException("join " + join + " out of range [" + + JOIN_MITER + ".." + JOIN_BEVEL + + "]"); + else if (dashPhase < 0.0f && dash != null) + throw new IllegalArgumentException("dashPhase " + dashPhase + + " < 0.0f while dash != null"); + else if (dash != null) + if (dash.length == 0) + throw new IllegalArgumentException("dash.length is 0"); + else + { + boolean allZero = true; + + for ( int i = 0; i < dash.length; ++i) + { + if (dash[i] != 0.0f) + { + allZero = false; + break; + } + } + + if (allZero) + throw new IllegalArgumentException("all dashes are 0.0f"); + } + + this.width = width; + this.cap = cap; + this.join = join; + limit = miterlimit; + this.dash = dash == null ? null : (float[]) dash.clone(); + phase = dashPhase; + } + + /** + * Creates a basic stroke. + * + * @param width The width of the BasicStroke. May not be negative . + * @param cap May be either CAP_BUTT, CAP_ROUND or CAP_SQUARE. + * @param join May be either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER. + * @param miterlimit the limit to trim the miter join. The miterlimit must be + * greater than or equal to 1.0f. + * + * @exception IllegalArgumentException If one input parameter doesn't meet + * its needs. + */ + public BasicStroke(float width, int cap, int join, float miterlimit) + { + this(width, cap, join, miterlimit, null, 0); + } + + /** + * Creates a basic stroke. + * + * @param width The width of the BasicStroke. May not be nehative. + * @param cap May be either CAP_BUTT, CAP_ROUND or CAP_SQUARE. + * @param join May be either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER. + * + * @exception IllegalArgumentException If one input parameter doesn't meet + * its needs. + * @exception IllegalArgumentException FIXME + */ + public BasicStroke(float width, int cap, int join) + { + this(width, cap, join, 10, null, 0); + } + + /** + * Creates a basic stroke. + * + * @param width The width of the BasicStroke. + * + * @exception IllegalArgumentException If width is negative. + */ + public BasicStroke(float width) + { + this(width, CAP_SQUARE, JOIN_MITER, 10, null, 0); + } + + /** + * Creates a basic stroke. + */ + public BasicStroke() + { + this(1, CAP_SQUARE, JOIN_MITER, 10, null, 0); + } + + public Shape createStrokedShape(Shape s) + { + throw new Error("not implemented"); + } + + public float getLineWidth() + { + return width; + } + + public int getEndCap() + { + return cap; + } + + public int getLineJoin() + { + return join; + } + + public float getMiterLimit() + { + return limit; + } + + public float[] getDashArray() + { + return dash; + } + + public float getDashPhase() + { + return phase; + } + + /** + * Returns the hash code for this object. The hash is calculated by + * xoring the hash, cap, join, limit, dash array and phase values + * (converted to <code>int</code> first with + * <code>Float.floatToIntBits()</code> if the value is a + * <code>float</code>). + */ + public int hashCode() + { + int hash = Float.floatToIntBits(width); + hash ^= cap; + hash ^= join; + hash ^= Float.floatToIntBits(limit); + + if (dash != null) + for (int i = 0; i < dash.length; i++) + hash ^= Float.floatToIntBits(dash[i]); + + hash ^= Float.floatToIntBits(phase); + + return hash; + } + + /** + * Returns true if the given Object is an instance of BasicStroke + * and the width, cap, join, limit, dash array and phase are all + * equal. + */ + public boolean equals(Object o) + { + if (! (o instanceof BasicStroke)) + return false; + BasicStroke s = (BasicStroke) o; + return width == s.width && cap == s.cap && join == s.join + && limit == s.limit && Arrays.equals(dash, s.dash) && phase == s.phase; + } +} // class BasicStroke diff --git a/libjava/classpath/java/awt/BorderLayout.java b/libjava/classpath/java/awt/BorderLayout.java new file mode 100644 index 0000000..c9eb5dd --- /dev/null +++ b/libjava/classpath/java/awt/BorderLayout.java @@ -0,0 +1,731 @@ +/* BorderLayout.java -- A layout manager class + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This class implements a layout manager that positions components + * in certain sectors of the parent container. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public class BorderLayout implements LayoutManager2, java.io.Serializable +{ + +/* + * Static Variables + */ + +/** + * Constant indicating the top of the container + */ +public static final String NORTH = "North"; + +/** + * Constant indicating the bottom of the container + */ +public static final String SOUTH = "South"; + +/** + * Constant indicating the right side of the container + */ +public static final String EAST = "East"; + +/** + * Constant indicating the left side of the container + */ +public static final String WEST = "West"; + +/** + * Constant indicating the center of the container + */ +public static final String CENTER = "Center"; + + + /** + * The constant indicating the position before the first line of the + * layout. The exact position depends on the writing system: For a + * top-to-bottom orientation, it is the same as {@link #NORTH}, for + * a bottom-to-top orientation, it is the same as {@link #SOUTH}. + * + * <p>This constant is an older name for {@link #PAGE_START} which + * has exactly the same value. + * + * @since 1.2 + */ + public static final String BEFORE_FIRST_LINE = "First"; + + + /** + * The constant indicating the position after the last line of the + * layout. The exact position depends on the writing system: For a + * top-to-bottom orientation, it is the same as {@link #SOUTH}, for + * a bottom-to-top orientation, it is the same as {@link #NORTH}. + * + * <p>This constant is an older name for {@link #PAGE_END} which + * has exactly the same value. + * + * @since 1.2 + */ + public static final String AFTER_LAST_LINE = "Last"; + + + /** + * The constant indicating the position before the first item of the + * layout. The exact position depends on the writing system: For a + * left-to-right orientation, it is the same as {@link #WEST}, for + * a right-to-left orientation, it is the same as {@link #EAST}. + * + * <p>This constant is an older name for {@link #LINE_START} which + * has exactly the same value. + * + * @since 1.2 + */ + public static final String BEFORE_LINE_BEGINS = "Before"; + + + /** + * The constant indicating the position after the last item of the + * layout. The exact position depends on the writing system: For a + * left-to-right orientation, it is the same as {@link #EAST}, for + * a right-to-left orientation, it is the same as {@link #WEST}. + * + * <p>This constant is an older name for {@link #LINE_END} which + * has exactly the same value. + * + * @since 1.2 + */ + public static final String AFTER_LINE_ENDS = "After"; + + + /** + * The constant indicating the position before the first line of the + * layout. The exact position depends on the writing system: For a + * top-to-bottom orientation, it is the same as {@link #NORTH}, for + * a bottom-to-top orientation, it is the same as {@link #SOUTH}. + * + * @since 1.4 + */ + public static final String PAGE_START = BEFORE_FIRST_LINE; + + + /** + * The constant indicating the position after the last line of the + * layout. The exact position depends on the writing system: For a + * top-to-bottom orientation, it is the same as {@link #SOUTH}, for + * a bottom-to-top orientation, it is the same as {@link #NORTH}. + * + * @since 1.4 + */ + public static final String PAGE_END = AFTER_LAST_LINE; + + + /** + * The constant indicating the position before the first item of the + * layout. The exact position depends on the writing system: For a + * left-to-right orientation, it is the same as {@link #WEST}, for + * a right-to-left orientation, it is the same as {@link #EAST}. + * + * @since 1.4 + */ + public static final String LINE_START = BEFORE_LINE_BEGINS; + + + /** + * The constant indicating the position after the last item of the + * layout. The exact position depends on the writing system: For a + * left-to-right orientation, it is the same as {@link #EAST}, for + * a right-to-left orientation, it is the same as {@link #WEST}. + * + * @since 1.4 + */ + public static final String LINE_END = AFTER_LINE_ENDS; + + + +// Serialization constant +private static final long serialVersionUID = -8658291919501921765L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial + */ +private Component north; + +/** + * @serial + */ +private Component south; + +/** + * @serial + */ +private Component east; + +/** + * @serial + */ +private Component west; + +/** + * @serial + */ +private Component center; + +/** + * @serial + */ +private Component firstLine; + +/** + * @serial + */ +private Component lastLine; + +/** + * @serial + */ +private Component firstItem; + +/** + * @serial + */ +private Component lastItem; + +/** + * @serial The horizontal gap between components + */ +private int hgap; + +/** + * @serial The vertical gap between components + */ +private int vgap; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>BorderLayout</code> with no + * horiztonal or vertical gaps between components. + */ +public +BorderLayout() +{ + this(0,0); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>BorderLayout</code> with the + * specified horiztonal and vertical gaps between components. + * + * @param hgap The horizontal gap between components. + * @param vgap The vertical gap between components. + */ +public +BorderLayout(int hgap, int vgap) +{ + this.hgap = hgap; + this.vgap = vgap; +} + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * Returns the horitzontal gap value. + * + * @return The horitzontal gap value. + */ +public int +getHgap() +{ + return(hgap); +} + +/*************************************************************************/ + +/** + * Sets the horizontal gap to the specified value. + * + * @param hgap The new horizontal gap. + */ +public void +setHgap(int hgap) +{ + this.hgap = hgap; +} + +/*************************************************************************/ + +/** + * Returns the vertical gap value. + * + * @return The vertical gap value. + */ +public int +getVgap() +{ + return(vgap); +} + +/*************************************************************************/ + +/** + * Sets the vertical gap to the specified value. + * + * @param vgap The new vertical gap value. + */ +public void +setVgap(int vgap) +{ + this.vgap = vgap; +} + +/*************************************************************************/ + +/** + * Adds a component to the layout in the specified constraint position, + * which must be one of the string constants defined in this class. + * + * @param component The component to add. + * @param constraints The constraint string. + * + * @exception IllegalArgumentException If the constraint object is not + * a string, or is not one of the specified constants in this class. + */ +public void +addLayoutComponent(Component component, Object constraints) +{ + if (constraints != null && ! (constraints instanceof String)) + throw new IllegalArgumentException("Constraint must be a string"); + + addLayoutComponent((String) constraints, component); +} + +/*************************************************************************/ + +/** + * Adds a component to the layout in the specified constraint position, + * which must be one of the string constants defined in this class. + * + * @param constraints The constraint string. + * @param component The component to add. + * + * @exception IllegalArgumentException If the constraint object is not + * one of the specified constants in this class. + * + * @deprecated This method is deprecated in favor of + * <code>addLayoutComponent(Component, Object)</code>. + */ +public void +addLayoutComponent(String constraints, Component component) +{ + String str = constraints; + + if (str == null || str.equals(CENTER)) + center = component; + else if (str.equals(NORTH)) + north = component; + else if (str.equals(SOUTH)) + south = component; + else if (str.equals(EAST)) + east = component; + else if (str.equals(WEST)) + west = component; + else if (str.equals(BEFORE_FIRST_LINE)) + firstLine = component; + else if (str.equals(AFTER_LAST_LINE)) + lastLine = component; + else if (str.equals(BEFORE_LINE_BEGINS)) + firstItem = component; + else if (str.equals(AFTER_LINE_ENDS)) + lastItem = component; + else + throw new IllegalArgumentException("Constraint value not valid: " + str); +} + +/*************************************************************************/ + +/** + * Removes the specified component from the layout. + * + * @param component The component to remove from the layout. + */ +public void +removeLayoutComponent(Component component) +{ + if (north == component) + north = null; + if (south == component) + south = null; + if (east == component) + east = null; + if (west == component) + west = null; + if (center == component) + center = null; + if (firstItem == component) + firstItem = null; + if (lastItem == component) + lastItem = null; + if (firstLine == component) + firstLine = null; + if (lastLine == component) + lastLine = null; +} + +/*************************************************************************/ + +/** + * Returns the minimum size of the specified container using this layout. + * + * @param target The container to calculate the minimum size for. + * + * @return The minimum size of the container + */ +public Dimension +minimumLayoutSize(Container target) +{ + return calcSize(target, MIN); +} + +/*************************************************************************/ + +/** + * Returns the preferred size of the specified container using this layout. + * + * @param target The container to calculate the preferred size for. + * + * @return The preferred size of the container + */ +public Dimension +preferredLayoutSize(Container target) +{ + return calcSize(target, PREF); +} + +/*************************************************************************/ + +/** + * Returns the maximum size of the specified container using this layout. + * + * @param target The container to calculate the maximum size for. + * + * @return The maximum size of the container + */ +public Dimension +maximumLayoutSize(Container target) +{ + return calcSize(target, MAX); +} + +/*************************************************************************/ + +/** + * Returns the X axis alignment, which is a <code>float</code> indicating + * where along the X axis this container wishs to position its layout. + * 0 indicates align to the left, 1 indicates align to the right, and 0.5 + * indicates align to the center. + * + * @param parent The parent container. + * + * @return The X alignment value. + */ +public float +getLayoutAlignmentX(Container parent) +{ + return(parent.getAlignmentX()); +} + +/*************************************************************************/ + +/** + * Returns the Y axis alignment, which is a <code>float</code> indicating + * where along the Y axis this container wishs to position its layout. + * 0 indicates align to the top, 1 indicates align to the bottom, and 0.5 + * indicates align to the center. + * + * @param parent The parent container. + * + * @return The Y alignment value. + */ +public float +getLayoutAlignmentY(Container parent) +{ + return(parent.getAlignmentY()); +} + +/*************************************************************************/ + +/** + * Instructs this object to discard any layout information it might + * have cached. + * + * @param parent The parent container. + */ +public void +invalidateLayout(Container parent) +{ +} + +/*************************************************************************/ + +/** + * Lays out the specified container according to the constraints + * in this object. + * + * @param target The container to lay out. + */ +public void +layoutContainer(Container target) +{ + synchronized (target.getTreeLock ()) + { + Insets i = target.getInsets(); + + ComponentOrientation orient = target.getComponentOrientation (); + boolean left_to_right = orient.isLeftToRight (); + + Component my_north = north; + Component my_east = east; + Component my_south = south; + Component my_west = west; + + // Note that we currently don't handle vertical layouts. Neither + // does JDK 1.3. + if (firstLine != null) + my_north = firstLine; + if (lastLine != null) + my_south = lastLine; + if (firstItem != null) + { + if (left_to_right) + my_west = firstItem; + else + my_east = firstItem; + } + if (lastItem != null) + { + if (left_to_right) + my_east = lastItem; + else + my_west = lastItem; + } + + Dimension c = calcCompSize(center, PREF); + Dimension n = calcCompSize(my_north, PREF); + Dimension s = calcCompSize(my_south, PREF); + Dimension e = calcCompSize(my_east, PREF); + Dimension w = calcCompSize(my_west, PREF); + Dimension t = target.getSize(); + + /* + <-> hgap <-> hgap + +----------------------------+ } + |t | } i.top + | +----------------------+ | --- y1 } + | |n | | + | +----------------------+ | } vgap + | +---+ +----------+ +---+ | --- y2 } } + | |w | |c | |e | | } hh + | +---+ +----------+ +---+ | } vgap } + | +----------------------+ | --- y3 } + | |s | | + | +----------------------+ | } + | | } i.bottom + +----------------------------+ } + |x1 |x2 |x3 + <----------------------> + <--> ww <--> + i.left i.right + */ + + int x1 = i.left; + int x2 = x1 + w.width + hgap; + int x3; + if (t.width <= i.right + e.width) + x3 = x2 + w.width + hgap; + else + x3 = t.width - i.right - e.width; + int ww = t.width - i.right - i.left; + + int y1 = i.top; + int y2 = y1 + n.height + vgap; + int midh = Math.max(e.height, Math.max(w.height, c.height)); + int y3; + if (t.height <= i.bottom + s.height) + y3 = y2 + midh + vgap; + else + y3 = t.height - i.bottom - s.height; + int hh = y3-y2-vgap; + + setBounds(center, x2, y2, x3-x2-hgap, hh); + setBounds(my_north, x1, y1, ww, n.height); + setBounds(my_south, x1, y3, ww, s.height); + setBounds(my_west, x1, y2, w.width, hh); + setBounds(my_east, x3, y2, e.width, hh); + } +} + +/*************************************************************************/ + +/** + * Returns a string representation of this layout manager. + * + * @return A string representation of this object. + */ +public String +toString() +{ + return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]"; +} + +private void +setBounds(Component comp, int x, int y, int w, int h) +{ + if (comp == null) + return; + comp.setBounds(x, y, w, h); +} + +// Some constants for use with calcSize(). +private static final int MIN = 0; +private static final int MAX = 1; +private static final int PREF = 2; + +private Dimension +calcCompSize(Component comp, int what) +{ + if (comp == null || !comp.isVisible()) + return new Dimension(0, 0); + if (what == MIN) + return comp.getMinimumSize(); + else if (what == MAX) + return comp.getMaximumSize(); + return comp.getPreferredSize(); +} + +// This is a helper function used to compute the various sizes for +// this layout. +private Dimension +calcSize(Container target, int what) +{ + synchronized (target.getTreeLock ()) + { + Insets ins = target.getInsets(); + + ComponentOrientation orient = target.getComponentOrientation (); + boolean left_to_right = orient.isLeftToRight (); + + Component my_north = north; + Component my_east = east; + Component my_south = south; + Component my_west = west; + + // Note that we currently don't handle vertical layouts. Neither + // does JDK 1.3. + if (firstLine != null) + my_north = firstLine; + if (lastLine != null) + my_south = lastLine; + if (firstItem != null) + { + if (left_to_right) + my_west = firstItem; + else + my_east = firstItem; + } + if (lastItem != null) + { + if (left_to_right) + my_east = lastItem; + else + my_west = lastItem; + } + + Dimension ndim = calcCompSize(my_north, what); + Dimension sdim = calcCompSize(my_south, what); + Dimension edim = calcCompSize(my_east, what); + Dimension wdim = calcCompSize(my_west, what); + Dimension cdim = calcCompSize(center, what); + + int width = edim.width + cdim.width + wdim.width + (hgap * 2); + // check for overflow + if (width < edim.width || width < cdim.width || width < cdim.width) + width = Integer.MAX_VALUE; + + if (ndim.width > width) + width = ndim.width; + if (sdim.width > width) + width = sdim.width; + + width += (ins.left + ins.right); + + int height = edim.height; + if (cdim.height > height) + height = cdim.height; + if (wdim.height > height) + height = wdim.height; + + int addedHeight = height + (ndim.height + sdim.height + (vgap * 2) + + ins.top + ins.bottom); + // check for overflow + if (addedHeight < height) + height = Integer.MAX_VALUE; + else + height = addedHeight; + + return(new Dimension(width, height)); + } +} +} // class BorderLayout diff --git a/libjava/classpath/java/awt/BufferCapabilities.java b/libjava/classpath/java/awt/BufferCapabilities.java new file mode 100644 index 0000000..bba83dc --- /dev/null +++ b/libjava/classpath/java/awt/BufferCapabilities.java @@ -0,0 +1,253 @@ +/* BufferCapabilities.java -- double-buffering capabilities descriptor + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.image.BufferStrategy; + +/** + * A double-buffering capability descriptor. This class exposes + * details about the double-buffering algorithms used by image + * buffers. + * + * BufferCapabilities represents algorithms that involve at least two + * buffers but it can also specify so-called "multi-buffer" schemes + * involving more than two buffers. This class describes the + * capabilities of the front and back buffers as well as the results + * of "flipping" -- that is, what happens when an image is transferred + * from the back buffer to the front buffer. + * + * Flipping may or may not be supported or may be supported only in + * fullscreen mode. If it is not supported then "blitting" is implied + * -- that is, the contents of the back buffer are copied using a fast + * block transfer operation from the back buffer to the front buffer. + * + * The front buffer is the one that is displayed. + * + * @author Eric Blake (ebb9@email.byu.edu) + * + * @see BufferStrategy#getCapabilities() + * @see GraphicsConfiguration#getBufferCapabilities() + * + * @since 1.4 + */ +public class BufferCapabilities implements Cloneable +{ + /** + * A type-safe enumeration of buffer flipping results. + * + * @see AttributeValue + */ + public static final class FlipContents extends AttributeValue + { + /** + * The names of the different flipping results. + */ + private static final String[] NAMES + = { "undefined", "background", "prior", "copied" }; + + /** + * The contents of the back buffer are undefined after flipping. + */ + public static final FlipContents UNDEFINED = new FlipContents(0); + + /** + * The back buffer is cleared with the background color after + * flipping. + */ + public static final FlipContents BACKGROUND = new FlipContents(1); + + /** + * The back buffer contains the pre-flipping contents of the front + * buffer after flipping. In other words a true "flip" has been + * performed. + */ + public static final FlipContents PRIOR = new FlipContents(2); + + /** + * The back buffer has the same contents as the front buffer after + * flipping. + */ + public static final FlipContents COPIED = new FlipContents(3); + + /** + * Create a new flipping result descriptor. + * + * @param value the enumeration value + */ + private FlipContents(int value) + { + super(value, NAMES); + } + } + + /** + * Front buffer capabilities descriptor. + */ + private final ImageCapabilities front; + + /** + * Back buffer capabilities descriptor. + */ + private final ImageCapabilities back; + + /** + * Describes the results of a "flip" operation. + */ + private final FlipContents flip; + + /** + * Creates a buffer capabilities object. + * + * @param frontCaps front buffer capabilities descriptor + * @param backCaps back buffer capabilities descriptor + * @param flip the results of a flip operation or null if + * flipping is not supported + * + * @exception IllegalArgumentException if frontCaps or backCaps is + * null + */ + public BufferCapabilities(ImageCapabilities frontCaps, + ImageCapabilities backCaps, + FlipContents flip) + { + if (frontCaps == null || backCaps == null) + throw new IllegalArgumentException(); + this.front = frontCaps; + this.back = backCaps; + this.flip = flip; + } + + /** + * Retrieve the front buffer's image capabilities. + * + * @return the front buffer's image capabilities + */ + public ImageCapabilities getFrontBufferCapabilities() + { + return front; + } + + /** + * Retrieve the back buffer's image capabilities. + * + * @return the back buffer's image capabilities + */ + public ImageCapabilities getBackBufferCapabilities() + { + return back; + } + + /** + * Return whether or not flipping is supported. + * + * @return true if flipping is supported, false otherwise + */ + public boolean isPageFlipping() + { + return flip != null; + } + + /** + * Retrieve the result of a flipping operation. If this method + * returns null then flipping is not supported. This implies that + * "blitting", a fast block transfer, is used to copy the contents + * of the back buffer to the front buffer. Other possible return + * values are: + * <ul> + * <li><code>FlipContents.UNDEFINED</code> the contents of the + * back buffer are undefined after flipping.</li> + * <li><code>FlipContents.BACKGROUND</code> the contents of the + * back buffer are cleared to the background color after + * flipping.</li> + * <li><code>FlipContents.PRIOR</code> the back buffer contains + * the pre-flipping contents of the front * buffer after + * flipping.</li> + * <li><code>FlipContents.COPIED</code> the back buffer has the + * same contents as the front buffer after flipping.</li> + * </ul> + * + * @return the result of a flipping operation or null if flipping is + * not supported + */ + public FlipContents getFlipContents() + { + return flip; + } + + /** + * Returns true if flipping is only supported in fullscreen mode. + * + * @return true if flipping is only supported in fullscreen mode, + * false otherwise + */ + public boolean isFullScreenRequired() + { + return true; + } + + /** + * Returns true if flipping can involve more than two buffers. One + * or more intermediate buffers may be available in addition to the + * front and back buffers. + * + * @return true if there are more than two buffers available for + * flipping, false otherwise + */ + public boolean isMultiBufferAvailable() + { + return false; + } + + /** + * Clone this buffering capability descriptor. + * + * @return a clone of this buffer capability descriptor + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); + } + } +} diff --git a/libjava/classpath/java/awt/Button.java b/libjava/classpath/java/awt/Button.java new file mode 100644 index 0000000..90be1e5 --- /dev/null +++ b/libjava/classpath/java/awt/Button.java @@ -0,0 +1,466 @@ +/* Button.java -- AWT button widget + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.peer.ButtonPeer; +import java.lang.reflect.Array; +import java.util.EventListener; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleValue; + +/** + * This class provides a button widget for the AWT. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Tom Tromey (tromey@cygnus.com) + */ +public class Button extends Component + implements java.io.Serializable, Accessible +{ + +/* + * Static Variables + */ + +// FIXME: Need readObject/writeObject for serialization + +// Serialization version constant +private static final long serialVersionUID = -8774683716313001058L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial The action command name for this button. + * This is package-private to avoid an accessor method. + */ +String actionCommand; + +/** + * @serial The label for this button. + * This is package-private to avoid an accessor method. + */ +String label; + +// List of ActionListeners for this class. +private transient ActionListener action_listeners; + + /* + * The number used to generate the name returned by getName. + */ + private static transient long next_button_number; + + protected class AccessibleAWTButton extends AccessibleAWTComponent + implements AccessibleAction, AccessibleValue + { + protected AccessibleAWTButton() + { + // Do nothing here. + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleAction#getAccessibleActionCount() + */ + public int getAccessibleActionCount() + { + // Only 1 action possible + return 1; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int) + */ + public String getAccessibleActionDescription(int i) + { + // JDK 1.4.2 returns the string "click" for action 0. However, the API + // docs don't say what the string to be returned is, beyond being a + // description of the action. So we return the same thing for + // compatibility with 1.4.2. + if (i == 0) + return "click"; + return null; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleAction#doAccessibleAction(int) + */ + public boolean doAccessibleAction(int i) + { + if (i != 0) + return false; + processActionEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, actionCommand)); + return true; + } + + public String getAccessibleName() + { + return label; + } + + public AccessibleAction getAccessibleAction() + { + return this; + } + + public AccessibleValue getAccessibleValue() + { + return this; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue() + */ + public Number getCurrentAccessibleValue() + { + // Docs say return 1 if selected, but buttons can't be selected, right? + return new Integer(0); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number) + */ + public boolean setCurrentAccessibleValue(Number number) + { + // Since there's no selection with buttons, we're ignoring this. + // TODO someone who knows shoulw check this. + return false; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue() + */ + public Number getMinimumAccessibleValue() + { + return new Integer(0); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue() + */ + public Number getMaximumAccessibleValue() + { + return new Integer(0); + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.PUSH_BUTTON; + } + } + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>Button</code> with no label. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true + */ +public +Button() +{ + this(""); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Button</code> with the specified + * label. The action command name is also initialized to this value. + * + * @param label The label to display on the button. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true + */ +public +Button(String label) +{ + this.label = label; + actionCommand = label; + + if (GraphicsEnvironment.isHeadless ()) + throw new HeadlessException (); +} + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * Returns the label for this button. + * + * @return The label for this button. + */ +public String +getLabel() +{ + return(label); +} + +/*************************************************************************/ + +/** + * Sets the label for this button to the specified value. + * + * @param label The new label for this button. + */ +public synchronized void +setLabel(String label) +{ + this.label = label; + actionCommand = label; + if (peer != null) + { + ButtonPeer bp = (ButtonPeer) peer; + bp.setLabel (label); + } +} + +/*************************************************************************/ + +/** + * Returns the action command name for this button. + * + * @return The action command name for this button. + */ +public String +getActionCommand() +{ + return(actionCommand); +} + +/*************************************************************************/ + +/** + * Sets the action command name for this button to the specified value. + * + * @param actionCommand The new action command name. + */ +public void +setActionCommand(String actionCommand) +{ + this.actionCommand = actionCommand == null ? label : actionCommand; +} + +/*************************************************************************/ + +/** + * Adds a new entry to the list of listeners that will receive + * action events from this button. + * + * @param listener The listener to add. + */ +public synchronized void +addActionListener(ActionListener listener) +{ + action_listeners = AWTEventMulticaster.add(action_listeners, listener); +} + +/*************************************************************************/ + +/** + * Removes the specified listener from the list of listeners that will + * receive action events from this button. + * + * @param listener The listener to remove. + */ +public synchronized void +removeActionListener(ActionListener listener) +{ + action_listeners = AWTEventMulticaster.remove(action_listeners, listener); +} + + /** + * Returns all added <code>ActionListener</code> objects. + * + * @return an array of listeners + * + * @since 1.4 + */ + public synchronized ActionListener[] getActionListeners() + { + return (ActionListener[]) + AWTEventMulticaster.getListeners(action_listeners, + ActionListener.class); + } + +/** + * Returns all registered EventListers of the given listenerType. + * listenerType must be a subclass of EventListener, or a + * ClassClassException is thrown. + * + * @param listenerType the listener type to return + * + * @return an array of listeners + * + * @exception ClassCastException If listenerType doesn't specify a class or + * interface that implements @see java.util.EventListener. + * + * @since 1.3 + */ + public EventListener[] getListeners(Class listenerType) + { + if (listenerType == ActionListener.class) + return getActionListeners(); + return (EventListener[]) Array.newInstance(listenerType, 0); + } + +/*************************************************************************/ + +/** + * Notifies this button that it should create its native peer object. + */ +public void +addNotify() +{ + if (peer == null) + peer = getToolkit ().createButton (this); + super.addNotify(); +} + +/*************************************************************************/ + +/** + * Processes an event for this button. If the specified event is an + * instance of <code>ActionEvent</code>, then the + * <code>processActionEvent()</code> method is called to dispatch it + * to any registered listeners. Otherwise, the superclass method + * will be invoked. Note that this method will not be called at all + * unless <code>ActionEvent</code>'s are enabled. This will be done + * implicitly if any listeners are added. + * + * @param event The event to process. + */ +protected void +processEvent(AWTEvent event) +{ + if (event instanceof ActionEvent) + processActionEvent((ActionEvent)event); + else + super.processEvent(event); +} + +/*************************************************************************/ + +/** + * This method dispatches an action event for this button to any + * registered listeners. + * + * @param event The event to process. + */ +protected void +processActionEvent(ActionEvent event) +{ + if (action_listeners != null) + action_listeners.actionPerformed(event); +} + +void +dispatchEventImpl(AWTEvent e) +{ + if (e.id <= ActionEvent.ACTION_LAST + && e.id >= ActionEvent.ACTION_FIRST + && (action_listeners != null + || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0)) + processEvent(e); + else + super.dispatchEventImpl(e); +} + +/*************************************************************************/ + +/** + * Returns a debugging string for this button. + * + * @return A debugging string for this button. + */ +protected String +paramString() +{ + return getName () + "," + getX () + "," + getY () + "," + + getWidth () + "x" + getHeight () + ",label=" + getLabel (); +} + +/** + * Gets the AccessibleContext associated with this <code>Button</code>. + * The context is created, if necessary. + * + * @return the associated context + */ +public AccessibleContext getAccessibleContext() +{ + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTButton(); + return accessibleContext; +} + + /** + * Generate a unique name for this button. + * + * @return A unique name for this button. + */ + String generateName () + { + return "button" + getUniqueLong (); + } + + private static synchronized long getUniqueLong () + { + return next_button_number++; + } + +} // class Button + diff --git a/libjava/classpath/java/awt/Canvas.java b/libjava/classpath/java/awt/Canvas.java new file mode 100644 index 0000000..fe2f854 --- /dev/null +++ b/libjava/classpath/java/awt/Canvas.java @@ -0,0 +1,354 @@ +/* Canvas.java -- + Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.image.BufferStrategy; +import java.awt.peer.ComponentPeer; +import java.io.Serializable; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * The <code>Canvas</code> component provides a blank rectangular + * area, which the client application can use for drawing and for + * capturing events. By overriding the <code>paint()</code> method, + * the canvas can be used for anything from simple line drawings to + * full-scale custom components. + * + * @author Original author unknown + * @author Tom Tromey (tromey@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.0 + */ + +public class Canvas + extends Component + implements Serializable, Accessible +{ + + /** + * Compatible with Sun's JDK. + */ + private static final long serialVersionUID = -2284879212465893870L; + + /** + * The graphics configuration associated with the canvas. + */ + transient GraphicsConfiguration graphicsConfiguration; + + /** + * The buffer strategy associated with this canvas. + */ + transient BufferStrategy bufferStrategy; + + /** + * Initializes a new instance of <code>Canvas</code>. + */ + public Canvas() + { + } + + /** + * Initializes a new instance of <code>Canvas</code> + * with the supplied graphics configuration. + * + * @param graphicsConfiguration the graphics configuration to use + * for this particular canvas. + */ + public Canvas(GraphicsConfiguration graphicsConfiguration) + { + this.graphicsConfiguration = graphicsConfiguration; + } + + GraphicsConfiguration getGraphicsConfigurationImpl() + { + if (graphicsConfiguration != null) + return graphicsConfiguration; + return super.getGraphicsConfigurationImpl(); + } + + /** + * Creates the native peer for this object. + */ + public void addNotify() + { + if (peer == null) + peer = (ComponentPeer) getToolkit().createCanvas(this); + super.addNotify(); + } + + /** + * Repaints the canvas window. This method should be overridden by + * a subclass to do something useful, as this method simply paints + * the window with the background color. + * + * @param gfx the <code>Graphics</code> to use for painting + */ + public void paint(Graphics gfx) + { + /* This implementation doesn't make much sense since the filling + of background color is guaranteed for heavyweight components + such as this. But there's no need to worry, since paint() is + usually overridden anyway. */ + gfx.setColor(getBackground()); + Dimension size = getSize(); + gfx.fillRect(0, 0, size.width, size.height); + } + + /** + * This class provides accessibility support for the canvas. + */ + protected class AccessibleAWTCanvas + extends AccessibleAWTComponent + { + /** + * For compatability with Sun's JDK + */ + private static final long serialVersionUID = -6325592262103146699L; + + /** + * Constructor for the accessible canvas. + */ + protected AccessibleAWTCanvas() + { + } + + /** + * Returns the accessible role for the canvas. + * + * @return an instance of <code>AccessibleRole</code>, describing + * the role of the canvas. + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.CANVAS; + } + + } + + /** + * Gets the AccessibleContext associated with this <code>Canvas</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTCanvas(); + return accessibleContext; + } + + /** + * A BltBufferStrategy for canvases. + */ + private class CanvasBltBufferStrategy extends BltBufferStrategy + { + /** + * Creates a block transfer strategy for this canvas. + * + * @param numBuffers the number of buffers in this strategy + * @param accelerated true if the buffer should be accelerated, + * false otherwise + */ + CanvasBltBufferStrategy(int numBuffers, boolean accelerated) + { + super(numBuffers, + new BufferCapabilities(new ImageCapabilities(accelerated), + new ImageCapabilities(accelerated), + BufferCapabilities.FlipContents.COPIED)); + } + } + + /** + * A FlipBufferStrategy for canvases. + */ + private class CanvasFlipBufferStrategy extends FlipBufferStrategy + { + /** + * Creates a flip buffer strategy for this canvas. + * + * @param numBuffers the number of buffers in this strategy + * + * @throws AWTException if the requested number of buffers is not + * supported + */ + CanvasFlipBufferStrategy(int numBuffers) + throws AWTException + { + super(numBuffers, + new BufferCapabilities(new ImageCapabilities(true), + new ImageCapabilities(true), + BufferCapabilities.FlipContents.COPIED)); + } + } + + /** + * Creates a buffering strategy that manages how this canvas is + * repainted. This method attempts to create the optimum strategy + * based on the desired number of buffers. Hardware or software + * acceleration may be used. + * + * createBufferStrategy attempts different levels of optimization, + * but guarantees that some strategy with the requested number of + * buffers will be created even if it is not optimal. First it + * attempts to create a page flipping strategy, then an accelerated + * blitting strategy, then an unaccelerated blitting strategy. + * + * Calling this method causes any existing buffer strategy to be + * destroyed. + * + * @param numBuffers the number of buffers in this strategy + * + * @throws IllegalArgumentException if requested number of buffers + * is less than one + * @throws IllegalStateException if this canvas is not displayable + * + * @since 1.4 + */ + public void createBufferStrategy(int numBuffers) + { + if (numBuffers < 1) + throw new IllegalArgumentException("Canvas.createBufferStrategy: number" + + " of buffers is less than one"); + + if (!isDisplayable()) + throw new IllegalStateException("Canvas.createBufferStrategy: canvas is" + + " not displayable"); + + BufferStrategy newStrategy = null; + + // try a flipping strategy + try + { + newStrategy = new CanvasFlipBufferStrategy(numBuffers); + } + catch (AWTException e) + { + } + + // fall back to an accelerated blitting strategy + if (newStrategy == null) + newStrategy = new CanvasBltBufferStrategy(numBuffers, true); + + bufferStrategy = newStrategy; + } + + /** + * Creates a buffering strategy that manages how this canvas is + * repainted. This method attempts to create a strategy based on + * the specified capabilities and throws an exception if the + * requested strategy is not supported. + * + * Calling this method causes any existing buffer strategy to be + * destroyed. + * + * @param numBuffers the number of buffers in this strategy + * @param caps the requested buffering capabilities + * + * @throws AWTException if the requested capabilities are not + * supported + * @throws IllegalArgumentException if requested number of buffers + * is less than one or if caps is null + * + * @since 1.4 + */ + public void createBufferStrategy(int numBuffers, + BufferCapabilities caps) + { + if (numBuffers < 1) + throw new IllegalArgumentException("Canvas.createBufferStrategy: number" + + " of buffers is less than one"); + + if (caps == null) + throw new IllegalArgumentException("Canvas.createBufferStrategy:" + + " capabilities object is null"); + + // a flipping strategy was requested + if (caps.isPageFlipping()) + { + try + { + bufferStrategy = new CanvasFlipBufferStrategy(numBuffers); + } + catch (AWTException e) + { + } + } + else + bufferStrategy = new CanvasBltBufferStrategy(numBuffers, true); + } + + /** + * Returns the buffer strategy used by the canvas. + * + * @return the buffer strategy. + * @since 1.4 + */ + public BufferStrategy getBufferStrategy() + { + return bufferStrategy; + } + + /** + * Updates the canvas in response to a request to + * <code>repaint()</code> it. The canvas is cleared + * with the current background colour, before <code>paint()</code> + * is called to add the new contents. Subclasses + * which override this method should either call this + * method via <code>super.update(graphics)</code> or re-implement + * this behaviour, so as to ensure that the canvas is + * clear before painting takes place. + * + * @param graphics the graphics context. + */ + public void update(Graphics graphics) + { + Dimension size; + + /* Clear the canvas */ + size = getSize(); + graphics.clearRect(0, 0, size.width, size.height); + /* Call the paint method */ + paint(graphics); + } +} diff --git a/libjava/classpath/java/awt/CardLayout.java b/libjava/classpath/java/awt/CardLayout.java new file mode 100644 index 0000000..8582c5f0 --- /dev/null +++ b/libjava/classpath/java/awt/CardLayout.java @@ -0,0 +1,483 @@ +/* CardLayout.java -- Card-based layout engine + Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.io.Serializable; +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * This class implements a card-based layout scheme. Each included + * component is treated as a card. Only one card can be shown at a + * time. This class includes methods for changing which card is + * shown. + * + * @author Tom Tromey (tromey@redhat.com) + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class CardLayout implements LayoutManager2, Serializable +{ + private static final long serialVersionUID = -4328196481005934313L; + + /** + * Initializes a new instance of <code>CardLayout</code> with horizontal + * and vertical gaps of 0. + */ + public CardLayout () + { + this (0, 0); + } + + /** + * Create a new <code>CardLayout</code> object with the specified + * horizontal and vertical gaps. + * + * @param hgap The horizontal gap + * @param vgap The vertical gap + */ + public CardLayout (int hgap, int vgap) + { + this.hgap = hgap; + this.vgap = vgap; + this.tab = new Hashtable (); + } + + /** + * Add a new component to the layout. The constraint must be a + * string which is used to name the component. This string can + * later be used to refer to the particular component. + * + * @param comp The component to add + * @param constraints The name by which the component can later be called + * + * @exception IllegalArgumentException If `constraints' is not a + * <code>String</code> + */ + public void addLayoutComponent (Component comp, Object constraints) + { + if (! (constraints instanceof String)) + throw new IllegalArgumentException ("Object " + constraints + + " is not a string"); + addLayoutComponent ((String) constraints, comp); + } + + /** + * Add a new component to the layout. The name can be used later + * to refer to the component. + * + * @param name The name by which the component can later be called + * @param comp The component to add + * + * @deprecated This method is deprecated in favor of + * <code>addLayoutComponent(Component, Object)</code>. + */ + public void addLayoutComponent (String name, Component comp) + { + tab.put (name, comp); + // First component added is the default component. + comp.setVisible(tab.size() == 1); + } + + /** + * Cause the first component in the container to be displayed. + * + * @param parent The parent container + */ + public void first (Container parent) + { + gotoComponent (parent, FIRST); + } + + /** + * Return this layout manager's horizontal gap. + * + * @return the horizontal gap + */ + public int getHgap () + { + return hgap; + } + + /** + * Return this layout manager's x alignment. This method always + * returns Component.CENTER_ALIGNMENT. + * + * @param parent Container using this layout manager instance + * + * @return the x-axis alignment + */ + public float getLayoutAlignmentX (Container parent) + { + return Component.CENTER_ALIGNMENT; + } + + /** + * Returns this layout manager's y alignment. This method always + * returns Component.CENTER_ALIGNMENT. + * + * @param parent Container using this layout manager instance + * + * @return the y-axis alignment + */ + public float getLayoutAlignmentY (Container parent) + { + return Component.CENTER_ALIGNMENT; + } + + /** + * Return this layout manager's vertical gap. + * + * @return the vertical gap + */ + public int getVgap () + { + return vgap; + } + + /** + * Invalidate this layout manager's state. + */ + public void invalidateLayout (Container target) + { + // Do nothing. + } + + /** + * Cause the last component in the container to be displayed. + * + * @param parent The parent container + */ + public void last (Container parent) + { + gotoComponent (parent, LAST); + } + + /** + * Lays out the container. This is done by resizing the child components + * to be the same size as the parent, less insets and gaps. + * + * @param parent The parent container. + */ + public void layoutContainer (Container parent) + { + synchronized (parent.getTreeLock ()) + { + int width = parent.width; + int height = parent.height; + + Insets ins = parent.getInsets (); + + int num = parent.ncomponents; + Component[] comps = parent.component; + + int x = ins.left + hgap; + int y = ins.top + vgap; + width = width - 2 * hgap - ins.left - ins.right; + height = height - 2 * vgap - ins.top - ins.bottom; + + for (int i = 0; i < num; ++i) + comps[i].setBounds (x, y, width, height); + } + } + + /** + * Get the maximum layout size of the container. + * + * @param target The parent container + * + * @return the maximum layout size + */ + public Dimension maximumLayoutSize (Container target) + { + // The JCL says that this returns Integer.MAX_VALUE for both + // dimensions. But that just seems wrong to me. + return getSize (target, MAX); + } + + /** + * Get the minimum layout size of the container. + * + * @param target The parent container + * + * @return the minimum layout size + */ + public Dimension minimumLayoutSize (Container target) + { + return getSize (target, MIN); + } + + /** + * Cause the next component in the container to be displayed. If + * this current card is the last one in the deck, the first + * component is displayed. + * + * @param parent The parent container + */ + public void next (Container parent) + { + gotoComponent (parent, NEXT); + } + + /** + * Get the preferred layout size of the container. + * + * @param parent The parent container + * + * @return the preferred layout size + */ + public Dimension preferredLayoutSize (Container parent) + { + return getSize (parent, PREF); + } + + /** + * Cause the previous component in the container to be displayed. + * If this current card is the first one in the deck, the last + * component is displayed. + * + * @param parent The parent container + */ + public void previous (Container parent) + { + gotoComponent (parent, PREV); + } + + /** + * Remove the indicated component from this layout manager. + * + * @param comp The component to remove + */ + public void removeLayoutComponent (Component comp) + { + Enumeration e = tab.keys (); + while (e.hasMoreElements ()) + { + Object key = e.nextElement (); + if (tab.get (key) == comp) + { + tab.remove (key); + Container parent = comp.getParent(); + next(parent); + break; + } + } + } + + /** + * Set this layout manager's horizontal gap. + * + * @param hgap The new gap + */ + public void setHgap (int hgap) + { + this.hgap = hgap; + } + + /** + * Set this layout manager's vertical gap. + * + * @param vgap The new gap + */ + public void setVgap (int vgap) + { + this.vgap = vgap; + } + + /** + * Cause the named component to be shown. If the component name is + * unknown, this method does nothing. + * + * @param parent The parent container + * @param name The name of the component to show + */ + public void show (Container parent, String name) + { + Object target = tab.get (name); + if (target != null) + { + int num = parent.ncomponents; + // This is more efficient than calling getComponents(). + Component[] comps = parent.component; + for (int i = 0; i < num; ++i) + { + if (comps[i].isVisible()) + { + if (target == comps[i]) + return; + comps[i].setVisible (false); + } + } + ((Component) target).setVisible (true); + } + } + + /** + * Returns a string representation of this layout manager. + * + * @return A string representation of this object. + */ + public String toString () + { + return getClass ().getName () + "[" + hgap + "," + vgap + "]"; + } + + /** + * This implements first(), last(), next(), and previous(). + * + * @param parent The parent container + * @param what The type of goto: FIRST, LAST, NEXT or PREV + */ + private void gotoComponent (Container parent, int what) + { + synchronized (parent.getTreeLock ()) + { + int num = parent.ncomponents; + // This is more efficient than calling getComponents(). + Component[] comps = parent.component; + + if (num == 1) + { + comps[0].setVisible(true); + return; + } + + int choice = -1; + + if (what == FIRST) + choice = 0; + else if (what == LAST) + choice = num - 1; + + for (int i = 0; i < num; ++i) + { + if (comps[i].isVisible ()) + { + if (what == NEXT) + { + choice = i + 1; + if (choice == num) + choice = 0; + } + else if (what == PREV) + { + choice = i - 1; + if (choice < 0) + choice = num - 1; + } + else if (choice == i) + { + // Do nothing if we're already looking at the right + // component. + return; + } + comps[i].setVisible (false); + + if (choice >= 0) + break; + } + } + + if (choice >= 0 && choice < num) + comps[choice].setVisible (true); + } + } + + // Compute the size according to WHAT. + private Dimension getSize (Container parent, int what) + { + synchronized (parent.getTreeLock ()) + { + int w = 0, h = 0, num = parent.ncomponents; + Component[] comps = parent.component; + + for (int i = 0; i < num; ++i) + { + Dimension d; + + if (what == MIN) + d = comps[i].getMinimumSize (); + else if (what == MAX) + d = comps[i].getMaximumSize (); + else + d = comps[i].getPreferredSize (); + + w = Math.max (d.width, w); + h = Math.max (d.height, h); + } + + Insets i = parent.getInsets (); + w += 2 * hgap + i.right + i.left; + h += 2 * vgap + i.bottom + i.top; + + // Handle overflow. + if (w < 0) + w = Integer.MAX_VALUE; + if (h < 0) + h = Integer.MAX_VALUE; + + return new Dimension (w, h); + } + } + + /** + * @serial Horizontal gap value. + */ + private int hgap; + + /** + * @serial Vertical gap value. + */ + private int vgap; + + /** + * @serial Table of named components. + */ + private Hashtable tab; + + // These constants are used by the private gotoComponent method. + private static final int FIRST = 0; + private static final int LAST = 1; + private static final int NEXT = 2; + private static final int PREV = 3; + + // These constants are used by the private getSize method. + private static final int MIN = 0; + private static final int MAX = 1; + private static final int PREF = 2; +} diff --git a/libjava/classpath/java/awt/Checkbox.java b/libjava/classpath/java/awt/Checkbox.java new file mode 100644 index 0000000..cd39ad4 --- /dev/null +++ b/libjava/classpath/java/awt/Checkbox.java @@ -0,0 +1,649 @@ +/* Checkbox.java -- An AWT checkbox widget + Copyright (C) 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.peer.CheckboxPeer; +import java.io.Serializable; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleValue; + +/** + * This class implements a component which has an on/off state. Two + * or more Checkboxes can be grouped by a CheckboxGroup. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Tom Tromey (tromey@redhat.com) + */ +public class Checkbox extends Component + implements ItemSelectable, Accessible, Serializable +{ + +// FIXME: Need readObject/writeObject for this. + +/* + * Static Variables + */ + +// Serialization Constant +private static final long serialVersionUID = 7270714317450821763L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial The checkbox group for this checkbox. + */ +private CheckboxGroup group; + +/** + * @serial The label on this checkbox. + */ +private String label; + +/** + * @serial The state of this checkbox. + * This is package-private to avoid an accessor method. + */ +boolean state; + +// The list of listeners for this object. +private transient ItemListener item_listeners; + + /* + * The number used to generate the name returned by getName. + */ + private static transient long next_checkbox_number; + +/** + * This class provides accessibility support for the + * checkbox. + * + * @author Jerry Quinn (jlquinn@optonline.net) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ +protected class AccessibleAWTCheckbox + extends AccessibleAWTComponent + implements ItemListener, AccessibleAction, AccessibleValue +{ + /** + * Serialization constant to match JDK 1.5 + */ + private static final long serialVersionUID = 7881579233144754107L; + + /** + * Default constructor which simply calls the + * super class for generic component accessibility + * handling. + */ + public AccessibleAWTCheckbox() + { + super(); + } + + /** + * Captures changes to the state of the checkbox and + * fires appropriate accessible property change events. + * + * @param event the event fired. + * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent) + */ + public void itemStateChanged(ItemEvent event) + { + firePropertyChange(ACCESSIBLE_STATE_PROPERTY, + state ? null : AccessibleState.CHECKED, + state ? AccessibleState.CHECKED : null); + } + + /** + * Returns an implementation of the <code>AccessibleAction</code> + * interface for this accessible object. In this case, the + * current instance is simply returned (with a more appropriate + * type), as it also implements the accessible action as well as + * the context. + * + * @return the accessible action associated with this context. + * @see javax.accessibility.AccessibleAction + */ + public AccessibleAction getAccessibleAction() + { + return this; + } + + /** + * Returns an implementation of the <code>AccessibleValue</code> + * interface for this accessible object. In this case, the + * current instance is simply returned (with a more appropriate + * type), as it also implements the accessible value as well as + * the context. + * + * @return the accessible value associated with this context. + * @see javax.accessibility.AccessibleValue + */ + public AccessibleValue getAccessibleValue() + { + return this; + } + + /* + * The following methods are implemented in the JDK (up to + * 1.5) as stubs. We do likewise here. + */ + + /** + * Returns the number of actions associated with this accessible + * object. This default implementation returns 0. + * + * @return the number of accessible actions available. + * @see javax.accessibility.AccessibleAction#getAccessibleActionCount() + */ + public int getAccessibleActionCount() + { + // 1.4.1 and 1.5 do this + return 0; + } + + /** + * Returns a description of the action with the supplied id. + * This default implementation always returns null. + * + * @param i the id of the action whose description should be + * retrieved. + * @return a <code>String</code> describing the action. + * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int) + */ + public String getAccessibleActionDescription(int i) + { + // 1.5 does this + return null; + } + + /** + * Executes the action with the specified id. This + * default implementation simply returns false. + * + * @param i the id of the action to perform. + * @return true if the action was performed. + * @see javax.accessibility.AccessibleAction#doAccessibleAction(int) + */ + public boolean doAccessibleAction(int i) + { + // 1.5 does this + return false; + } + + /** + * Returns the current value of this accessible object. + * If no value has been set, null is returned. This + * default implementation always returns null, regardless. + * + * @return the numeric value of this object, or null if + * no value has been set. + * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue() + */ + public Number getCurrentAccessibleValue() + { + // 1.5 does this + return null; + } + + /** + * Sets the current value of this accessible object + * to that supplied. In this default implementation, + * the value is never set and the method always returns + * false. + * + * @param number the new accessible value. + * @return true if the value was set. + * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number) + */ + public boolean setCurrentAccessibleValue(Number number) + { + // 1.5 does this + return false; + } + + /** + * Returns the minimum acceptable accessible value used + * by this object, or null if no minimum value exists. + * This default implementation always returns null. + * + * @return the minimum acceptable accessible value, or null + * if there is no minimum. + * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue() + */ + public Number getMinimumAccessibleValue() + { + return null; + } + + /** + * Returns the maximum acceptable accessible value used + * by this object, or null if no maximum value exists. + * This default implementation always returns null. + * + * @return the maximum acceptable accessible value, or null + * if there is no maximum. + * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue() + */ + public Number getMaximumAccessibleValue() + { + return null; + } + + /** + * Returns the role of this accessible object. + * + * @return the instance of <code>AccessibleRole</code>, + * which describes this object. + * @see javax.accessibility.AccessibleRole + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.CHECK_BOX; + } + + /** + * Returns the state set of this accessible object. + * + * @return a set of <code>AccessibleState</code>s + * which represent the current state of the + * accessible object. + * @see javax.accessibility.AccessibleState + * @see javax.accessibility.AccessibleStateSet + */ + public AccessibleStateSet getAccessibleStateSet() + { + AccessibleStateSet set = super.getAccessibleStateSet(); + if (state) + set.add(AccessibleState.CHECKED); + return set; + } + +} + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>Checkbox</code> with no label, + * an initial state of off, and that is not part of any checkbox group. + */ +public +Checkbox() +{ + this("", false, null); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Checkbox</code> with the specified + * label, an initial state of off, and that is not part of any checkbox + * group. + * + * @param label The label for this checkbox. + */ +public +Checkbox(String label) +{ + this(label, false, null); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Checkbox</code> with the specified + * label and initial state, and that is not part of any checkbox + * group. + * + * @param label The label for this checkbox. + * @param state The initial state of the checkbox, <code>true</code> for + * on, <code>false</code> for off. + */ +public +Checkbox(String label, boolean state) +{ + this(label, state, null); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Checkbox</code> with the specified + * label, initial state, and checkbox group. + * + * @param label The label for this checkbox. + * @param group The checkbox group for this box, or <code>null</code> + * if there is no checkbox group. + * @param state The initial state of the checkbox, <code>true</code> for + * on, <code>false</code> for off. + */ +public +Checkbox(String label, CheckboxGroup group, boolean state) +{ + this(label, state, group); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Checkbox</code> with the specified + * label, initial state, and checkbox group. + * + * @param label The label for this checkbox. + * @param state The initial state of the checkbox, <code>true</code> for + * on, <code>false</code> for off. + * @param group The checkbox group for this box, or <code>null</code> + * if there is no checkbox group. + */ +public +Checkbox(String label, boolean state, CheckboxGroup group) +{ + this.label = label; + this.state = state; + this.group = group; +} + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * Returns the label for this checkbox. + * + * @return The label for this checkbox. + */ +public String +getLabel() +{ + return(label); +} + +/*************************************************************************/ + +/** + * Sets the label for this checkbox to the specified value. + * + * @param label The new checkbox label. + */ +public synchronized void +setLabel(String label) +{ + this.label = label; + if (peer != null) + { + CheckboxPeer cp = (CheckboxPeer) peer; + cp.setLabel(label); + } +} + +/*************************************************************************/ + +/** + * Returns the state of this checkbox. + * + * @return The state of this checkbox, which will be <code>true</code> for + * on and <code>false</code> for off. + */ +public boolean +getState() +{ + return(state); +} + +/*************************************************************************/ + +/** + * Sets the state of this checkbox to the specified value. + * + * @param state The new state of the checkbox, which will be <code>true</code> + * for on or <code>false</code> for off. + */ +public synchronized void +setState(boolean state) +{ + this.state = state; + if (peer != null) + { + CheckboxPeer cp = (CheckboxPeer) peer; + cp.setState (state); + } +} + +/*************************************************************************/ + +/** + * Returns an array of length one containing the checkbox label if this + * checkbox is selected. Otherwise <code>null</code> is returned. + * + * @return The selection state of this checkbox. + */ +public Object[] +getSelectedObjects() +{ + if (state == false) + return(null); + + Object[] objs = new Object[1]; + objs[0] = label; + + return(objs); +} + +/*************************************************************************/ + +/** + * Returns the checkbox group this object is a member of, if any. + * + * @return This object's checkbox group, of <code>null</code> if it is + * not a member of any group. + */ +public CheckboxGroup +getCheckboxGroup() +{ + return(group); +} + +/*************************************************************************/ + +/** + * Sets this object's checkbox group to the specified group. + * + * @param group The new checkbox group, or <code>null</code> to make this + * object part of no checkbox group. + */ +public synchronized void +setCheckboxGroup(CheckboxGroup group) +{ + this.group = group; + if (peer != null) + { + CheckboxPeer cp = (CheckboxPeer) peer; + cp.setCheckboxGroup (group); + } +} + +/*************************************************************************/ + +/** + * Creates this object's native peer. + */ +public void +addNotify() +{ + if (peer == null) + peer = getToolkit ().createCheckbox (this); + super.addNotify (); +} + + public ItemListener[] getItemListeners () + { + return (ItemListener[]) + AWTEventMulticaster.getListeners (item_listeners, ItemListener.class); + } + +/** + * Adds a new listeners to the list of registered listeners for this object. + * + * @param listener The new listener to add. + */ +public synchronized void +addItemListener(ItemListener listener) +{ + item_listeners = AWTEventMulticaster.add(item_listeners, listener); +} + +/*************************************************************************/ + +/** + * Removes a listener from the list of registered listeners for this object. + * + * @param listener The listener to remove. + */ +public synchronized void +removeItemListener(ItemListener listener) +{ + item_listeners = AWTEventMulticaster.remove(item_listeners, listener); +} + +/*************************************************************************/ + +/** + * Processes this event by calling <code>processItemEvent()</code> if it + * is any instance of <code>ItemEvent</code>. Otherwise it is passed to + * the superclass for processing. + * + * @param event The event to process. + */ +protected void +processEvent(AWTEvent event) +{ + if (event instanceof ItemEvent) + processItemEvent((ItemEvent)event); + else + super.processEvent(event); +} + +/*************************************************************************/ + +/** + * Processes this event by dispatching it to any registered listeners. + * + * @param event The <code>ItemEvent</code> to process. + */ +protected void +processItemEvent(ItemEvent event) +{ + if (item_listeners != null) + item_listeners.itemStateChanged(event); +} + +void +dispatchEventImpl(AWTEvent e) +{ + if (e.id <= ItemEvent.ITEM_LAST + && e.id >= ItemEvent.ITEM_FIRST + && (item_listeners != null + || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0)) + processEvent(e); + else + super.dispatchEventImpl(e); +} + +/*************************************************************************/ + +/** + * Returns a debugging string for this object. + */ +protected String +paramString() +{ + return ("label=" + label + ",state=" + state + ",group=" + group + + "," + super.paramString()); +} + +/** + * Gets the AccessibleContext associated with this <code>Checkbox</code>. + * The context is created, if necessary. + * + * @return the associated context + */ +public AccessibleContext getAccessibleContext() +{ + /* Create the context if this is the first request */ + if (accessibleContext == null) + { + AccessibleAWTCheckbox ac = new AccessibleAWTCheckbox(); + accessibleContext = ac; + addItemListener(ac); + } + return accessibleContext; +} + + /** + * Generate a unique name for this checkbox. + * + * @return A unique name for this checkbox. + */ + String generateName() + { + return "checkbox" + getUniqueLong(); + } + + private static synchronized long getUniqueLong() + { + return next_checkbox_number++; + } +} diff --git a/libjava/classpath/java/awt/CheckboxGroup.java b/libjava/classpath/java/awt/CheckboxGroup.java new file mode 100644 index 0000000..31b573e --- /dev/null +++ b/libjava/classpath/java/awt/CheckboxGroup.java @@ -0,0 +1,173 @@ +/* CheckboxGroup.java -- A grouping class for checkboxes. + Copyright (C) 1999, 2000, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This class if for combining checkboxes into groups so that only + * one checkbox in the group can be selected at any one time. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Tom Tromey (tromey@redhat.com) + */ +public class CheckboxGroup implements java.io.Serializable +{ + +/* + * Static Variables + */ + +// Serialization constant +private static final long serialVersionUID = 3729780091441768983L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial The currently selected checkbox. + */ +private Checkbox selectedCheckbox; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>CheckboxGroup</code>. + */ +public +CheckboxGroup() +{ +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns the currently selected checkbox, or <code>null</code> if none + * of the checkboxes in this group are selected. + * + * @return The selected checkbox. + */ +public Checkbox +getSelectedCheckbox() +{ + return getCurrent (); +} + +/*************************************************************************/ + +/** + * Returns the currently selected checkbox, or <code>null</code> if none + * of the checkboxes in this group are selected. + * + * @return The selected checkbox. + * + * @deprecated This method is deprecated in favor of + * <code>getSelectedCheckbox()</code>. + */ +public Checkbox +getCurrent() +{ + return(selectedCheckbox); +} + +/*************************************************************************/ + +/** + * This method sets the specified checkbox to be the selected on in this + * group, and unsets all others. + * + * @param selectedCheckbox The new selected checkbox. + */ +public void +setSelectedCheckbox(Checkbox selectedCheckbox) +{ + setCurrent (selectedCheckbox); +} + +/*************************************************************************/ + +/** + * This method sets the specified checkbox to be the selected on in this + * group, and unsets all others. + * + * @param selectedCheckbox The new selected checkbox. + * + * @deprecated This method is deprecated in favor of + * <code>setSelectedCheckbox()</code>. + */ +public void +setCurrent(Checkbox selectedCheckbox) +{ + if (this.selectedCheckbox != null) + { + if (this.selectedCheckbox.getCheckboxGroup() != this) + return; + + this.selectedCheckbox.setState(false); + } + + this.selectedCheckbox = selectedCheckbox; + if (selectedCheckbox != null) + selectedCheckbox.setState(true); +} + +/*************************************************************************/ + +/** + * Returns a string representation of this checkbox group. + * + * @return A string representation of this checkbox group. + */ +public String +toString() +{ + return(getClass().getName() + "[selectedCheckbox=" + selectedCheckbox + "]"); +} + +} // class CheckboxGroup + diff --git a/libjava/classpath/java/awt/CheckboxMenuItem.java b/libjava/classpath/java/awt/CheckboxMenuItem.java new file mode 100644 index 0000000..5e446b8 --- /dev/null +++ b/libjava/classpath/java/awt/CheckboxMenuItem.java @@ -0,0 +1,355 @@ +/* CheckboxMenuItem.java -- A menu option with a checkbox on it. + Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.peer.CheckboxMenuItemPeer; +import java.util.EventListener; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleValue; + +/** + * This class implements a menu item that has a checkbox on it indicating + * the selected state of some option. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Tom Tromey (tromey@redhat.com) + */ +public class CheckboxMenuItem extends MenuItem + implements ItemSelectable, Accessible +{ + +/* + * Static Variables + */ + +// Serialization constant +private static final long serialVersionUID = 6190621106981774043L; + +/* + * Instance Variables + */ + +/** + * @serial The state of the checkbox, with <code>true</code> being on and + * <code>false</code> being off. + */ +private boolean state; + +// List of registered ItemListeners +private transient ItemListener item_listeners; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>CheckboxMenuItem</code> with no + * label and an initial state of off. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true. + */ +public +CheckboxMenuItem() +{ + this("", false); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>CheckboxMenuItem</code> with the + * specified label and an initial state of off. + * + * @param label The label of the menu item. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true. + */ +public +CheckboxMenuItem(String label) +{ + this(label, false); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>CheckboxMenuItem</code> with the + * specified label and initial state. + * + * @param label The label of the menu item. + * @param state The initial state of the menu item, where <code>true</code> + * is on, and <code>false</code> is off. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true. + */ +public +CheckboxMenuItem(String label, boolean state) +{ + super(label); + this.state = state; + + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException (); +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns the state of this menu item. + * + * @return The state of this menu item. + */ +public boolean +getState() +{ + return(state); +} + +/*************************************************************************/ + +/** + * Sets the state of this menu item. + * + * @param state The initial state of the menu item, where <code>true</code> + * is on, and <code>false</code> is off. + */ +public synchronized void +setState(boolean state) +{ + this.state = state; + if (peer != null) + { + CheckboxMenuItemPeer cp = (CheckboxMenuItemPeer) peer; + cp.setState (state); + } +} + +/*************************************************************************/ + +/** + * Returns an array of length 1 with the menu item label for this object + * if the state is on. Otherwise <code>null</code> is returned. + * + * @return An array with this menu item's label if it has a state of on, + * or <code>null</code> otherwise. + */ +public Object[] +getSelectedObjects() +{ + if (state == false) + return(null); + + Object[] obj = new Object[1]; + obj[0] = getLabel(); + + return(obj); +} + +/*************************************************************************/ + +/** + * Create's this object's native peer + */ +public synchronized void +addNotify() +{ + if (peer == null) + peer = getToolkit().createCheckboxMenuItem(this); + + super.addNotify (); +} + +/*************************************************************************/ + +/** + * Adds the specified listener to the list of registered item listeners + * for this object. + * + * @param listener The listener to add. + */ +public synchronized void +addItemListener(ItemListener listener) +{ + item_listeners = AWTEventMulticaster.add(item_listeners, listener); + + enableEvents(AWTEvent.ITEM_EVENT_MASK); +} + +/*************************************************************************/ + +/** + * Removes the specified listener from the list of registered item + * listeners for this object. + * + * @param listener The listener to remove. + */ +public synchronized void +removeItemListener(ItemListener listener) +{ + item_listeners = AWTEventMulticaster.remove(item_listeners, listener); +} + +/*************************************************************************/ + +/** + * Processes the specified event by calling <code>processItemEvent()</code> + * if it is an instance of <code>ItemEvent</code> or calling the superclass + * method otherwise. + * + * @param event The event to process. + */ +protected void +processEvent(AWTEvent event) +{ + if (event instanceof ItemEvent) + processItemEvent((ItemEvent)event); + else + super.processEvent(event); +} + +/*************************************************************************/ + +/** + * Processes the specified event by dispatching it to any registered listeners. + * + * @param event The event to process. + */ +protected void +processItemEvent(ItemEvent event) +{ + if (item_listeners != null) + item_listeners.itemStateChanged(event); +} + +void +dispatchEventImpl(AWTEvent e) +{ + if (e instanceof ItemEvent) + { + synchronized (this) + { + state = (((ItemEvent) e).getStateChange() == ItemEvent.SELECTED); + } + } + + if (e.id <= ItemEvent.ITEM_LAST + && e.id >= ItemEvent.ITEM_FIRST + && (item_listeners != null + || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0)) + processEvent(e); + else + super.dispatchEventImpl(e); +} + +/*************************************************************************/ + +/** + * Returns a debugging string for this object. + * + * @return A debugging string for this object. + */ +public String +paramString() +{ + return ("label=" + getLabel() + ",state=" + state + + "," + super.paramString()); +} + + /** + * Returns an array of all the objects currently registered as FooListeners + * upon this <code>CheckboxMenuItem</code>. FooListeners are registered using + * the addFooListener method. + * + * @exception ClassCastException If listenerType doesn't specify a class or + * interface that implements java.util.EventListener. + */ + public EventListener[] getListeners (Class listenerType) + { + if (listenerType == ItemListener.class) + return AWTEventMulticaster.getListeners (item_listeners, listenerType); + + return super.getListeners (listenerType); + } + + /** + * Returns an aray of all item listeners currently registered to this + * <code>CheckBoxMenuItem</code>. + */ + public ItemListener[] getItemListeners () + { + return (ItemListener[]) getListeners (ItemListener.class); + } + + + protected class AccessibleAWTCheckboxMenuItem extends AccessibleAWTMenuItem + implements AccessibleAction, AccessibleValue + { + // I think the base class provides the necessary implementation + } + + /** + * Gets the AccessibleContext associated with this <code>CheckboxMenuItem</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTCheckboxMenuItem(); + return accessibleContext; + } + +} // class CheckboxMenuItem + diff --git a/libjava/classpath/java/awt/Choice.java b/libjava/classpath/java/awt/Choice.java new file mode 100644 index 0000000..5075ea9 --- /dev/null +++ b/libjava/classpath/java/awt/Choice.java @@ -0,0 +1,638 @@ +/* Choice.java -- Java choice button widget. + Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.peer.ChoicePeer; +import java.io.Serializable; +import java.util.EventListener; +import java.util.Vector; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * This class implements a drop down choice list. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class Choice extends Component + implements ItemSelectable, Serializable, Accessible +{ + +/* + * Static Variables + */ + +// Serialization constant +private static final long serialVersionUID = -4075310674757313071L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial A list of items for the choice box, which can be <code>null</code>. + * This is package-private to avoid an accessor method. + */ +Vector pItems = new Vector(); + +/** + * @serial The index of the selected item in the choice box. + */ +private int selectedIndex = -1; + +// Listener chain +private ItemListener item_listeners; + +/** + * This class provides accessibility support for the + * combo box. + * + * @author Jerry Quinn (jlquinn@optonline.net) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ + protected class AccessibleAWTChoice + extends AccessibleAWTComponent + implements AccessibleAction + { + + /** + * Serialization constant to match JDK 1.5 + */ + private static final long serialVersionUID = 7175603582428509322L; + + /** + * Default constructor which simply calls the + * super class for generic component accessibility + * handling. + */ + public AccessibleAWTChoice() + { + super(); + } + + /** + * Returns an implementation of the <code>AccessibleAction</code> + * interface for this accessible object. In this case, the + * current instance is simply returned (with a more appropriate + * type), as it also implements the accessible action as well as + * the context. + * + * @return the accessible action associated with this context. + * @see javax.accessibility.AccessibleAction + */ + public AccessibleAction getAccessibleAction() + { + return this; + } + + /** + * Returns the role of this accessible object. + * + * @return the instance of <code>AccessibleRole</code>, + * which describes this object. + * @see javax.accessibility.AccessibleRole + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.COMBO_BOX; + } + + /** + * Returns the number of actions associated with this accessible + * object. In this case, it is the number of choices available. + * + * @return the number of choices available. + * @see javax.accessibility.AccessibleAction#getAccessibleActionCount() + */ + public int getAccessibleActionCount() + { + return pItems.size(); + } + + /** + * Returns a description of the action with the supplied id. + * In this case, it is the text used in displaying the particular + * choice on-screen. + * + * @param i the id of the choice whose description should be + * retrieved. + * @return the <code>String</code> used to describe the choice. + * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int) + */ + public String getAccessibleActionDescription(int i) + { + return (String) pItems.get(i); + } + + /** + * Executes the action with the specified id. In this case, + * calling this method provides the same behaviour as would + * choosing a choice from the list in a visual manner. + * + * @param i the id of the choice to select. + * @return true if a valid choice was specified. + * @see javax.accessibility.AccessibleAction#doAccessibleAction(int) + */ + public boolean doAccessibleAction(int i) + { + if (i < 0 || i >= pItems.size()) + return false; + + Choice.this.processItemEvent(new ItemEvent(Choice.this, + ItemEvent.ITEM_STATE_CHANGED, + this, ItemEvent.SELECTED)); + return true; + } + } + +/*************************************************************************/ + +/* + * Constructors + */ + + /** + * Initializes a new instance of <code>Choice</code>. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true + */ + public Choice() + { + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException (); + } + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns the number of items in the list. + * + * @return The number of items in the list. + */ +public int +getItemCount() +{ + return countItems (); +} + +/*************************************************************************/ + +/** + * Returns the number of items in the list. + * + * @return The number of items in the list. + * + * @deprecated This method is deprecated in favor of <code>getItemCount</code>. + */ +public int +countItems() +{ + return(pItems.size()); +} + +/*************************************************************************/ + +/** + * Returns the item at the specified index in the list. + * + * @param index The index into the list to return the item from. + * + * @exception ArrayIndexOutOfBoundsException If the index is invalid. + */ +public String +getItem(int index) +{ + return((String)pItems.elementAt(index)); +} + +/*************************************************************************/ + +/** + * Adds the specified item to this choice box. + * + * @param item The item to add. + * + * @exception NullPointerException If the item's value is null + * + * @since 1.1 + */ +public synchronized void +add(String item) +{ + if (item == null) + throw new NullPointerException ("item must be non-null"); + + pItems.addElement(item); + + int i = pItems.size () - 1; + if (peer != null) + { + ChoicePeer cp = (ChoicePeer) peer; + cp.add (item, i); + } + else if (selectedIndex == -1) + select(0); +} + +/*************************************************************************/ + +/** + * Adds the specified item to this choice box. + * + * This method is oboslete since Java 2 platform 1.1. Please use @see add + * instead. + * + * @param item The item to add. + * + * @exception NullPointerException If the item's value is equal to null + */ +public synchronized void +addItem(String item) +{ + add(item); +} + +/*************************************************************************/ + +/** Inserts an item into this Choice. Existing items are shifted + * upwards. If the new item is the only item, then it is selected. + * If the currently selected item is shifted, then the first item is + * selected. If the currently selected item is not shifted, then it + * remains selected. + * + * @param item The item to add. + * @param index The index at which the item should be inserted. + * + * @exception IllegalArgumentException If index is less than 0 + */ +public synchronized void +insert(String item, int index) +{ + if (index < 0) + throw new IllegalArgumentException ("index may not be less then 0"); + + if (index > getItemCount ()) + index = getItemCount (); + + pItems.insertElementAt(item, index); + + if (peer != null) + { + ChoicePeer cp = (ChoicePeer) peer; + cp.add (item, index); + } + else if (selectedIndex == -1 || selectedIndex >= index) + select(0); +} + +/*************************************************************************/ + +/** + * Removes the specified item from the choice box. + * + * @param item The item to remove. + * + * @exception IllegalArgumentException If the specified item doesn't exist. + */ +public synchronized void +remove(String item) +{ + int index = pItems.indexOf(item); + if (index == -1) + throw new IllegalArgumentException ("item \"" + + item + "\" not found in Choice"); + remove(index); +} + +/*************************************************************************/ + +/** + * Removes the item at the specified index from the choice box. + * + * @param index The index of the item to remove. + * + * @exception IndexOutOfBoundsException If the index is not valid. + */ +public synchronized void +remove(int index) +{ + if ((index < 0) || (index > getItemCount())) + throw new IllegalArgumentException("Bad index: " + index); + + pItems.removeElementAt(index); + + if (peer != null) + { + ChoicePeer cp = (ChoicePeer) peer; + cp.remove (index); + } + else + { + if (getItemCount() == 0) + selectedIndex = -1; + else if (index == selectedIndex) + select(0); + } + + if (selectedIndex > index) + --selectedIndex; +} + +/*************************************************************************/ + +/** + * Removes all of the objects from this choice box. + */ +public synchronized void +removeAll() +{ + if (getItemCount() <= 0) + return; + + pItems.removeAllElements (); + + if (peer != null) + { + ChoicePeer cp = (ChoicePeer) peer; + cp.removeAll (); + } + + selectedIndex = -1; +} + +/*************************************************************************/ + +/** + * Returns the currently selected item, or null if no item is + * selected. + * + * @return The currently selected item. + */ +public synchronized String +getSelectedItem() +{ + return (selectedIndex == -1 + ? null + : ((String)pItems.elementAt(selectedIndex))); +} + +/*************************************************************************/ + +/** + * Returns an array with one row containing the selected item. + * + * @return An array containing the selected item. + */ +public synchronized Object[] +getSelectedObjects() +{ + if (selectedIndex == -1) + return null; + + Object[] objs = new Object[1]; + objs[0] = pItems.elementAt(selectedIndex); + + return(objs); +} + +/*************************************************************************/ + +/** + * Returns the index of the selected item. + * + * @return The index of the selected item. + */ +public int +getSelectedIndex() +{ + return(selectedIndex); +} + +/*************************************************************************/ + +/** + * Forces the item at the specified index to be selected. + * + * @param index The index of the row to make selected. + * + * @exception IllegalArgumentException If the specified index is invalid. + */ +public synchronized void +select(int index) +{ + if ((index < 0) || (index > getItemCount())) + throw new IllegalArgumentException("Bad index: " + index); + + this.selectedIndex = index; + if (peer != null) + { + ChoicePeer cp = (ChoicePeer) peer; + cp.select (index); + } +} + +/*************************************************************************/ + +/** + * Forces the named item to be selected. + * + * @param item The item to be selected. + * + * @exception IllegalArgumentException If the specified item does not exist. + */ +public synchronized void +select(String item) +{ + int index = pItems.indexOf(item); + if (index >= 0) + select(index); +} + +/*************************************************************************/ + +/** + * Creates the native peer for this object. + */ +public void +addNotify() +{ + if (peer == null) + peer = getToolkit ().createChoice (this); + super.addNotify (); +} + +/*************************************************************************/ + +/** + * Adds the specified listener to the list of registered listeners for + * this object. + * + * @param listener The listener to add. + */ +public synchronized void +addItemListener(ItemListener listener) +{ + item_listeners = AWTEventMulticaster.add(item_listeners, listener); +} + +/*************************************************************************/ + +/** + * Removes the specified listener from the list of registered listeners for + * this object. + * + * @param listener The listener to remove. + */ +public synchronized void +removeItemListener(ItemListener listener) +{ + item_listeners = AWTEventMulticaster.remove(item_listeners, listener); +} + +/*************************************************************************/ + +/** + * Processes this event by invoking <code>processItemEvent()</code> if the + * event is an instance of <code>ItemEvent</code>, otherwise the event + * is passed to the superclass. + * + * @param event The event to process. + */ +protected void +processEvent(AWTEvent event) +{ + if (event instanceof ItemEvent) + processItemEvent((ItemEvent)event); + else + super.processEvent(event); +} + +/*************************************************************************/ + +/** + * Processes item event by dispatching to any registered listeners. + * + * @param event The event to process. + */ +protected void +processItemEvent(ItemEvent event) +{ + if (item_listeners != null) + item_listeners.itemStateChanged(event); +} + +void +dispatchEventImpl(AWTEvent e) +{ + if (e.id <= ItemEvent.ITEM_LAST + && e.id >= ItemEvent.ITEM_FIRST + && (item_listeners != null + || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0)) + processEvent(e); + else + super.dispatchEventImpl(e); +} + +/*************************************************************************/ + +/** + * Returns a debugging string for this object. + * + * @return A debugging string for this object. + */ +protected String +paramString() +{ + return ("selectedIndex=" + selectedIndex + "," + super.paramString()); +} + + /** + * Returns an array of all the objects currently registered as FooListeners + * upon this Choice. FooListeners are registered using the addFooListener + * method. + * + * @exception ClassCastException If listenerType doesn't specify a class or + * interface that implements java.util.EventListener. + * + * @since 1.3 + */ + public EventListener[] getListeners (Class listenerType) + { + if (listenerType == ItemListener.class) + return AWTEventMulticaster.getListeners (item_listeners, listenerType); + + return super.getListeners (listenerType); + } + + /** + * Returns all registered item listeners. + * + * @since 1.4 + */ + public ItemListener[] getItemListeners () + { + return (ItemListener[]) getListeners (ItemListener.class); + } + + /** + * Gets the AccessibleContext associated with this <code>Choice</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTChoice(); + return accessibleContext; + } +} // class Choice diff --git a/libjava/classpath/java/awt/Color.java b/libjava/classpath/java/awt/Color.java new file mode 100644 index 0000000..4ad46d0 --- /dev/null +++ b/libjava/classpath/java/awt/Color.java @@ -0,0 +1,1008 @@ +/* Color.java -- represents a color in Java + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.color.ColorSpace; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.ColorModel; +import java.io.Serializable; + +/** + * This class represents a color value in the AWT system. It uses the sRGB + * (standard Red-Green-Blue) system, along with an alpha value ranging from + * transparent (0.0f or 0) and opaque (1.0f or 255). The color is not + * pre-multiplied by the alpha value an any of the accessor methods. Further + * information about sRGB can be found at + * <a href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html"> + * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html</a>. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ColorSpace + * @see AlphaComposite + * @since 1.0 + * @status updated to 1.4 + */ +public class Color implements Paint, Serializable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 118526816881161077L; + + /** Constant for the color white: R=255, G=255, B=255. */ + public static final Color white = new Color(0xffffff, false); + + /** + * Constant for the color white: R=255, G=255, B=255. + * + * @since 1.4 + */ + public static final Color WHITE = white; + + /** Constant for the color light gray: R=192, G=192, B=192. */ + public static final Color lightGray = new Color(0xc0c0c0, false); + + /** + * Constant for the color light gray: R=192, G=192, B=192. + * + * @since 1.4 + */ + public static final Color LIGHT_GRAY = lightGray; + + /** Constant for the color gray: R=128, G=128, B=128. */ + public static final Color gray = new Color(0x808080, false); + + /** + * Constant for the color gray: R=128, G=128, B=128. + * + * @since 1.4 + */ + public static final Color GRAY = gray; + + /** Constant for the color dark gray: R=64, G=64, B=64. */ + public static final Color darkGray = new Color(0x404040, false); + + /** + * Constant for the color dark gray: R=64, G=64, B=64. + * + * @since 1.4 + */ + public static final Color DARK_GRAY = darkGray; + + /** Constant for the color black: R=0, G=0, B=0. */ + public static final Color black = new Color(0x000000, false); + + /** + * Constant for the color black: R=0, G=0, B=0. + * + * @since 1.4 + */ + public static final Color BLACK = black; + + /** Constant for the color red: R=255, G=0, B=0. */ + public static final Color red = new Color(0xff0000, false); + + /** + * Constant for the color red: R=255, G=0, B=0. + * + * @since 1.4 + */ + public static final Color RED = red; + + /** Constant for the color pink: R=255, G=175, B=175. */ + public static final Color pink = new Color(0xffafaf, false); + + /** + * Constant for the color pink: R=255, G=175, B=175. + * + * @since 1.4 + */ + public static final Color PINK = pink; + + /** Constant for the color orange: R=255, G=200, B=0. */ + public static final Color orange = new Color(0xffc800, false); + + /** + * Constant for the color orange: R=255, G=200, B=0. + * + * @since 1.4 + */ + public static final Color ORANGE = orange; + + /** Constant for the color yellow: R=255, G=255, B=0. */ + public static final Color yellow = new Color(0xffff00, false); + + /** + * Constant for the color yellow: R=255, G=255, B=0. + * + * @since 1.4 + */ + public static final Color YELLOW = yellow; + + /** Constant for the color green: R=0, G=255, B=0. */ + public static final Color green = new Color(0x00ff00, false); + + /** + * Constant for the color green: R=0, G=255, B=0. + * + * @since 1.4 + */ + public static final Color GREEN = green; + + /** Constant for the color magenta: R=255, G=0, B=255. */ + public static final Color magenta = new Color(0xff00ff, false); + + /** + * Constant for the color magenta: R=255, G=0, B=255. + * + * @since 1.4 + */ + public static final Color MAGENTA = magenta; + + /** Constant for the color cyan: R=0, G=255, B=255. */ + public static final Color cyan = new Color(0x00ffff, false); + + /** + * Constant for the color cyan: R=0, G=255, B=255. + * + * @since 1.4 + */ + public static final Color CYAN = cyan; + + /** Constant for the color blue: R=0, G=0, B=255. */ + public static final Color blue = new Color(0x0000ff, false); + + /** + * Constant for the color blue: R=0, G=0, B=255. + * + * @since 1.4 + */ + public static final Color BLUE = blue; + + /** Internal mask for red. */ + private static final int RED_MASK = 255 << 16; + + /** Internal mask for green. */ + private static final int GREEN_MASK = 255 << 8; + + /** Internal mask for blue. */ + private static final int BLUE_MASK = 255; + + /** Internal mask for alpha. Package visible for use in subclass. */ + static final int ALPHA_MASK = 255 << 24; + + /** Amount to scale a color by when brightening or darkening. */ + private static final float BRIGHT_SCALE = 0.7f; + + /** + * The color value, in sRGB. Note that the actual color may be more + * precise if frgbvalue or fvalue is non-null. This class stores alpha, red, + * green, and blue, each 0-255, packed in an int. However, the subclass + * SystemColor stores an index into an array. Therefore, for serial + * compatibility (and because of poor design on Sun's part), this value + * cannot be used directly; instead you must use <code>getRGB()</code>. + * + * @see #getRGB() + * @serial the value of the color, whether an RGB literal or array index + */ + final int value; + + /** + * The color value, in sRGB. This may be null if the color was constructed + * with ints; and it does not include alpha. This stores red, green, and + * blue, in the range 0.0f - 1.0f. + * + * @see #getRGBColorComponents(float[]) + * @see #getRGBComponents(float[]) + * @serial the rgb components of the value + * @since 1.2 + */ + private float[] frgbvalue; + + /** + * The color value, in the native ColorSpace components. This may be null + * if the color was constructed with ints or in the sRGB color space; and + * it does not include alpha. + * + * @see #getRGBColorComponents(float[]) + * @see #getRGBComponents(float[]) + * @serial the original color space components of the color + * @since 1.2 + */ + private float[] fvalue; + + /** + * The alpha value. This is in the range 0.0f - 1.0f, but is invalid if + * deserialized as 0.0 when frgbvalue is null. + * + * @see #getRGBComponents(float[]) + * @see #getComponents(float[]) + * @serial the alpha component of this color + * @since 1.2 + */ + private final float falpha; + + /** + * The ColorSpace. Null means the default sRGB space. + * + * @see #getColor(String) + * @see #getColorSpace() + * @see #getColorComponents(float[]) + * @serial the color space for this color + * @since 1.2 + */ + private final ColorSpace cs; + + /** + * The paint context for this solid color. Package visible for use in + * subclass. + */ + transient ColorPaintContext context; + + /** + * Initializes a new instance of <code>Color</code> using the specified + * red, green, and blue values, which must be given as integers in the + * range of 0-255. Alpha will default to 255 (opaque). When drawing to + * screen, the actual color may be adjusted to the best match of hardware + * capabilities. + * + * @param red the red component of the RGB value + * @param green the green component of the RGB value + * @param blue the blue component of the RGB value + * @throws IllegalArgumentException if the values are out of range 0-255 + * @see #getRed() + * @see #getGreen() + * @see #getBlue() + * @see #getRGB() + * @see #Color(int, int, int, int) + */ + public Color(int red, int green, int blue) + { + this(red, green, blue, 255); + } + + /** + * Initializes a new instance of <code>Color</code> using the specified + * red, green, blue, and alpha values, which must be given as integers in + * the range of 0-255. When drawing to screen, the actual color may be + * adjusted to the best match of hardware capabilities. + * + * @param red the red component of the RGB value + * @param green the green component of the RGB value + * @param blue the blue component of the RGB value + * @param alpha the alpha value of the color + * @throws IllegalArgumentException if the values are out of range 0-255 + * @see #getRed() + * @see #getGreen() + * @see #getBlue() + * @see #getAlpha() + * @see #getRGB() + */ + public Color(int red, int green, int blue, int alpha) + { + if ((red & 255) != red || (green & 255) != green || (blue & 255) != blue + || (alpha & 255) != alpha) + throw new IllegalArgumentException("Bad RGB values" + +" red=0x"+Integer.toHexString(red) + +" green=0x"+Integer.toHexString(green) + +" blue=0x"+Integer.toHexString(blue) + +" alpha=0x"+Integer.toHexString(alpha) ); + + value = (alpha << 24) | (red << 16) | (green << 8) | blue; + falpha = 1; + cs = null; + } + + /** + * Initializes a new instance of <code>Color</code> using the specified + * RGB value. The blue value is in bits 0-7, green in bits 8-15, and + * red in bits 16-23. The other bits are ignored. The alpha value is set + * to 255 (opaque). When drawing to screen, the actual color may be + * adjusted to the best match of hardware capabilities. + * + * @param value the RGB value + * @see ColorModel#getRGBdefault() + * @see #getRed() + * @see #getGreen() + * @see #getBlue() + * @see #getRGB() + * @see #Color(int, boolean) + */ + public Color(int value) + { + this(value, false); + } + + /** + * Initializes a new instance of <code>Color</code> using the specified + * RGB value. The blue value is in bits 0-7, green in bits 8-15, and + * red in bits 16-23. The alpha value is in bits 24-31, unless hasalpha + * is false, in which case alpha is set to 255. When drawing to screen, the + * actual color may be adjusted to the best match of hardware capabilities. + * + * @param value the RGB value + * @param hasalpha true if value includes the alpha + * @see ColorModel#getRGBdefault() + * @see #getRed() + * @see #getGreen() + * @see #getBlue() + * @see #getAlpha() + * @see #getRGB() + */ + public Color(int value, boolean hasalpha) + { + // Note: SystemColor calls this constructor, setting falpha to 0; but + // code in getRGBComponents correctly reports falpha as 1.0 to the user + // for all instances of SystemColor since frgbvalue is left null here. + if (hasalpha) + falpha = ((value & ALPHA_MASK) >> 24) / 255f; + else + { + value |= ALPHA_MASK; + falpha = 1; + } + this.value = value; + cs = null; + } + + /** + * Initializes a new instance of <code>Color</code> using the specified + * RGB values. These must be in the range of 0.0-1.0. Alpha is assigned + * the value of 1.0 (opaque). When drawing to screen, the actual color may + * be adjusted to the best match of hardware capabilities. + * + * @param red the red component of the RGB value + * @param green the green component of the RGB value + * @param blue the blue component of the RGB value + * @throws IllegalArgumentException tf the values are out of range 0.0f-1.0f + * @see #getRed() + * @see #getGreen() + * @see #getBlue() + * @see #getRGB() + * @see #Color(float, float, float, float) + */ + public Color(float red, float green, float blue) + { + this(red, green, blue, 1.0f); + } + + /** + * Initializes a new instance of <code>Color</code> using the specified + * RGB and alpha values. These must be in the range of 0.0-1.0. When drawing + * to screen, the actual color may be adjusted to the best match of + * hardware capabilities. + * + * @param red the red component of the RGB value + * @param green the green component of the RGB value + * @param blue the blue component of the RGB value + * @param alpha the alpha value of the color + * @throws IllegalArgumentException tf the values are out of range 0.0f-1.0f + * @see #getRed() + * @see #getGreen() + * @see #getBlue() + * @see #getAlpha() + * @see #getRGB() + */ + public Color(float red, float green, float blue, float alpha) + { + value = convert(red, green, blue, alpha); + frgbvalue = new float[] {red, green, blue}; + falpha = alpha; + cs = null; + } + + /** + * Creates a color in the given ColorSpace with the specified alpha. The + * array must be non-null and have enough elements for the color space + * (for example, RGB requires 3 elements, CMYK requires 4). When drawing + * to screen, the actual color may be adjusted to the best match of + * hardware capabilities. + * + * @param space the color space of components + * @param components the color components, except alpha + * @param alpha the alpha value of the color + * @throws NullPointerException if cpsace or components is null + * @throws ArrayIndexOutOfBoundsException if components is too small + * @throws IllegalArgumentException if alpha or any component is out of range + * @see #getComponents(float[]) + * @see #getColorComponents(float[]) + */ + public Color(ColorSpace space, float[] components, float alpha) + { + frgbvalue = space.toRGB(components); + fvalue = components; + falpha = alpha; + cs = space; + value = convert(frgbvalue[0], frgbvalue[1], frgbvalue[2], alpha); + } + + /** + * Returns the red value for this color, as an integer in the range 0-255 + * in the sRGB color space. + * + * @return the red value for this color + * @see #getRGB() + */ + public int getRed() + { + // Do not inline getRGB() to value, because of SystemColor. + return (getRGB() & RED_MASK) >> 16; + } + + /** + * Returns the green value for this color, as an integer in the range 0-255 + * in the sRGB color space. + * + * @return the green value for this color + * @see #getRGB() + */ + public int getGreen() + { + // Do not inline getRGB() to value, because of SystemColor. + return (getRGB() & GREEN_MASK) >> 8; + } + + /** + * Returns the blue value for this color, as an integer in the range 0-255 + * in the sRGB color space. + * + * @return the blue value for this color + * @see #getRGB() + */ + public int getBlue() + { + // Do not inline getRGB() to value, because of SystemColor. + return getRGB() & BLUE_MASK; + } + + /** + * Returns the alpha value for this color, as an integer in the range 0-255. + * + * @return the alpha value for this color + * @see #getRGB() + */ + public int getAlpha() + { + // Do not inline getRGB() to value, because of SystemColor. + return (getRGB() & ALPHA_MASK) >>> 24; + } + + /** + * Returns the RGB value for this color, in the sRGB color space. The blue + * value will be in bits 0-7, green in 8-15, red in 16-23, and alpha value in + * 24-31. + * + * @return the RGB value for this color + * @see ColorModel#getRGBdefault() + * @see #getRed() + * @see #getGreen() + * @see #getBlue() + * @see #getAlpha() + */ + public int getRGB() + { + return value; + } + + /** + * Returns a brighter version of this color. This is done by increasing the + * RGB values by an arbitrary scale factor. The new color is opaque (an + * alpha of 255). Note that this method and the <code>darker()</code> + * method are not necessarily inverses. + * + * @return a brighter version of this color + * @see #darker() + */ + public Color brighter() + { + // Do not inline getRGB() to this.value, because of SystemColor. + int value = getRGB(); + int red = (value & RED_MASK) >> 16; + int green = (value & GREEN_MASK) >> 8; + int blue = value & BLUE_MASK; + // We have to special case 0-2 because they won't scale by division. + red = red < 3 ? 3 : (int) Math.min(255, red / BRIGHT_SCALE); + green = green < 3 ? 3 : (int) Math.min(255, green / BRIGHT_SCALE); + blue = blue < 3 ? 3 : (int) Math.min(255, blue / BRIGHT_SCALE); + return new Color(red, green, blue, 255); + } + + /** + * Returns a darker version of this color. This is done by decreasing the + * RGB values by an arbitrary scale factor. The new color is opaque (an + * alpha of 255). Note that this method and the <code>brighter()</code> + * method are not necessarily inverses. + * + * @return a darker version of this color + * @see #brighter() + */ + public Color darker() + { + // Do not inline getRGB() to this.value, because of SystemColor. + int value = getRGB(); + return new Color((int) (((value & RED_MASK) >> 16) * BRIGHT_SCALE), + (int) (((value & GREEN_MASK) >> 8) * BRIGHT_SCALE), + (int) ((value & BLUE_MASK) * BRIGHT_SCALE), 255); + } + + /** + * Returns a hash value for this color. This is simply the color in 8-bit + * precision, in the format 0xAARRGGBB (alpha, red, green, blue). + * + * @return a hash value for this color + */ + public int hashCode() + { + return value; + } + + /** + * Tests this object for equality against the specified object. This will + * be true if and only if the specified object is an instance of + * <code>Color</code> and has the same 8-bit integer red, green, and blue + * values as this object. Note that two colors may be slightly different + * as float values, but round to the same integer values. Also note that + * this does not accurately compare SystemColors, since that class does + * not store its internal data in RGB format like regular colors. + * + * @param obj the object to compare to + * @return true if the specified object is semantically equal to this one + */ + public boolean equals(Object obj) + { + return obj instanceof Color && ((Color) obj).value == value; + } + + /** + * Returns a string representation of this object. Subclasses may return + * any desired format, except for null, but this implementation returns + * <code>getClass().getName() + "[r=" + getRed() + ",g=" + getGreen() + * + ",b=" + getBlue() + ']'</code>. + * + * @return a string representation of this object + */ + public String toString() + { + return getClass().getName() + "[r=" + ((value & RED_MASK) >> 16) + + ",g=" + ((value & GREEN_MASK) >> 8) + ",b=" + (value & BLUE_MASK) + + ']'; + } + + /** + * Converts the specified string to a number, using Integer.decode, and + * creates a new instance of <code>Color</code> from the value. The alpha + * value will be 255 (opaque). + * + * @param str the numeric color string + * @return a new instance of <code>Color</code> for the string + * @throws NumberFormatException if the string cannot be parsed + * @throws NullPointerException if the string is null + * @see Integer#decode(String) + * @see #Color(int) + * @since 1.1 + */ + public static Color decode(String str) + { + return new Color(Integer.decode(str).intValue(), false); + } + + /** + * Returns a new instance of <code>Color</code> from the value of the + * system property named by the specified string. If the property does not + * exist, or cannot be parsed, then <code>null</code> will be returned. + * + * @param prop the system property to retrieve + * @throws SecurityException if getting the property is denied + * @see #getColor(String, Color) + * @see Integer#getInteger(String) + */ + public static Color getColor(String prop) + { + return getColor(prop, null); + } + + /** + * Returns a new instance of <code>Color</code> from the value of the + * system property named by the specified string. If the property does + * not exist, or cannot be parsed, then the default color value will be + * returned. + * + * @param prop the system property to retrieve + * @param defcolor the default color + * @throws SecurityException if getting the property is denied + * @see Integer#getInteger(String) + */ + public static Color getColor(String prop, Color defcolor) + { + Integer val = Integer.getInteger(prop, null); + return val == null ? defcolor + : new Color(val.intValue(), false); + } + + /** + * Returns a new instance of <code>Color</code> from the value of the + * system property named by the specified string. If the property does + * not exist, or cannot be parsed, then the default RGB value will be + * used to create a return value. + * + * @param prop the system property to retrieve + * @param defrgb the default RGB value + * @throws SecurityException if getting the property is denied + * @see #getColor(String, Color) + * @see Integer#getInteger(String, int) + */ + public static Color getColor(String prop, int defrgb) + { + Color c = getColor(prop, null); + return c == null ? new Color(defrgb, false) : c; + } + + /** + * Converts from the HSB (hue, saturation, brightness) color model to the + * RGB (red, green, blue) color model. The hue may be any floating point; + * it's fractional portion is used to select the angle in the HSB model. + * The saturation and brightness must be between 0 and 1. The result is + * suitable for creating an RGB color with the one-argument constructor. + * + * @param hue the hue of the HSB value + * @param saturation the saturation of the HSB value + * @param brightness the brightness of the HSB value + * @return the RGB value + * @see #getRGB() + * @see #Color(int) + * @see ColorModel#getRGBdefault() + */ + public static int HSBtoRGB(float hue, float saturation, float brightness) + { + if (saturation == 0) + return convert(brightness, brightness, brightness, 0); + if (saturation < 0 || saturation > 1 || brightness < 0 || brightness > 1) + throw new IllegalArgumentException(); + hue = hue - (float) Math.floor(hue); + int i = (int) (6 * hue); + float f = 6 * hue - i; + float p = brightness * (1 - saturation); + float q = brightness * (1 - saturation * f); + float t = brightness * (1 - saturation * (1 - f)); + switch (i) + { + case 0: + return convert(brightness, t, p, 0); + case 1: + return convert(q, brightness, p, 0); + case 2: + return convert(p, brightness, t, 0); + case 3: + return convert(p, q, brightness, 0); + case 4: + return convert(t, p, brightness, 0); + case 5: + return convert(brightness, p, q, 0); + default: + throw new InternalError("impossible"); + } + } + + /** + * Converts from the RGB (red, green, blue) color model to the HSB (hue, + * saturation, brightness) color model. If the array is null, a new one + * is created, otherwise it is recycled. The results will be in the range + * 0.0-1.0 if the inputs are in the range 0-255. + * + * @param red the red part of the RGB value + * @param green the green part of the RGB value + * @param blue the blue part of the RGB value + * @param array an array for the result (at least 3 elements), or null + * @return the array containing HSB value + * @throws ArrayIndexOutOfBoundsException of array is too small + * @see #getRGB() + * @see #Color(int) + * @see ColorModel#getRGBdefault() + */ + public static float[] RGBtoHSB(int red, int green, int blue, float array[]) + { + if (array == null) + array = new float[3]; + // Calculate brightness. + int min; + int max; + if (red < green) + { + min = red; + max = green; + } + else + { + min = green; + max = red; + } + if (blue > max) + max = blue; + else if (blue < min) + min = blue; + array[2] = max / 255f; + // Calculate saturation. + if (max == 0) + array[1] = 0; + else + array[1] = (max - min) / max; + // Calculate hue. + if (array[1] == 0) + array[0] = 0; + else + { + float delta = (max - min) * 6; + if (red == max) + array[0] = (green - blue) / delta; + else if (green == max) + array[0] = 1f / 3 + (blue - red) / delta; + else + array[0] = 2f / 3 + (red - green) / delta; + if (array[0] < 0) + array[0]++; + } + return array; + } + + /** + * Returns a new instance of <code>Color</code> based on the specified + * HSB values. The hue may be any floating point; it's fractional portion + * is used to select the angle in the HSB model. The saturation and + * brightness must be between 0 and 1. + * + * @param hue the hue of the HSB value + * @param saturation the saturation of the HSB value + * @param brightness the brightness of the HSB value + * @return the new <code>Color</code> object + */ + public static Color getHSBColor(float hue, float saturation, + float brightness) + { + return new Color(HSBtoRGB(hue, saturation, brightness), false); + } + + /** + * Returns a float array with the red, green, and blue components, and the + * alpha value, in the default sRGB space, with values in the range 0.0-1.0. + * If the array is null, a new one is created, otherwise it is recycled. + * + * @param array the array to put results into (at least 4 elements), or null + * @return the RGB components and alpha value + * @throws ArrayIndexOutOfBoundsException if array is too small + */ + public float[] getRGBComponents(float[] array) + { + if (array == null) + array = new float[4]; + getRGBColorComponents(array); + // Stupid serialization issues require this check. + array[3] = (falpha == 0 && frgbvalue == null + ? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha); + return array; + } + + /** + * Returns a float array with the red, green, and blue components, in the + * default sRGB space, with values in the range 0.0-1.0. If the array is + * null, a new one is created, otherwise it is recycled. + * + * @param array the array to put results into (at least 3 elements), or null + * @return the RGB components + * @throws ArrayIndexOutOfBoundsException if array is too small + */ + public float[] getRGBColorComponents(float[] array) + { + if (array == null) + array = new float[3]; + else if (array == frgbvalue) + return array; // Optimization for getColorComponents(float[]). + if (frgbvalue == null) + { + // Do not inline getRGB() to this.value, because of SystemColor. + int value = getRGB(); + frgbvalue = new float[] { ((value & RED_MASK) >> 16) / 255f, + ((value & GREEN_MASK) >> 8) / 255f, + (value & BLUE_MASK) / 255f }; + } + array[0] = frgbvalue[0]; + array[1] = frgbvalue[1]; + array[2] = frgbvalue[2]; + return array; + } + + /** + * Returns a float array containing the color and alpha components of this + * color in the ColorSpace it was created with (the constructors which do + * not take a ColorSpace parameter use a default sRGB ColorSpace). If the + * array is null, a new one is created, otherwise it is recycled, and must + * have at least one more position than components used in the color space. + * + * @param array the array to put results into, or null + * @return the original color space components and alpha value + * @throws ArrayIndexOutOfBoundsException if array is too small + */ + public float[] getComponents(float[] array) + { + int numComponents = cs == null ? 3 : cs.getNumComponents(); + if (array == null) + array = new float[1 + numComponents]; + getColorComponents(array); + // Stupid serialization issues require this check. + array[numComponents] = (falpha == 0 && frgbvalue == null + ? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha); + return array; + } + + /** + * Returns a float array containing the color components of this color in + * the ColorSpace it was created with (the constructors which do not take + * a ColorSpace parameter use a default sRGB ColorSpace). If the array is + * null, a new one is created, otherwise it is recycled, and must have at + * least as many positions as used in the color space. + * + * @param array the array to put results into, or null + * @return the original color space components + * @throws ArrayIndexOutOfBoundsException if array is too small + */ + public float[] getColorComponents(float[] array) + { + int numComponents = cs == null ? 3 : cs.getNumComponents(); + if (array == null) + array = new float[numComponents]; + if (fvalue == null) // If fvalue is null, cs should be null too. + fvalue = getRGBColorComponents(frgbvalue); + System.arraycopy(fvalue, 0, array, 0, numComponents); + return array; + } + + /** + * Returns a float array containing the color and alpha components of this + * color in the given ColorSpace. If the array is null, a new one is + * created, otherwise it is recycled, and must have at least one more + * position than components used in the color space. + * + * @param space the color space to translate to + * @param array the array to put results into, or null + * @return the color space components and alpha value + * @throws ArrayIndexOutOfBoundsException if array is too small + * @throws NullPointerException if space is null + */ + public float[] getComponents(ColorSpace space, float[] array) + { + int numComponents = space.getNumComponents(); + if (array == null) + array = new float[1 + numComponents]; + getColorComponents(space, array); + // Stupid serialization issues require this check. + array[numComponents] = (falpha == 0 && frgbvalue == null + ? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha); + return array; + } + + /** + * Returns a float array containing the color components of this color in + * the given ColorSpace. If the array is null, a new one is created, + * otherwise it is recycled, and must have at least as many positions as + * used in the color space. + * + * @param space the color space to translate to + * @return the color space components + * @throws ArrayIndexOutOfBoundsException if array is too small + * @throws NullPointerException if space is null + */ + public float[] getColorComponents(ColorSpace space, float[] array) + { + float[] components = space.fromRGB(getRGBColorComponents(frgbvalue)); + if (array == null) + return components; + System.arraycopy(components, 0, array, 0, components.length); + return array; + } + + /** + * Returns the color space of this color. Except for the constructor which + * takes a ColorSpace argument, this will be an implementation of + * ColorSpace.CS_sRGB. + * + * @return the color space + */ + public ColorSpace getColorSpace() + { + return cs == null ? ColorSpace.getInstance(ColorSpace.CS_sRGB) : cs; + } + + /** + * Returns a paint context, used for filling areas of a raster scan with + * this color. Since the color is constant across the entire rectangle, and + * since it is always in sRGB space, this implementation returns the same + * object, regardless of the parameters. Subclasses, however, may have a + * mutable result. + * + * @param cm the requested color model + * @param deviceBounds the bounding box in device coordinates, ignored + * @param userBounds the bounding box in user coordinates, ignored + * @param xform the bounds transformation, ignored + * @param hints any rendering hints, ignored + * @return a context for painting this solid color + */ + public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, + Rectangle2D userBounds, + AffineTransform xform, + RenderingHints hints) + { + if (context == null || !context.getColorModel().equals(cm)) + context = new ColorPaintContext(cm,value); + return context; + } + + /** + * Returns the transparency level of this color. + * + * @return one of {@link #OPAQUE}, {@link #BITMASK}, or {@link #TRANSLUCENT} + */ + public int getTransparency() + { + // Do not inline getRGB() to this.value, because of SystemColor. + int alpha = getRGB() & ALPHA_MASK; + return alpha == (255 << 24) ? OPAQUE : alpha == 0 ? BITMASK : TRANSLUCENT; + } + + /** + * Converts float values to integer value. + * + * @param red the red value + * @param green the green value + * @param blue the blue value + * @param alpha the alpha value + * @return the integer value made of 8-bit sections + * @throws IllegalArgumentException if parameters are out of range 0.0-1.0 + */ + private static int convert(float red, float green, float blue, float alpha) + { + if (red < 0 || red > 1 || green < 0 || green > 1 || blue < 0 || blue > 1 + || alpha < 0 || alpha > 1) + throw new IllegalArgumentException("Bad RGB values"); + int redval = Math.round(255 * red); + int greenval = Math.round(255 * green); + int blueval = Math.round(255 * blue); + int alphaval = Math.round(255 * alpha); + return (alphaval << 24) | (redval << 16) | (greenval << 8) | blueval; + } +} // class Color diff --git a/libjava/classpath/java/awt/ColorPaintContext.java b/libjava/classpath/java/awt/ColorPaintContext.java new file mode 100644 index 0000000..759ba9d --- /dev/null +++ b/libjava/classpath/java/awt/ColorPaintContext.java @@ -0,0 +1,195 @@ +/* ColorPaintContext.java -- context for painting solid colors + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.image.ColorModel; +import java.awt.image.Raster; + +/** + * This class provides a paint context which will fill a rectanglar region of + * a raster scan with the given color. However, it is not yet completely + * implemented. + * + * @author Eric Blake (ebb9@email.byu.edu) + */ +class ColorPaintContext implements PaintContext +{ + /** + * The color to fill any raster with. Package visible for use in + * SystemColor. + */ + final int color; + final ColorModel colorModel; + + private ColorRaster cachedRaster; + + + /** + * Create the context for a given color. + * + * @param c The solid color to use. + */ + ColorPaintContext(int colorRGB) + { + this(ColorModel.getRGBdefault(), colorRGB); + } + + /** + * Create the context for a given color. + * + * @param cm The color model of this context. + * @param c The solid color to use. + */ + ColorPaintContext(ColorModel cm,int colorRGB) + { + color = colorRGB; + colorModel = cm; + } + + /** + * Release the resources allocated for the paint. As the color is constant, + * there aren't any resources. + */ + public void dispose() + { + } + + /** + * Return the color model of this context. + * + * @return the context color model + */ + public ColorModel getColorModel() + { + return colorModel; + } + + /** + * Return a raster containing the colors for the graphics operation. + * + * @param x the x-coordinate, in device space + * @param y the y-coordinate, in device space + * @param width the width, in device space + * @param height the height, in device space + * @return a raster for the given area and color + */ + public Raster getRaster(int x, int y, int width, int height) + { + if( cachedRaster == null + || cachedRaster.getWidth() < width + || cachedRaster.getHeight() < height) + { + cachedRaster = new ColorRaster(colorModel, 0, 0, width, height, color); + } + return cachedRaster.createChild(0 ,0 ,width ,height ,x ,y , null); + } + + /** + * A ColorRaster is a raster that is completely filled with one color. The + * data layout is taken from the color model given to the constructor. + */ + private class ColorRaster extends Raster + { + + /** + * Create a raster that is compaltible with the given color model and + * filled with the given color. + * @param cm The color model for this raster. + * @param x The smallest horizontal corrdinate in the raster. + * @param y The smallest vertical coordinate in the raster. + * @param width The width of the raster. + * @param height The height of the raster. + * @param rgbPixel The RGB value of the color for this raster. + */ + ColorRaster(ColorModel cm,int x, int y, int width, int height, int rgbPixel) + { + super(cm.createCompatibleSampleModel(width,height),new Point(x,y)); + Object pixel = cm.getDataElements(rgbPixel,null); + getSampleModel().setDataElements(0, 0, + width, height, + multiplyData(pixel,null,width*height), + dataBuffer); + } + + + + private Object multiplyData(Object src, Object dest, int factor) + { + Object from; + int srcLength = 0; + if (src instanceof byte[]) + { + srcLength = ((byte[])src).length; + + if (dest == null) dest = new byte[factor * srcLength]; + } + else if (src instanceof short[]) + { + srcLength = ((short[])src).length; + if (dest == null) dest = new short[factor * srcLength]; + } + else if (src instanceof int[]) + { + srcLength = ((int[]) src).length; + if (dest == null) dest = new int[factor * srcLength]; + } + else + { + throw new ClassCastException("Unknown data buffer type"); + } + + System.arraycopy(src,0,dest,0,srcLength); + + int count = 1; + while(count*2 < factor) + { + System.arraycopy(dest, 0, dest, count * srcLength, count*srcLength); + count *= 2; + } + + if(factor > count) + System.arraycopy(dest,0, dest, count * srcLength, + (factor - count) * srcLength ); + + return dest; + } + + } + +} // class ColorPaintContext diff --git a/libjava/classpath/java/awt/Component.java b/libjava/classpath/java/awt/Component.java new file mode 100644 index 0000000..4491904 --- /dev/null +++ b/libjava/classpath/java/awt/Component.java @@ -0,0 +1,6017 @@ +/* Component.java -- a graphics component + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.dnd.DropTarget; +import java.awt.event.ActionEvent; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.HierarchyBoundsListener; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; +import java.awt.event.InputEvent; +import java.awt.event.InputMethodEvent; +import java.awt.event.InputMethodListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.event.PaintEvent; +import java.awt.event.WindowEvent; +import java.awt.im.InputContext; +import java.awt.im.InputMethodRequests; +import java.awt.image.BufferStrategy; +import java.awt.image.ColorModel; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.awt.image.VolatileImage; +import java.awt.peer.ComponentPeer; +import java.awt.peer.LightweightPeer; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.Collections; +import java.util.EventListener; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Locale; +import java.util.Set; +import java.util.Vector; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleComponent; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +/** + * The root of all evil. All graphical representations are subclasses of this + * giant class, which is designed for screen display and user interaction. + * This class can be extended directly to build a lightweight component (one + * not associated with a native window); lightweight components must reside + * inside a heavyweight window. + * + * <p>This class is Serializable, which has some big implications. A user can + * save the state of all graphical components in one VM, and reload them in + * another. Note that this class will only save Serializable listeners, and + * ignore the rest, without causing any serialization exceptions. However, by + * making a listener serializable, and adding it to another element, you link + * in that entire element to the state of this component. To get around this, + * use the idiom shown in the example below - make listeners non-serializable + * in inner classes, rather than using this object itself as the listener, if + * external objects do not need to save the state of this object. + * + * <pre> + * import java.awt.*; + * import java.awt.event.*; + * import java.io.Serializable; + * class MyApp implements Serializable + * { + * BigObjectThatShouldNotBeSerializedWithAButton bigOne; + * // Serializing aButton will not suck in an instance of MyApp, with its + * // accompanying field bigOne. + * Button aButton = new Button(); + * class MyActionListener implements ActionListener + * { + * public void actionPerformed(ActionEvent e) + * { + * System.out.println("Hello There"); + * } + * } + * MyApp() + * { + * aButton.addActionListener(new MyActionListener()); + * } + * } + * </pre> + * + * <p>Status: Incomplete. The event dispatch mechanism is implemented. All + * other methods defined in the J2SE 1.3 API javadoc exist, but are mostly + * incomplete or only stubs; except for methods relating to the Drag and + * Drop, Input Method, and Accessibility frameworks: These methods are + * present but commented out. + * + * @author original author unknown + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status still missing 1.4 support + */ +public abstract class Component + implements ImageObserver, MenuContainer, Serializable +{ + // Word to the wise - this file is huge. Search for '\f' (^L) for logical + // sectioning by fields, public API, private API, and nested classes. + + + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -7644114512714619750L; + + /** + * Constant returned by the <code>getAlignmentY</code> method to indicate + * that the component wishes to be aligned to the top relative to + * other components. + * + * @see #getAlignmentY() + */ + public static final float TOP_ALIGNMENT = 0; + + /** + * Constant returned by the <code>getAlignmentY</code> and + * <code>getAlignmentX</code> methods to indicate + * that the component wishes to be aligned to the center relative to + * other components. + * + * @see #getAlignmentX() + * @see #getAlignmentY() + */ + public static final float CENTER_ALIGNMENT = 0.5f; + + /** + * Constant returned by the <code>getAlignmentY</code> method to indicate + * that the component wishes to be aligned to the bottom relative to + * other components. + * + * @see #getAlignmentY() + */ + public static final float BOTTOM_ALIGNMENT = 1; + + /** + * Constant returned by the <code>getAlignmentX</code> method to indicate + * that the component wishes to be aligned to the right relative to + * other components. + * + * @see #getAlignmentX() + */ + public static final float RIGHT_ALIGNMENT = 1; + + /** + * Constant returned by the <code>getAlignmentX</code> method to indicate + * that the component wishes to be aligned to the left relative to + * other components. + * + * @see #getAlignmentX() + */ + public static final float LEFT_ALIGNMENT = 0; + + /** + * Make the treelock a String so that it can easily be identified + * in debug dumps. We clone the String in order to avoid a conflict in + * the unlikely event that some other package uses exactly the same string + * as a lock object. + */ + static final Object treeLock = new String("AWT_TREE_LOCK"); + + // Serialized fields from the serialization spec. + + /** + * The x position of the component in the parent's coordinate system. + * + * @see #getLocation() + * @serial the x position + */ + int x; + + /** + * The y position of the component in the parent's coordinate system. + * + * @see #getLocation() + * @serial the y position + */ + int y; + + /** + * The component width. + * + * @see #getSize() + * @serial the width + */ + int width; + + /** + * The component height. + * + * @see #getSize() + * @serial the height + */ + int height; + + /** + * The foreground color for the component. This may be null. + * + * @see #getForeground() + * @see #setForeground(Color) + * @serial the foreground color + */ + Color foreground; + + /** + * The background color for the component. This may be null. + * + * @see #getBackground() + * @see #setBackground(Color) + * @serial the background color + */ + Color background; + + /** + * The default font used in the component. This may be null. + * + * @see #getFont() + * @see #setFont(Font) + * @serial the font + */ + Font font; + + /** + * The font in use by the peer, or null if there is no peer. + * + * @serial the peer's font + */ + Font peerFont; + + /** + * The cursor displayed when the pointer is over this component. This may + * be null. + * + * @see #getCursor() + * @see #setCursor(Cursor) + */ + Cursor cursor; + + /** + * The locale for the component. + * + * @see #getLocale() + * @see #setLocale(Locale) + */ + Locale locale = Locale.getDefault (); + + /** + * True if the object should ignore repaint events (usually because it is + * not showing). + * + * @see #getIgnoreRepaint() + * @see #setIgnoreRepaint(boolean) + * @serial true to ignore repaints + * @since 1.4 + */ + boolean ignoreRepaint; + + /** + * True when the object is visible (although it is only showing if all + * ancestors are likewise visible). For component, this defaults to true. + * + * @see #isVisible() + * @see #setVisible(boolean) + * @serial true if visible + */ + boolean visible = true; + + /** + * True if the object is enabled, meaning it can interact with the user. + * For component, this defaults to true. + * + * @see #isEnabled() + * @see #setEnabled(boolean) + * @serial true if enabled + */ + boolean enabled = true; + + /** + * True if the object is valid. This is set to false any time a size + * adjustment means the component need to be layed out again. + * + * @see #isValid() + * @see #validate() + * @see #invalidate() + * @serial true if layout is valid + */ + boolean valid; + + /** + * The DropTarget for drag-and-drop operations. + * + * @see #getDropTarget() + * @see #setDropTarget(DropTarget) + * @serial the drop target, or null + * @since 1.2 + */ + DropTarget dropTarget; + + /** + * The list of popup menus for this component. + * + * @see #add(PopupMenu) + * @serial the list of popups + */ + Vector popups; + + /** + * The component's name. May be null, in which case a default name is + * generated on the first use. + * + * @see #getName() + * @see #setName(String) + * @serial the name + */ + String name; + + /** + * True once the user has set the name. Note that the user may set the name + * to null. + * + * @see #name + * @see #getName() + * @see #setName(String) + * @serial true if the name has been explicitly set + */ + boolean nameExplicitlySet; + + /** + * Indicates if the object can be focused. Defaults to true for components. + * + * @see #isFocusable() + * @see #setFocusable(boolean) + * @since 1.4 + */ + boolean focusable = true; + + /** + * Tracks whether this component's {@link #isFocusTraversable} + * method has been overridden. + * + * @since 1.4 + */ + int isFocusTraversableOverridden; + + /** + * The focus traversal keys, if not inherited from the parent or + * default keyboard focus manager. These sets will contain only + * AWTKeyStrokes that represent press and release events to use as + * focus control. + * + * @see #getFocusTraversalKeys(int) + * @see #setFocusTraversalKeys(int, Set) + * @since 1.4 + */ + Set[] focusTraversalKeys; + + /** + * True if focus traversal keys are enabled. This defaults to true for + * Component. If this is true, keystrokes in focusTraversalKeys are trapped + * and processed automatically rather than being passed on to the component. + * + * @see #getFocusTraversalKeysEnabled() + * @see #setFocusTraversalKeysEnabled(boolean) + * @since 1.4 + */ + boolean focusTraversalKeysEnabled = true; + + /** + * Cached information on the minimum size. Should have been transient. + * + * @serial ignore + */ + Dimension minSize; + + /** + * Cached information on the preferred size. Should have been transient. + * + * @serial ignore + */ + Dimension prefSize; + + /** + * Set to true if an event is to be handled by this component, false if + * it is to be passed up the hierarcy. + * + * @see #dispatchEvent(AWTEvent) + * @serial true to process event locally + */ + boolean newEventsOnly; + + /** + * Set by subclasses to enable event handling of particular events, and + * left alone when modifying listeners. For component, this defaults to + * enabling only input methods. + * + * @see #enableInputMethods(boolean) + * @see AWTEvent + * @serial the mask of events to process + */ + long eventMask = AWTEvent.INPUT_ENABLED_EVENT_MASK; + + /** + * Describes all registered PropertyChangeListeners. + * + * @see #addPropertyChangeListener(PropertyChangeListener) + * @see #removePropertyChangeListener(PropertyChangeListener) + * @see #firePropertyChange(String, Object, Object) + * @serial the property change listeners + * @since 1.2 + */ + PropertyChangeSupport changeSupport; + + /** + * True if the component has been packed (layed out). + * + * @serial true if this is packed + */ + boolean isPacked; + + /** + * The serialization version for this class. Currently at version 4. + * + * XXX How do we handle prior versions? + * + * @serial the serialization version + */ + int componentSerializedDataVersion = 4; + + /** + * The accessible context associated with this component. This is only set + * by subclasses. + * + * @see #getAccessibleContext() + * @serial the accessibility context + * @since 1.2 + */ + AccessibleContext accessibleContext; + + + // Guess what - listeners are special cased in serialization. See + // readObject and writeObject. + + /** Component listener chain. */ + transient ComponentListener componentListener; + + /** Focus listener chain. */ + transient FocusListener focusListener; + + /** Key listener chain. */ + transient KeyListener keyListener; + + /** Mouse listener chain. */ + transient MouseListener mouseListener; + + /** Mouse motion listener chain. */ + transient MouseMotionListener mouseMotionListener; + + /** + * Mouse wheel listener chain. + * + * @since 1.4 + */ + transient MouseWheelListener mouseWheelListener; + + /** + * Input method listener chain. + * + * @since 1.2 + */ + transient InputMethodListener inputMethodListener; + + /** + * Hierarcy listener chain. + * + * @since 1.3 + */ + transient HierarchyListener hierarchyListener; + + /** + * Hierarcy bounds listener chain. + * + * @since 1.3 + */ + transient HierarchyBoundsListener hierarchyBoundsListener; + + // Anything else is non-serializable, and should be declared "transient". + + /** The parent. */ + transient Container parent; + + /** The associated native peer. */ + transient ComponentPeer peer; + + /** The preferred component orientation. */ + transient ComponentOrientation orientation = ComponentOrientation.UNKNOWN; + + /** + * The associated graphics configuration. + * + * @since 1.4 + */ + transient GraphicsConfiguration graphicsConfig; + + /** + * The buffer strategy for repainting. + * + * @since 1.4 + */ + transient BufferStrategy bufferStrategy; + + /** + * true if requestFocus was called on this component when its + * top-level ancestor was not focusable. + */ + private transient FocusEvent pendingFocusRequest = null; + + /** + * The system properties that affect image updating. + */ + private static transient boolean incrementalDraw; + private static transient Long redrawRate; + + static + { + incrementalDraw = Boolean.getBoolean ("awt.image.incrementalDraw"); + redrawRate = Long.getLong ("awt.image.redrawrate"); + } + + // Public and protected API. + + /** + * Default constructor for subclasses. When Component is extended directly, + * it forms a lightweight component that must be hosted in an opaque native + * container higher in the tree. + */ + protected Component() + { + } + + /** + * Returns the name of this component. + * + * @return the name of this component + * @see #setName(String) + * @since 1.1 + */ + public String getName() + { + if (name == null && ! nameExplicitlySet) + name = generateName(); + return name; + } + + /** + * Sets the name of this component to the specified name. + * + * @param name the new name of this component + * @see #getName() + * @since 1.1 + */ + public void setName(String name) + { + nameExplicitlySet = true; + this.name = name; + } + + /** + * Returns the parent of this component. + * + * @return the parent of this component + */ + public Container getParent() + { + return parent; + } + + /** + * Returns the native windowing system peer for this component. Only the + * platform specific implementation code should call this method. + * + * @return the peer for this component + * @deprecated user programs should not directly manipulate peers; use + * {@link #isDisplayable()} instead + */ + // Classpath's Gtk peers rely on this. + public ComponentPeer getPeer() + { + return peer; + } + + /** + * Set the associated drag-and-drop target, which receives events when this + * is enabled. + * + * @param dt the new drop target + * @see #isEnabled() + */ + public void setDropTarget(DropTarget dt) + { + this.dropTarget = dt; + } + + /** + * Gets the associated drag-and-drop target, if there is one. + * + * @return the drop target + */ + public DropTarget getDropTarget() + { + return dropTarget; + } + + /** + * Returns the graphics configuration of this component, if there is one. + * If it has not been set, it is inherited from the parent. + * + * @return the graphics configuration, or null + * @since 1.3 + */ + public GraphicsConfiguration getGraphicsConfiguration() + { + return getGraphicsConfigurationImpl(); + } + + /** + * Returns the object used for synchronization locks on this component + * when performing tree and layout functions. + * + * @return the synchronization lock for this component + */ + public final Object getTreeLock() + { + return treeLock; + } + + /** + * Returns the toolkit in use for this component. The toolkit is associated + * with the frame this component belongs to. + * + * @return the toolkit for this component + */ + public Toolkit getToolkit() + { + if (peer != null) + { + Toolkit tk = peer.getToolkit(); + if (tk != null) + return tk; + } + // Get toolkit for lightweight component. + if (parent != null) + return parent.getToolkit(); + return Toolkit.getDefaultToolkit(); + } + + /** + * Tests whether or not this component is valid. A invalid component needs + * to have its layout redone. + * + * @return true if this component is valid + * @see #validate() + * @see #invalidate() + */ + public boolean isValid() + { + return valid; + } + + /** + * Tests if the component is displayable. It must be connected to a native + * screen resource, and all its ancestors must be displayable. A containment + * hierarchy is made displayable when a window is packed or made visible. + * + * @return true if the component is displayable + * @see Container#add(Component) + * @see Container#remove(Component) + * @see Window#pack() + * @see Window#show() + * @see Window#dispose() + * @since 1.2 + */ + public boolean isDisplayable() + { + if (parent != null) + return parent.isDisplayable(); + return false; + } + + /** + * Tests whether or not this component is visible. Except for top-level + * frames, components are initially visible. + * + * @return true if the component is visible + * @see #setVisible(boolean) + */ + public boolean isVisible() + { + return visible; + } + + /** + * Tests whether or not this component is actually being shown on + * the screen. This will be true if and only if it this component is + * visible and its parent components are all visible. + * + * @return true if the component is showing on the screen + * @see #setVisible(boolean) + */ + public boolean isShowing() + { + if (! visible || peer == null) + return false; + + return parent == null ? true : parent.isShowing(); + } + + /** + * Tests whether or not this component is enabled. Components are enabled + * by default, and must be enabled to receive user input or generate events. + * + * @return true if the component is enabled + * @see #setEnabled(boolean) + */ + public boolean isEnabled() + { + return enabled; + } + + /** + * Enables or disables this component. The component must be enabled to + * receive events (except that lightweight components always receive mouse + * events). + * + * @param enabled true to enable this component + * + * @see #isEnabled() + * @see #isLightweight() + * + * @since 1.1 + */ + public void setEnabled(boolean enabled) + { + enable(enabled); + } + + /** + * Enables this component. + * + * @deprecated use {@link #setEnabled(boolean)} instead + */ + public void enable() + { + this.enabled = true; + if (peer != null) + peer.setEnabled (true); + } + + /** + * Enables or disables this component. + * + * @param enabled true to enable this component + * + * @deprecated use {@link #setEnabled(boolean)} instead + */ + public void enable(boolean enabled) + { + if (enabled) + enable(); + else + disable(); + } + + /** + * Disables this component. + * + * @deprecated use {@link #setEnabled(boolean)} instead + */ + public void disable() + { + this.enabled = false; + if (peer != null) + peer.setEnabled (false); + } + + /** + * Checks if this image is painted to an offscreen image buffer that is + * later copied to screen (double buffering reduces flicker). This version + * returns false, so subclasses must override it if they provide double + * buffering. + * + * @return true if this is double buffered; defaults to false + */ + public boolean isDoubleBuffered() + { + return false; + } + + /** + * Enables or disables input method support for this component. By default, + * components have this enabled. Input methods are given the opportunity + * to process key events before this component and its listeners. + * + * @param enable true to enable input method processing + * @see #processKeyEvent(KeyEvent) + * @since 1.2 + */ + public void enableInputMethods(boolean enable) + { + if (enable) + eventMask |= AWTEvent.INPUT_ENABLED_EVENT_MASK; + else + eventMask &= ~AWTEvent.INPUT_ENABLED_EVENT_MASK; + } + + /** + * Makes this component visible or invisible. Note that it wtill might + * not show the component, if a parent is invisible. + * + * @param visible true to make this component visible + * + * @see #isVisible() + * + * @since 1.1 + */ + public void setVisible(boolean visible) + { + // Inspection by subclassing shows that Sun's implementation calls + // show(boolean) which then calls show() or hide(). It is the show() + // method that is overriden in subclasses like Window. + show(visible); + } + + /** + * Makes this component visible on the screen. + * + * @deprecated use {@link #setVisible(boolean)} instead + */ + public void show() + { + // We must set visible before showing the peer. Otherwise the + // peer could post paint events before visible is true, in which + // case lightweight components are not initially painted -- + // Container.paint first calls isShowing () before painting itself + // and its children. + if(!isVisible()) + { + this.visible = true; + if (peer != null) + peer.setVisible(true); + invalidate(); + ComponentEvent ce = + new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN); + getToolkit().getSystemEventQueue().postEvent(ce); + } + } + + /** + * Makes this component visible or invisible. + * + * @param visible true to make this component visible + * + * @deprecated use {@link #setVisible(boolean)} instead + */ + public void show(boolean visible) + { + if (visible) + show(); + else + hide(); + } + + /** + * Hides this component so that it is no longer shown on the screen. + * + * @deprecated use {@link #setVisible(boolean)} instead + */ + public void hide() + { + if (isVisible()) + { + if (peer != null) + peer.setVisible(false); + this.visible = false; + invalidate(); + ComponentEvent ce = + new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN); + getToolkit().getSystemEventQueue().postEvent(ce); + } + } + + /** + * Returns this component's foreground color. If not set, this is inherited + * from the parent. + * + * @return this component's foreground color, or null + * @see #setForeground(Color) + */ + public Color getForeground() + { + if (foreground != null) + return foreground; + return parent == null ? SystemColor.windowText : parent.getForeground(); + } + + /** + * Sets this component's foreground color to the specified color. This is a + * bound property. + * + * @param c the new foreground color + * @see #getForeground() + */ + public void setForeground(Color c) + { + firePropertyChange("foreground", foreground, c); + if (peer != null) + peer.setForeground(c); + foreground = c; + } + + /** + * Tests if the foreground was explicitly set, or just inherited from the + * parent. + * + * @return true if the foreground has been set + * @since 1.4 + */ + public boolean isForegroundSet() + { + return foreground != null; + } + + /** + * Returns this component's background color. If not set, this is inherited + * from the parent. + * + * @return the background color of the component, or null + * @see #setBackground(Color) + */ + public Color getBackground() + { + if (background != null) + return background; + return parent == null ? SystemColor.window : parent.getBackground(); + } + + /** + * Sets this component's background color to the specified color. The parts + * of the component affected by the background color may by system dependent. + * This is a bound property. + * + * @param c the new background color + * @see #getBackground() + */ + public void setBackground(Color c) + { + // return if the background is already set to that color. + if (background != null && c != null) + if (background.equals(c)) + return; + // If c is null, inherit from closest ancestor whose bg is set. + if (c == null && parent != null) + c = parent.getBackground(); + firePropertyChange("background", background, c); + if (peer != null && c != null) + peer.setBackground(c); + background = c; + } + + /** + * Tests if the background was explicitly set, or just inherited from the + * parent. + * + * @return true if the background has been set + * @since 1.4 + */ + public boolean isBackgroundSet() + { + return background != null; + } + + /** + * Returns the font in use for this component. If not set, this is inherited + * from the parent. + * + * @return the font for this component + * @see #setFont(Font) + */ + public Font getFont() + { + if (font != null) + return font; + + if (parent != null) + return parent.getFont (); + else + return new Font ("Dialog", Font.PLAIN, 12); + } + + /** + * Sets the font for this component to the specified font. This is a bound + * property. + * + * @param newFont the new font for this component + * + * @see #getFont() + */ + public void setFont(Font newFont) + { + if (font == newFont) + return; + + Font oldFont = font; + font = newFont; + if (peer != null) + peer.setFont(font); + firePropertyChange("font", oldFont, newFont); + invalidate(); + } + + /** + * Tests if the font was explicitly set, or just inherited from the parent. + * + * @return true if the font has been set + * @since 1.4 + */ + public boolean isFontSet() + { + return font != null; + } + + /** + * Returns the locale for this component. If this component does not + * have a locale, the locale of the parent component is returned. + * + * @return the locale for this component + * @throws IllegalComponentStateException if it has no locale or parent + * @see #setLocale(Locale) + * @since 1.1 + */ + public Locale getLocale() + { + if (locale != null) + return locale; + if (parent == null) + throw new IllegalComponentStateException + ("Component has no parent: can't determine Locale"); + return parent.getLocale(); + } + + /** + * Sets the locale for this component to the specified locale. This is a + * bound property. + * + * @param newLocale the new locale for this component + */ + public void setLocale(Locale newLocale) + { + if (locale == newLocale) + return; + + Locale oldLocale = locale; + locale = newLocale; + firePropertyChange("locale", oldLocale, newLocale); + // New writing/layout direction or more/less room for localized labels. + invalidate(); + } + + /** + * Returns the color model of the device this componet is displayed on. + * + * @return this object's color model + * @see Toolkit#getColorModel() + */ + public ColorModel getColorModel() + { + GraphicsConfiguration config = getGraphicsConfiguration(); + return config != null ? config.getColorModel() + : getToolkit().getColorModel(); + } + + /** + * Returns the location of this component's top left corner relative to + * its parent component. This may be outdated, so for synchronous behavior, + * you should use a component listner. + * + * @return the location of this component + * @see #setLocation(int, int) + * @see #getLocationOnScreen() + * @since 1.1 + */ + public Point getLocation() + { + return location (); + } + + /** + * Returns the location of this component's top left corner in screen + * coordinates. + * + * @return the location of this component in screen coordinates + * @throws IllegalComponentStateException if the component is not showing + */ + public Point getLocationOnScreen() + { + if (! isShowing()) + throw new IllegalComponentStateException("component " + + getClass().getName() + + " not showing"); + // We know peer != null here. + return peer.getLocationOnScreen(); + } + + /** + * Returns the location of this component's top left corner relative to + * its parent component. + * + * @return the location of this component + * @deprecated use {@link #getLocation()} instead + */ + public Point location() + { + return new Point (x, y); + } + + /** + * Moves this component to the specified location, relative to the parent's + * coordinates. The coordinates are the new upper left corner of this + * component. + * + * @param x the new X coordinate of this component + * @param y the new Y coordinate of this component + * @see #getLocation() + * @see #setBounds(int, int, int, int) + */ + public void setLocation(int x, int y) + { + move (x, y); + } + + /** + * Moves this component to the specified location, relative to the parent's + * coordinates. The coordinates are the new upper left corner of this + * component. + * + * @param x the new X coordinate of this component + * @param y the new Y coordinate of this component + * @deprecated use {@link #setLocation(int, int)} instead + */ + public void move(int x, int y) + { + setBounds(x, y, this.width, this.height); + } + + /** + * Moves this component to the specified location, relative to the parent's + * coordinates. The coordinates are the new upper left corner of this + * component. + * + * @param p new coordinates for this component + * @throws NullPointerException if p is null + * @see #getLocation() + * @see #setBounds(int, int, int, int) + * @since 1.1 + */ + public void setLocation(Point p) + { + setLocation(p.x, p.y); + } + + /** + * Returns the size of this object. + * + * @return the size of this object + * @see #setSize(int, int) + * @since 1.1 + */ + public Dimension getSize() + { + return size (); + } + + /** + * Returns the size of this object. + * + * @return the size of this object + * @deprecated use {@link #getSize()} instead + */ + public Dimension size() + { + return new Dimension (width, height); + } + + /** + * Sets the size of this component to the specified width and height. + * + * @param width the new width of this component + * @param height the new height of this component + * @see #getSize() + * @see #setBounds(int, int, int, int) + */ + public void setSize(int width, int height) + { + resize (width, height); + } + + /** + * Sets the size of this component to the specified value. + * + * @param width the new width of the component + * @param height the new height of the component + * @deprecated use {@link #setSize(int, int)} instead + */ + public void resize(int width, int height) + { + setBounds(this.x, this.y, width, height); + } + + /** + * Sets the size of this component to the specified value. + * + * @param d the new size of this component + * @throws NullPointerException if d is null + * @see #setSize(int, int) + * @see #setBounds(int, int, int, int) + * @since 1.1 + */ + public void setSize(Dimension d) + { + resize (d); + } + + /** + * Sets the size of this component to the specified value. + * + * @param d the new size of this component + * @throws NullPointerException if d is null + * @deprecated use {@link #setSize(Dimension)} instead + */ + public void resize(Dimension d) + { + resize (d.width, d.height); + } + + /** + * Returns a bounding rectangle for this component. Note that the + * returned rectange is relative to this component's parent, not to + * the screen. + * + * @return the bounding rectangle for this component + * @see #setBounds(int, int, int, int) + * @see #getLocation() + * @see #getSize() + */ + public Rectangle getBounds() + { + return bounds (); + } + + /** + * Returns a bounding rectangle for this component. Note that the + * returned rectange is relative to this component's parent, not to + * the screen. + * + * @return the bounding rectangle for this component + * @deprecated use {@link #getBounds()} instead + */ + public Rectangle bounds() + { + return new Rectangle (x, y, width, height); + } + + /** + * Sets the bounding rectangle for this component to the specified values. + * Note that these coordinates are relative to the parent, not to the screen. + * + * @param x the X coordinate of the upper left corner of the rectangle + * @param y the Y coordinate of the upper left corner of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @see #getBounds() + * @see #setLocation(int, int) + * @see #setLocation(Point) + * @see #setSize(int, int) + * @see #setSize(Dimension) + * @since 1.1 + */ + public void setBounds(int x, int y, int w, int h) + { + reshape (x, y, w, h); + } + + /** + * Sets the bounding rectangle for this component to the specified values. + * Note that these coordinates are relative to the parent, not to the screen. + * + * @param x the X coordinate of the upper left corner of the rectangle + * @param y the Y coordinate of the upper left corner of the rectangle + * @param width the width of the rectangle + * @param height the height of the rectangle + * @deprecated use {@link #setBounds(int, int, int, int)} instead + */ + public void reshape(int x, int y, int width, int height) + { + int oldx = this.x; + int oldy = this.y; + int oldwidth = this.width; + int oldheight = this.height; + + if (this.x == x && this.y == y + && this.width == width && this.height == height) + return; + invalidate (); + this.x = x; + this.y = y; + this.width = width; + this.height = height; + if (peer != null) + peer.setBounds (x, y, width, height); + + // Erase old bounds and repaint new bounds for lightweights. + if (isLightweight() && isShowing ()) + { + boolean shouldRepaintParent = false; + boolean shouldRepaintSelf = false; + + if (parent != null) + { + Rectangle parentBounds = parent.getBounds(); + Rectangle oldBounds = new Rectangle(parent.getX() + oldx, + parent.getY() + oldy, + oldwidth, oldheight); + Rectangle newBounds = new Rectangle(parent.getX() + x, + parent.getY() + y, + width, height); + shouldRepaintParent = parentBounds.intersects(oldBounds); + shouldRepaintSelf = parentBounds.intersects(newBounds); + } + + if (shouldRepaintParent && parent != null) + parent.repaint(oldx, oldy, oldwidth, oldheight); + if (shouldRepaintSelf) + repaint(); + } + + // Only post event if this component is visible and has changed size. + if (isShowing () + && (oldx != x || oldy != y)) + { + ComponentEvent ce = new ComponentEvent(this, + ComponentEvent.COMPONENT_MOVED); + getToolkit().getSystemEventQueue().postEvent(ce); + } + if (isShowing () + && (oldwidth != width || oldheight != height)) + { + ComponentEvent ce = new ComponentEvent(this, + ComponentEvent.COMPONENT_RESIZED); + getToolkit().getSystemEventQueue().postEvent(ce); + } + } + + /** + * Sets the bounding rectangle for this component to the specified + * rectangle. Note that these coordinates are relative to the parent, not + * to the screen. + * + * @param r the new bounding rectangle + * @throws NullPointerException if r is null + * @see #getBounds() + * @see #setLocation(Point) + * @see #setSize(Dimension) + * @since 1.1 + */ + public void setBounds(Rectangle r) + { + setBounds (r.x, r.y, r.width, r.height); + } + + /** + * Gets the x coordinate of the upper left corner. This is more efficient + * than getBounds().x or getLocation().x. + * + * @return the current x coordinate + * @since 1.2 + */ + public int getX() + { + return x; + } + + /** + * Gets the y coordinate of the upper left corner. This is more efficient + * than getBounds().y or getLocation().y. + * + * @return the current y coordinate + * @since 1.2 + */ + public int getY() + { + return y; + } + + /** + * Gets the width of the component. This is more efficient than + * getBounds().width or getSize().width. + * + * @return the current width + * @since 1.2 + */ + public int getWidth() + { + return width; + } + + /** + * Gets the height of the component. This is more efficient than + * getBounds().height or getSize().height. + * + * @return the current width + * @since 1.2 + */ + public int getHeight() + { + return height; + } + + /** + * Returns the bounds of this component. This allows reuse of an existing + * rectangle, if r is non-null. + * + * @param r the rectangle to use, or null + * @return the bounds + */ + public Rectangle getBounds(Rectangle r) + { + if (r == null) + r = new Rectangle(); + r.x = x; + r.y = y; + r.width = width; + r.height = height; + return r; + } + + /** + * Returns the size of this component. This allows reuse of an existing + * dimension, if d is non-null. + * + * @param d the dimension to use, or null + * @return the size + */ + public Dimension getSize(Dimension d) + { + if (d == null) + d = new Dimension(); + d.width = width; + d.height = height; + return d; + } + + /** + * Returns the location of this component. This allows reuse of an existing + * point, if p is non-null. + * + * @param p the point to use, or null + * @return the location + */ + public Point getLocation(Point p) + { + if (p == null) + p = new Point(); + p.x = x; + p.y = y; + return p; + } + + /** + * Tests if this component is opaque. All "heavyweight" (natively-drawn) + * components are opaque. A component is opaque if it draws all pixels in + * the bounds; a lightweight component is partially transparent if it lets + * pixels underneath show through. Subclasses that guarantee that all pixels + * will be drawn should override this. + * + * @return true if this is opaque + * @see #isLightweight() + * @since 1.2 + */ + public boolean isOpaque() + { + return ! isLightweight(); + } + + /** + * Return whether the component is lightweight. That means the component has + * no native peer, but is displayable. This applies to subclasses of + * Component not in this package, such as javax.swing. + * + * @return true if the component has a lightweight peer + * @see #isDisplayable() + * @since 1.2 + */ + public boolean isLightweight() + { + return peer instanceof LightweightPeer; + } + + /** + * Returns the component's preferred size. + * + * @return the component's preferred size + * @see #getMinimumSize() + * @see LayoutManager + */ + public Dimension getPreferredSize() + { + return preferredSize(); + } + + /** + * Returns the component's preferred size. + * + * @return the component's preferred size + * @deprecated use {@link #getPreferredSize()} instead + */ + public Dimension preferredSize() + { + if (prefSize == null) + if (peer == null) + return new Dimension(width, height); + else + prefSize = peer.getPreferredSize(); + return prefSize; + } + + /** + * Returns the component's minimum size. + * + * @return the component's minimum size + * @see #getPreferredSize() + * @see LayoutManager + */ + public Dimension getMinimumSize() + { + return minimumSize(); + } + + /** + * Returns the component's minimum size. + * + * @return the component's minimum size + * @deprecated use {@link #getMinimumSize()} instead + */ + public Dimension minimumSize() + { + if (minSize == null) + minSize = (peer != null ? peer.getMinimumSize() + : new Dimension(width, height)); + return minSize; + } + + /** + * Returns the component's maximum size. + * + * @return the component's maximum size + * @see #getMinimumSize() + * @see #getPreferredSize() + * @see LayoutManager + */ + public Dimension getMaximumSize() + { + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + /** + * Returns the preferred horizontal alignment of this component. The value + * returned will be between {@link #LEFT_ALIGNMENT} and + * {@link #RIGHT_ALIGNMENT}, inclusive. + * + * @return the preferred horizontal alignment of this component + */ + public float getAlignmentX() + { + return CENTER_ALIGNMENT; + } + + /** + * Returns the preferred vertical alignment of this component. The value + * returned will be between {@link #TOP_ALIGNMENT} and + * {@link #BOTTOM_ALIGNMENT}, inclusive. + * + * @return the preferred vertical alignment of this component + */ + public float getAlignmentY() + { + return CENTER_ALIGNMENT; + } + + /** + * Calls the layout manager to re-layout the component. This is called + * during validation of a container in most cases. + * + * @see #validate() + * @see LayoutManager + */ + public void doLayout() + { + layout (); + } + + /** + * Calls the layout manager to re-layout the component. This is called + * during validation of a container in most cases. + * + * @deprecated use {@link #doLayout()} instead + */ + public void layout() + { + // Nothing to do unless we're a container. + } + + /** + * Called to ensure that the layout for this component is valid. This is + * usually called on containers. + * + * @see #invalidate() + * @see #doLayout() + * @see LayoutManager + * @see Container#validate() + */ + public void validate() + { + valid = true; + } + + /** + * Invalidates this component and all of its parent components. This will + * cause them to have their layout redone. This is called frequently, so + * make it fast. + */ + public void invalidate() + { + valid = false; + prefSize = null; + minSize = null; + if (parent != null && parent.valid) + parent.invalidate(); + } + + /** + * Returns a graphics object for this component. Returns <code>null</code> + * if this component is not currently displayed on the screen. + * + * @return a graphics object for this component + * @see #paint(Graphics) + */ + public Graphics getGraphics() + { + if (peer != null) + { + Graphics gfx = peer.getGraphics(); + if (gfx != null) + return gfx; + // create graphics for lightweight: + Container parent = getParent(); + if (parent != null) + { + gfx = parent.getGraphics(); + Rectangle bounds = getBounds(); + gfx.setClip(bounds); + gfx.translate(bounds.x, bounds.y); + return gfx; + } + } + return null; + } + + /** + * Returns the font metrics for the specified font in this component. + * + * @param font the font to retrieve metrics for + * @return the font metrics for the specified font + * @throws NullPointerException if font is null + * @see #getFont() + * @see Toolkit#getFontMetrics(Font) + */ + public FontMetrics getFontMetrics(Font font) + { + return peer == null ? getToolkit().getFontMetrics(font) + : peer.getFontMetrics(font); + } + + /** + * Sets the cursor for this component to the specified cursor. The cursor + * is displayed when the point is contained by the component, and the + * component is visible, displayable, and enabled. This is inherited by + * subcomponents unless they set their own cursor. + * + * @param cursor the new cursor for this component + * @see #isEnabled() + * @see #isShowing() + * @see #getCursor() + * @see #contains(int, int) + * @see Toolkit#createCustomCursor(Image, Point, String) + */ + public void setCursor(Cursor cursor) + { + this.cursor = cursor; + if (peer != null) + peer.setCursor(cursor); + } + + /** + * Returns the cursor for this component. If not set, this is inherited + * from the parent, or from Cursor.getDefaultCursor(). + * + * @return the cursor for this component + */ + public Cursor getCursor() + { + if (cursor != null) + return cursor; + return parent != null ? parent.getCursor() : Cursor.getDefaultCursor(); + } + + /** + * Tests if the cursor was explicitly set, or just inherited from the parent. + * + * @return true if the cursor has been set + * @since 1.4 + */ + public boolean isCursorSet() + { + return cursor != null; + } + + /** + * Paints this component on the screen. The clipping region in the graphics + * context will indicate the region that requires painting. This is called + * whenever the component first shows, or needs to be repaired because + * something was temporarily drawn on top. It is not necessary for + * subclasses to call <code>super.paint(g)</code>. Components with no area + * are not painted. + * + * @param g the graphics context for this paint job + * @see #update(Graphics) + */ + public void paint(Graphics g) + { + // Paint the heavyweight peer + if (!isLightweight() && peer != null) + peer.paint(g); + } + + /** + * Updates this component. This is called in response to + * <code>repaint</code>. This method fills the component with the + * background color, then sets the foreground color of the specified + * graphics context to the foreground color of this component and calls + * the <code>paint()</code> method. The coordinates of the graphics are + * relative to this component. Subclasses should call either + * <code>super.update(g)</code> or <code>paint(g)</code>. + * + * @param g the graphics context for this update + * + * @see #paint(Graphics) + * @see #repaint() + */ + public void update(Graphics g) + { + if (!isLightweight()) + { + Rectangle clip = g.getClipBounds(); + if (clip == null) + g.clearRect(0, 0, width, height); + else + g.clearRect(clip.x, clip.y, clip.width, clip.height); + } + + paint(g); + } + + /** + * Paints this entire component, including any sub-components. + * + * @param g the graphics context for this paint job + * + * @see #paint(Graphics) + */ + public void paintAll(Graphics g) + { + if (! visible) + return; + paint(g); + } + + /** + * Repaint this entire component. The <code>update()</code> method + * on this component will be called as soon as possible. + * + * @see #update(Graphics) + * @see #repaint(long, int, int, int, int) + */ + public void repaint() + { + repaint(0, 0, 0, width, height); + } + + /** + * Repaint this entire component. The <code>update()</code> method on this + * component will be called in approximate the specified number of + * milliseconds. + * + * @param tm milliseconds before this component should be repainted + * @see #paint(Graphics) + * @see #repaint(long, int, int, int, int) + */ + public void repaint(long tm) + { + repaint(tm, 0, 0, width, height); + } + + /** + * Repaints the specified rectangular region within this component. The + * <code>update</code> method on this component will be called as soon as + * possible. The coordinates are relative to this component. + * + * @param x the X coordinate of the upper left of the region to repaint + * @param y the Y coordinate of the upper left of the region to repaint + * @param w the width of the region to repaint + * @param h the height of the region to repaint + * @see #update(Graphics) + * @see #repaint(long, int, int, int, int) + */ + public void repaint(int x, int y, int w, int h) + { + repaint(0, x, y, w, h); + } + + /** + * Repaints the specified rectangular region within this component. The + * <code>update</code> method on this component will be called in + * approximately the specified number of milliseconds. The coordinates + * are relative to this component. + * + * @param tm milliseconds before this component should be repainted + * @param x the X coordinate of the upper left of the region to repaint + * @param y the Y coordinate of the upper left of the region to repaint + * @param width the width of the region to repaint + * @param height the height of the region to repaint + * @see #update(Graphics) + */ + public void repaint(long tm, int x, int y, int width, int height) + { + // Handle lightweight repainting by forwarding to native parent + if (isLightweight() && parent != null) + { + if (parent != null) + parent.repaint(tm, x + getX(), y + getY(), width, height); + } + else if (peer != null) + peer.repaint(tm, x, y, width, height); + } + + /** + * Prints this component. This method is provided so that printing can be + * done in a different manner from painting. However, the implementation + * in this class simply calls the <code>paint()</code> method. + * + * @param g the graphics context of the print device + * + * @see #paint(Graphics) + */ + public void print(Graphics g) + { + paint(g); + } + + /** + * Prints this component, including all sub-components. This method is + * provided so that printing can be done in a different manner from + * painting. However, the implementation in this class simply calls the + * <code>paintAll()</code> method. + * + * @param g the graphics context of the print device + * + * @see #paintAll(Graphics) + */ + public void printAll(Graphics g) + { + paintAll(g); + } + + /** + * Called when an image has changed so that this component is repainted. + * This incrementally draws an image as more bits are available, when + * possible. Incremental drawing is enabled if the system property + * <code>awt.image.incrementalDraw</code> is not present or is true, in which + * case the redraw rate is set to 100ms or the value of the system property + * <code>awt.image.redrawrate</code>. + * + * <p>The coordinate system used depends on the particular flags. + * + * @param img the image that has been updated + * @param flags tlags as specified in <code>ImageObserver</code> + * @param x the X coordinate + * @param y the Y coordinate + * @param w the width + * @param h the height + * @return false if the image is completely loaded, loading has been + * aborted, or an error has occurred. true if more updates are + * required. + * @see ImageObserver + * @see Graphics#drawImage(Image, int, int, Color, ImageObserver) + * @see Graphics#drawImage(Image, int, int, ImageObserver) + * @see Graphics#drawImage(Image, int, int, int, int, Color, ImageObserver) + * @see Graphics#drawImage(Image, int, int, int, int, ImageObserver) + * @see ImageObserver#imageUpdate(Image, int, int, int, int, int) + */ + public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) + { + if ((flags & (FRAMEBITS | ALLBITS)) != 0) + repaint (); + else if ((flags & SOMEBITS) != 0) + { + if (incrementalDraw) + { + if (redrawRate != null) + { + long tm = redrawRate.longValue(); + if (tm < 0) + tm = 0; + repaint (tm); + } + else + repaint (100); + } + } + return (flags & (ALLBITS | ABORT | ERROR)) == 0; + } + + /** + * Creates an image from the specified producer. + * + * @param producer the image procedure to create the image from + * @return the resulting image + */ + public Image createImage(ImageProducer producer) + { + // Sun allows producer to be null. + if (peer != null) + return peer.createImage(producer); + else + return getToolkit().createImage(producer); + } + + /** + * Creates an image with the specified width and height for use in + * double buffering. Headless environments do not support images. + * + * @param width the width of the image + * @param height the height of the image + * @return the requested image, or null if it is not supported + */ + public Image createImage (int width, int height) + { + Image returnValue = null; + if (!GraphicsEnvironment.isHeadless ()) + { + if (isLightweight () && parent != null) + returnValue = parent.createImage (width, height); + else if (peer != null) + returnValue = peer.createImage (width, height); + } + return returnValue; + } + + /** + * Creates an image with the specified width and height for use in + * double buffering. Headless environments do not support images. + * + * @param width the width of the image + * @param height the height of the image + * @return the requested image, or null if it is not supported + * @since 1.4 + */ + public VolatileImage createVolatileImage(int width, int height) + { + if (GraphicsEnvironment.isHeadless()) + return null; + GraphicsConfiguration config = getGraphicsConfiguration(); + return config == null ? null + : config.createCompatibleVolatileImage(width, height); + } + + /** + * Creates an image with the specified width and height for use in + * double buffering. Headless environments do not support images. The image + * will support the specified capabilities. + * + * @param width the width of the image + * @param height the height of the image + * @param caps the requested capabilities + * @return the requested image, or null if it is not supported + * @throws AWTException if a buffer with the capabilities cannot be created + * @since 1.4 + */ + public VolatileImage createVolatileImage(int width, int height, + ImageCapabilities caps) + throws AWTException + { + if (GraphicsEnvironment.isHeadless()) + return null; + GraphicsConfiguration config = getGraphicsConfiguration(); + return config == null ? null + : config.createCompatibleVolatileImage(width, height, caps); + } + + /** + * Prepares the specified image for rendering on this component. + * + * @param image the image to prepare for rendering + * @param observer the observer to notify of image preparation status + * @return true if the image is already fully prepared + * @throws NullPointerException if image is null + */ + public boolean prepareImage(Image image, ImageObserver observer) + { + return prepareImage(image, image.getWidth(observer), + image.getHeight(observer), observer); + } + + /** + * Prepares the specified image for rendering on this component at the + * specified scaled width and height + * + * @param image the image to prepare for rendering + * @param width the scaled width of the image + * @param height the scaled height of the image + * @param observer the observer to notify of image preparation status + * @return true if the image is already fully prepared + */ + public boolean prepareImage(Image image, int width, int height, + ImageObserver observer) + { + if (peer != null) + return peer.prepareImage(image, width, height, observer); + else + return getToolkit().prepareImage(image, width, height, observer); + } + + /** + * Returns the status of the loading of the specified image. The value + * returned will be those flags defined in <code>ImageObserver</code>. + * + * @param image the image to check on + * @param observer the observer to notify of image loading progress + * @return the image observer flags indicating the status of the load + * @see #prepareImage(Image, int, int, ImageObserver) + * @see Toolkit#checkImage(Image, int, int, ImageObserver) + * @throws NullPointerException if image is null + */ + public int checkImage(Image image, ImageObserver observer) + { + return checkImage(image, -1, -1, observer); + } + + /** + * Returns the status of the loading of the specified image. The value + * returned will be those flags defined in <code>ImageObserver</code>. + * + * @param image the image to check on + * @param width the scaled image width + * @param height the scaled image height + * @param observer the observer to notify of image loading progress + * @return the image observer flags indicating the status of the load + * @see #prepareImage(Image, int, int, ImageObserver) + * @see Toolkit#checkImage(Image, int, int, ImageObserver) + */ + public int checkImage(Image image, int width, int height, + ImageObserver observer) + { + if (peer != null) + return peer.checkImage(image, width, height, observer); + return getToolkit().checkImage(image, width, height, observer); + } + + /** + * Sets whether paint messages delivered by the operating system should be + * ignored. This does not affect messages from AWT, except for those + * triggered by OS messages. Setting this to true can allow faster + * performance in full-screen mode or page-flipping. + * + * @param ignoreRepaint the new setting for ignoring repaint events + * @see #getIgnoreRepaint() + * @see BufferStrategy + * @see GraphicsDevice#setFullScreenWindow(Window) + * @since 1.4 + */ + public void setIgnoreRepaint(boolean ignoreRepaint) + { + this.ignoreRepaint = ignoreRepaint; + } + + /** + * Test whether paint events from the operating system are ignored. + * + * @return the status of ignoring paint events + * @see #setIgnoreRepaint(boolean) + * @since 1.4 + */ + public boolean getIgnoreRepaint() + { + return ignoreRepaint; + } + + /** + * Tests whether or not the specified point is contained within this + * component. Coordinates are relative to this component. + * + * @param x the X coordinate of the point to test + * @param y the Y coordinate of the point to test + * @return true if the point is within this component + * @see #getComponentAt(int, int) + */ + public boolean contains(int x, int y) + { + return inside (x, y); + } + + /** + * Tests whether or not the specified point is contained within this + * component. Coordinates are relative to this component. + * + * @param x the X coordinate of the point to test + * @param y the Y coordinate of the point to test + * @return true if the point is within this component + * @deprecated use {@link #contains(int, int)} instead + */ + public boolean inside(int x, int y) + { + return x >= 0 && y >= 0 && x < width && y < height; + } + + /** + * Tests whether or not the specified point is contained within this + * component. Coordinates are relative to this component. + * + * @param p the point to test + * @return true if the point is within this component + * @throws NullPointerException if p is null + * @see #getComponentAt(Point) + * @since 1.1 + */ + public boolean contains(Point p) + { + return contains (p.x, p.y); + } + + /** + * Returns the component occupying the position (x,y). This will either + * be this component, an immediate child component, or <code>null</code> + * if neither of the first two occupies the specified location. + * + * @param x the X coordinate to search for components at + * @param y the Y coordinate to search for components at + * @return the component at the specified location, or null + * @see #contains(int, int) + */ + public Component getComponentAt(int x, int y) + { + return locate (x, y); + } + + /** + * Returns the component occupying the position (x,y). This will either + * be this component, an immediate child component, or <code>null</code> + * if neither of the first two occupies the specified location. + * + * @param x the X coordinate to search for components at + * @param y the Y coordinate to search for components at + * @return the component at the specified location, or null + * @deprecated use {@link #getComponentAt(int, int)} instead + */ + public Component locate(int x, int y) + { + return contains (x, y) ? this : null; + } + + /** + * Returns the component occupying the position (x,y). This will either + * be this component, an immediate child component, or <code>null</code> + * if neither of the first two occupies the specified location. + * + * @param p the point to search for components at + * @return the component at the specified location, or null + * @throws NullPointerException if p is null + * @see #contains(Point) + * @since 1.1 + */ + public Component getComponentAt(Point p) + { + return getComponentAt (p.x, p.y); + } + + /** + * AWT 1.0 event delivery. + * + * Deliver an AWT 1.0 event to this Component. This method simply + * calls {@link #postEvent}. + * + * @param e the event to deliver + * @deprecated use {@link #dispatchEvent (AWTEvent)} instead + */ + public void deliverEvent (Event e) + { + postEvent (e); + } + + /** + * Forwards AWT events to processEvent() if:<ul> + * <li>Events have been enabled for this type of event via + * <code>enableEvents()</code></li>, + * <li>There is at least one registered listener for this type of event</li> + * </ul> + * + * @param e the event to dispatch + */ + public final void dispatchEvent(AWTEvent e) + { + // Some subclasses in the AWT package need to override this behavior, + // hence the use of dispatchEventImpl(). + dispatchEventImpl(e); + if (peer != null && ! e.consumed) + peer.handleEvent(e); + } + + /** + * AWT 1.0 event handler. + * + * This method simply calls handleEvent and returns the result. + * + * @param e the event to handle + * @return true if the event was handled, false otherwise + * @deprecated use {@link #dispatchEvent(AWTEvent)} instead + */ + public boolean postEvent (Event e) + { + boolean handled = handleEvent (e); + + if (!handled && getParent() != null) + // FIXME: need to translate event coordinates to parent's + // coordinate space. + handled = getParent ().postEvent (e); + + return handled; + } + + /** + * Adds the specified listener to this component. This is harmless if the + * listener is null, but if the listener has already been registered, it + * will now be registered twice. + * + * @param listener the new listener to add + * @see ComponentEvent + * @see #removeComponentListener(ComponentListener) + * @see #getComponentListeners() + * @since 1.1 + */ + public synchronized void addComponentListener(ComponentListener listener) + { + componentListener = AWTEventMulticaster.add(componentListener, listener); + if (componentListener != null) + enableEvents(AWTEvent.COMPONENT_EVENT_MASK); + } + + /** + * Removes the specified listener from the component. This is harmless if + * the listener was not previously registered. + * + * @param listener the listener to remove + * @see ComponentEvent + * @see #addComponentListener(ComponentListener) + * @see #getComponentListeners() + * @since 1.1 + */ + public synchronized void removeComponentListener(ComponentListener listener) + { + componentListener = AWTEventMulticaster.remove(componentListener, listener); + } + + /** + * Returns an array of all specified listeners registered on this component. + * + * @return an array of listeners + * @see #addComponentListener(ComponentListener) + * @see #removeComponentListener(ComponentListener) + * @since 1.4 + */ + public synchronized ComponentListener[] getComponentListeners() + { + return (ComponentListener[]) + AWTEventMulticaster.getListeners(componentListener, + ComponentListener.class); + } + + /** + * Adds the specified listener to this component. This is harmless if the + * listener is null, but if the listener has already been registered, it + * will now be registered twice. + * + * @param listener the new listener to add + * @see FocusEvent + * @see #removeFocusListener(FocusListener) + * @see #getFocusListeners() + * @since 1.1 + */ + public synchronized void addFocusListener(FocusListener listener) + { + focusListener = AWTEventMulticaster.add(focusListener, listener); + if (focusListener != null) + enableEvents(AWTEvent.FOCUS_EVENT_MASK); + } + + /** + * Removes the specified listener from the component. This is harmless if + * the listener was not previously registered. + * + * @param listener the listener to remove + * @see FocusEvent + * @see #addFocusListener(FocusListener) + * @see #getFocusListeners() + * @since 1.1 + */ + public synchronized void removeFocusListener(FocusListener listener) + { + focusListener = AWTEventMulticaster.remove(focusListener, listener); + } + + /** + * Returns an array of all specified listeners registered on this component. + * + * @return an array of listeners + * @see #addFocusListener(FocusListener) + * @see #removeFocusListener(FocusListener) + * @since 1.4 + */ + public synchronized FocusListener[] getFocusListeners() + { + return (FocusListener[]) + AWTEventMulticaster.getListeners(focusListener, FocusListener.class); + } + + /** + * Adds the specified listener to this component. This is harmless if the + * listener is null, but if the listener has already been registered, it + * will now be registered twice. + * + * @param listener the new listener to add + * @see HierarchyEvent + * @see #removeHierarchyListener(HierarchyListener) + * @see #getHierarchyListeners() + * @since 1.3 + */ + public synchronized void addHierarchyListener(HierarchyListener listener) + { + hierarchyListener = AWTEventMulticaster.add(hierarchyListener, listener); + if (hierarchyListener != null) + enableEvents(AWTEvent.HIERARCHY_EVENT_MASK); + } + + /** + * Removes the specified listener from the component. This is harmless if + * the listener was not previously registered. + * + * @param listener the listener to remove + * @see HierarchyEvent + * @see #addHierarchyListener(HierarchyListener) + * @see #getHierarchyListeners() + * @since 1.3 + */ + public synchronized void removeHierarchyListener(HierarchyListener listener) + { + hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, listener); + } + + /** + * Returns an array of all specified listeners registered on this component. + * + * @return an array of listeners + * @see #addHierarchyListener(HierarchyListener) + * @see #removeHierarchyListener(HierarchyListener) + * @since 1.4 + */ + public synchronized HierarchyListener[] getHierarchyListeners() + { + return (HierarchyListener[]) + AWTEventMulticaster.getListeners(hierarchyListener, + HierarchyListener.class); + } + + /** + * Adds the specified listener to this component. This is harmless if the + * listener is null, but if the listener has already been registered, it + * will now be registered twice. + * + * @param listener the new listener to add + * @see HierarchyEvent + * @see #removeHierarchyBoundsListener(HierarchyBoundsListener) + * @see #getHierarchyBoundsListeners() + * @since 1.3 + */ + public synchronized void + addHierarchyBoundsListener(HierarchyBoundsListener listener) + { + hierarchyBoundsListener = + AWTEventMulticaster.add(hierarchyBoundsListener, listener); + if (hierarchyBoundsListener != null) + enableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK); + } + + /** + * Removes the specified listener from the component. This is harmless if + * the listener was not previously registered. + * + * @param listener the listener to remove + * @see HierarchyEvent + * @see #addHierarchyBoundsListener(HierarchyBoundsListener) + * @see #getHierarchyBoundsListeners() + * @since 1.3 + */ + public synchronized void + removeHierarchyBoundsListener(HierarchyBoundsListener listener) + { + hierarchyBoundsListener = + AWTEventMulticaster.remove(hierarchyBoundsListener, listener); + } + + /** + * Returns an array of all specified listeners registered on this component. + * + * @return an array of listeners + * @see #addHierarchyBoundsListener(HierarchyBoundsListener) + * @see #removeHierarchyBoundsListener(HierarchyBoundsListener) + * @since 1.4 + */ + public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners() + { + return (HierarchyBoundsListener[]) + AWTEventMulticaster.getListeners(hierarchyBoundsListener, + HierarchyBoundsListener.class); + } + + /** + * Adds the specified listener to this component. This is harmless if the + * listener is null, but if the listener has already been registered, it + * will now be registered twice. + * + * @param listener the new listener to add + * @see KeyEvent + * @see #removeKeyListener(KeyListener) + * @see #getKeyListeners() + * @since 1.1 + */ + public synchronized void addKeyListener(KeyListener listener) + { + keyListener = AWTEventMulticaster.add(keyListener, listener); + if (keyListener != null) + enableEvents(AWTEvent.KEY_EVENT_MASK); + } + + /** + * Removes the specified listener from the component. This is harmless if + * the listener was not previously registered. + * + * @param listener the listener to remove + * @see KeyEvent + * @see #addKeyListener(KeyListener) + * @see #getKeyListeners() + * @since 1.1 + */ + public synchronized void removeKeyListener(KeyListener listener) + { + keyListener = AWTEventMulticaster.remove(keyListener, listener); + } + + /** + * Returns an array of all specified listeners registered on this component. + * + * @return an array of listeners + * @see #addKeyListener(KeyListener) + * @see #removeKeyListener(KeyListener) + * @since 1.4 + */ + public synchronized KeyListener[] getKeyListeners() + { + return (KeyListener[]) + AWTEventMulticaster.getListeners(keyListener, KeyListener.class); + } + + /** + * Adds the specified listener to this component. This is harmless if the + * listener is null, but if the listener has already been registered, it + * will now be registered twice. + * + * @param listener the new listener to add + * @see MouseEvent + * @see #removeMouseListener(MouseListener) + * @see #getMouseListeners() + * @since 1.1 + */ + public synchronized void addMouseListener(MouseListener listener) + { + mouseListener = AWTEventMulticaster.add(mouseListener, listener); + if (mouseListener != null) + enableEvents(AWTEvent.MOUSE_EVENT_MASK); + } + + /** + * Removes the specified listener from the component. This is harmless if + * the listener was not previously registered. + * + * @param listener the listener to remove + * @see MouseEvent + * @see #addMouseListener(MouseListener) + * @see #getMouseListeners() + * @since 1.1 + */ + public synchronized void removeMouseListener(MouseListener listener) + { + mouseListener = AWTEventMulticaster.remove(mouseListener, listener); + } + + /** + * Returns an array of all specified listeners registered on this component. + * + * @return an array of listeners + * @see #addMouseListener(MouseListener) + * @see #removeMouseListener(MouseListener) + * @since 1.4 + */ + public synchronized MouseListener[] getMouseListeners() + { + return (MouseListener[]) + AWTEventMulticaster.getListeners(mouseListener, MouseListener.class); + } + + /** + * Adds the specified listener to this component. This is harmless if the + * listener is null, but if the listener has already been registered, it + * will now be registered twice. + * + * @param listener the new listener to add + * @see MouseEvent + * @see #removeMouseMotionListener(MouseMotionListener) + * @see #getMouseMotionListeners() + * @since 1.1 + */ + public synchronized void addMouseMotionListener(MouseMotionListener listener) + { + mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, listener); + if (mouseMotionListener != null) + enableEvents(AWTEvent.MOUSE_EVENT_MASK); + } + + /** + * Removes the specified listener from the component. This is harmless if + * the listener was not previously registered. + * + * @param listener the listener to remove + * @see MouseEvent + * @see #addMouseMotionListener(MouseMotionListener) + * @see #getMouseMotionListeners() + * @since 1.1 + */ + public synchronized void removeMouseMotionListener(MouseMotionListener listener) + { + mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, listener); + } + + /** + * Returns an array of all specified listeners registered on this component. + * + * @return an array of listeners + * @see #addMouseMotionListener(MouseMotionListener) + * @see #removeMouseMotionListener(MouseMotionListener) + * @since 1.4 + */ + public synchronized MouseMotionListener[] getMouseMotionListeners() + { + return (MouseMotionListener[]) + AWTEventMulticaster.getListeners(mouseMotionListener, + MouseMotionListener.class); + } + + /** + * Adds the specified listener to this component. This is harmless if the + * listener is null, but if the listener has already been registered, it + * will now be registered twice. + * + * @param listener the new listener to add + * @see MouseEvent + * @see MouseWheelEvent + * @see #removeMouseWheelListener(MouseWheelListener) + * @see #getMouseWheelListeners() + * @since 1.4 + */ + public synchronized void addMouseWheelListener(MouseWheelListener listener) + { + mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener, listener); + if (mouseWheelListener != null) + enableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK); + } + + /** + * Removes the specified listener from the component. This is harmless if + * the listener was not previously registered. + * + * @param listener the listener to remove + * @see MouseEvent + * @see MouseWheelEvent + * @see #addMouseWheelListener(MouseWheelListener) + * @see #getMouseWheelListeners() + * @since 1.4 + */ + public synchronized void removeMouseWheelListener(MouseWheelListener listener) + { + mouseWheelListener = AWTEventMulticaster.remove(mouseWheelListener, listener); + } + + /** + * Returns an array of all specified listeners registered on this component. + * + * @return an array of listeners + * @see #addMouseWheelListener(MouseWheelListener) + * @see #removeMouseWheelListener(MouseWheelListener) + * @since 1.4 + */ + public synchronized MouseWheelListener[] getMouseWheelListeners() + { + return (MouseWheelListener[]) + AWTEventMulticaster.getListeners(mouseWheelListener, + MouseWheelListener.class); + } + + /** + * Adds the specified listener to this component. This is harmless if the + * listener is null, but if the listener has already been registered, it + * will now be registered twice. + * + * @param listener the new listener to add + * @see InputMethodEvent + * @see #removeInputMethodListener(InputMethodListener) + * @see #getInputMethodListeners() + * @see #getInputMethodRequests() + * @since 1.2 + */ + public synchronized void addInputMethodListener(InputMethodListener listener) + { + inputMethodListener = AWTEventMulticaster.add(inputMethodListener, listener); + if (inputMethodListener != null) + enableEvents(AWTEvent.INPUT_METHOD_EVENT_MASK); + } + + /** + * Removes the specified listener from the component. This is harmless if + * the listener was not previously registered. + * + * @param listener the listener to remove + * @see InputMethodEvent + * @see #addInputMethodListener(InputMethodListener) + * @see #getInputMethodRequests() + * @since 1.2 + */ + public synchronized void removeInputMethodListener(InputMethodListener listener) + { + inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, listener); + } + + /** + * Returns an array of all specified listeners registered on this component. + * + * @return an array of listeners + * @see #addInputMethodListener(InputMethodListener) + * @see #removeInputMethodListener(InputMethodListener) + * @since 1.4 + */ + public synchronized InputMethodListener[] getInputMethodListeners() + { + return (InputMethodListener[]) + AWTEventMulticaster.getListeners(inputMethodListener, + InputMethodListener.class); + } + + /** + * Returns all registered EventListers of the given listenerType. + * + * @param listenerType the class of listeners to filter + * @return an array of registered listeners + * @see #getComponentListeners() + * @see #getFocusListeners() + * @see #getHierarchyListeners() + * @see #getHierarchyBoundsListeners() + * @see #getKeyListeners() + * @see #getMouseListeners() + * @see #getMouseMotionListeners() + * @see #getMouseWheelListeners() + * @see #getInputMethodListeners() + * @see #getPropertyChangeListeners() + * @since 1.3 + */ + public EventListener[] getListeners(Class listenerType) + { + if (listenerType == ComponentListener.class) + return getComponentListeners(); + if (listenerType == FocusListener.class) + return getFocusListeners(); + if (listenerType == HierarchyListener.class) + return getHierarchyListeners(); + if (listenerType == HierarchyBoundsListener.class) + return getHierarchyBoundsListeners(); + if (listenerType == KeyListener.class) + return getKeyListeners(); + if (listenerType == MouseListener.class) + return getMouseListeners(); + if (listenerType == MouseMotionListener.class) + return getMouseMotionListeners(); + if (listenerType == MouseWheelListener.class) + return getMouseWheelListeners(); + if (listenerType == InputMethodListener.class) + return getInputMethodListeners(); + if (listenerType == PropertyChangeListener.class) + return getPropertyChangeListeners(); + return (EventListener[]) Array.newInstance(listenerType, 0); + } + + /** + * Returns the input method request handler, for subclasses which support + * on-the-spot text input. By default, input methods are handled by AWT, + * and this returns null. + * + * @return the input method handler, null by default + * @since 1.2 + */ + public InputMethodRequests getInputMethodRequests() + { + return null; + } + + /** + * Gets the input context of this component, which is inherited from the + * parent unless this is overridden. + * + * @return the text input context + * @since 1.2 + */ + public InputContext getInputContext() + { + return parent == null ? null : parent.getInputContext(); + } + + /** + * Enables the specified events. The events to enable are specified + * by OR-ing together the desired masks from <code>AWTEvent</code>. + * + * <p>Events are enabled by default when a listener is attached to the + * component for that event type. This method can be used by subclasses + * to ensure the delivery of a specified event regardless of whether + * or not a listener is attached. + * + * @param eventsToEnable the desired events to enable + * @see #processEvent(AWTEvent) + * @see #disableEvents(long) + * @see AWTEvent + * @since 1.1 + */ + protected final void enableEvents(long eventsToEnable) + { + eventMask |= eventsToEnable; + // TODO: Unlike Sun's implementation, I think we should try and + // enable/disable events at the peer (gtk/X) level. This will avoid + // clogging the event pipeline with useless mousemove events that + // we arn't interested in, etc. This will involve extending the peer + // interface, but thats okay because the peer interfaces have been + // deprecated for a long time, and no longer feature in the + // API specification at all. + if (isLightweight() && parent != null) + parent.enableEvents(eventsToEnable); + else if (peer != null) + peer.setEventMask(eventMask); + } + + /** + * Disables the specified events. The events to disable are specified + * by OR-ing together the desired masks from <code>AWTEvent</code>. + * + * @param eventsToDisable the desired events to disable + * @see #enableEvents(long) + * @since 1.1 + */ + protected final void disableEvents(long eventsToDisable) + { + eventMask &= ~eventsToDisable; + // forward new event mask to peer? + } + + /** + * This is called by the EventQueue if two events with the same event id + * and owner component are queued. Returns a new combined event, or null if + * no combining is done. The coelesced events are currently mouse moves + * (intermediate ones are discarded) and paint events (a merged paint is + * created in place of the two events). + * + * @param existingEvent the event on the queue + * @param newEvent the new event that might be entered on the queue + * @return null if both events are kept, or the replacement coelesced event + */ + protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent) + { + switch (existingEvent.id) + { + case MouseEvent.MOUSE_MOVED: + case MouseEvent.MOUSE_DRAGGED: + // Just drop the old (intermediate) event and return the new one. + return newEvent; + case PaintEvent.PAINT: + case PaintEvent.UPDATE: + return coalescePaintEvents((PaintEvent) existingEvent, + (PaintEvent) newEvent); + default: + return null; + } + } + + /** + * Processes the specified event. In this class, this method simply + * calls one of the more specific event handlers. + * + * @param e the event to process + * @throws NullPointerException if e is null + * @see #processComponentEvent(ComponentEvent) + * @see #processFocusEvent(FocusEvent) + * @see #processKeyEvent(KeyEvent) + * @see #processMouseEvent(MouseEvent) + * @see #processMouseMotionEvent(MouseEvent) + * @see #processInputMethodEvent(InputMethodEvent) + * @see #processHierarchyEvent(HierarchyEvent) + * @see #processMouseWheelEvent(MouseWheelEvent) + * @since 1.1 + */ + protected void processEvent(AWTEvent e) + { + /* Note: the order of these if statements are + important. Subclasses must be checked first. Eg. MouseEvent + must be checked before ComponentEvent, since a MouseEvent + object is also an instance of a ComponentEvent. */ + + if (e instanceof FocusEvent) + processFocusEvent((FocusEvent) e); + else if (e instanceof MouseWheelEvent) + processMouseWheelEvent((MouseWheelEvent) e); + else if (e instanceof MouseEvent) + { + if (e.id == MouseEvent.MOUSE_MOVED + || e.id == MouseEvent.MOUSE_DRAGGED) + processMouseMotionEvent((MouseEvent) e); + else + processMouseEvent((MouseEvent) e); + } + else if (e instanceof KeyEvent) + processKeyEvent((KeyEvent) e); + else if (e instanceof InputMethodEvent) + processInputMethodEvent((InputMethodEvent) e); + else if (e instanceof ComponentEvent) + processComponentEvent((ComponentEvent) e); + else if (e instanceof HierarchyEvent) + { + if (e.id == HierarchyEvent.HIERARCHY_CHANGED) + processHierarchyEvent((HierarchyEvent) e); + else + processHierarchyBoundsEvent((HierarchyEvent) e); + } + } + + /** + * Called when a component event is dispatched and component events are + * enabled. This method passes the event along to any listeners + * that are attached. + * + * @param e the <code>ComponentEvent</code> to process + * @throws NullPointerException if e is null + * @see ComponentListener + * @see #addComponentListener(ComponentListener) + * @see #enableEvents(long) + * @since 1.1 + */ + protected void processComponentEvent(ComponentEvent e) + { + if (componentListener == null) + return; + switch (e.id) + { + case ComponentEvent.COMPONENT_HIDDEN: + componentListener.componentHidden(e); + break; + case ComponentEvent.COMPONENT_MOVED: + componentListener.componentMoved(e); + break; + case ComponentEvent.COMPONENT_RESIZED: + componentListener.componentResized(e); + break; + case ComponentEvent.COMPONENT_SHOWN: + componentListener.componentShown(e); + break; + } + } + + /** + * Called when a focus event is dispatched and component events are + * enabled. This method passes the event along to any listeners + * that are attached. + * + * @param e the <code>FocusEvent</code> to process + * @throws NullPointerException if e is null + * @see FocusListener + * @see #addFocusListener(FocusListener) + * @see #enableEvents(long) + * @since 1.1 + */ + protected void processFocusEvent(FocusEvent e) + { + if (focusListener == null) + return; + + switch (e.id) + { + case FocusEvent.FOCUS_GAINED: + focusListener.focusGained(e); + break; + case FocusEvent.FOCUS_LOST: + focusListener.focusLost(e); + break; + } + } + + /** + * Called when a key event is dispatched and component events are + * enabled. This method passes the event along to any listeners + * that are attached. + * + * @param e the <code>KeyEvent</code> to process + * @throws NullPointerException if e is null + * @see KeyListener + * @see #addKeyListener(KeyListener) + * @see #enableEvents(long) + * @since 1.1 + */ + protected void processKeyEvent(KeyEvent e) + { + if (keyListener == null) + return; + switch (e.id) + { + case KeyEvent.KEY_PRESSED: + keyListener.keyPressed(e); + break; + case KeyEvent.KEY_RELEASED: + keyListener.keyReleased(e); + break; + case KeyEvent.KEY_TYPED: + keyListener.keyTyped(e); + break; + } + } + + /** + * Called when a regular mouse event is dispatched and component events are + * enabled. This method passes the event along to any listeners + * that are attached. + * + * @param e the <code>MouseEvent</code> to process + * @throws NullPointerException if e is null + * @see MouseListener + * @see #addMouseListener(MouseListener) + * @see #enableEvents(long) + * @since 1.1 + */ + protected void processMouseEvent(MouseEvent e) + { + if (mouseListener == null) + return; + switch (e.id) + { + case MouseEvent.MOUSE_CLICKED: + mouseListener.mouseClicked(e); + break; + case MouseEvent.MOUSE_ENTERED: + mouseListener.mouseEntered(e); + break; + case MouseEvent.MOUSE_EXITED: + mouseListener.mouseExited(e); + break; + case MouseEvent.MOUSE_PRESSED: + mouseListener.mousePressed(e); + break; + case MouseEvent.MOUSE_RELEASED: + mouseListener.mouseReleased(e); + break; + } + e.consume(); + } + + /** + * Called when a mouse motion event is dispatched and component events are + * enabled. This method passes the event along to any listeners + * that are attached. + * + * @param e the <code>MouseMotionEvent</code> to process + * @throws NullPointerException if e is null + * @see MouseMotionListener + * @see #addMouseMotionListener(MouseMotionListener) + * @see #enableEvents(long) + * @since 1.1 + */ + protected void processMouseMotionEvent(MouseEvent e) + { + if (mouseMotionListener == null) + return; + switch (e.id) + { + case MouseEvent.MOUSE_DRAGGED: + mouseMotionListener.mouseDragged(e); + break; + case MouseEvent.MOUSE_MOVED: + mouseMotionListener.mouseMoved(e); + break; + } + e.consume(); + } + + /** + * Called when a mouse wheel event is dispatched and component events are + * enabled. This method passes the event along to any listeners that are + * attached. + * + * @param e the <code>MouseWheelEvent</code> to process + * @throws NullPointerException if e is null + * @see MouseWheelListener + * @see #addMouseWheelListener(MouseWheelListener) + * @see #enableEvents(long) + * @since 1.4 + */ + protected void processMouseWheelEvent(MouseWheelEvent e) + { + if (mouseWheelListener != null + && e.id == MouseEvent.MOUSE_WHEEL) + { + mouseWheelListener.mouseWheelMoved(e); + e.consume(); + } + } + + /** + * Called when an input method event is dispatched and component events are + * enabled. This method passes the event along to any listeners that are + * attached. + * + * @param e the <code>InputMethodEvent</code> to process + * @throws NullPointerException if e is null + * @see InputMethodListener + * @see #addInputMethodListener(InputMethodListener) + * @see #enableEvents(long) + * @since 1.2 + */ + protected void processInputMethodEvent(InputMethodEvent e) + { + if (inputMethodListener == null) + return; + switch (e.id) + { + case InputMethodEvent.CARET_POSITION_CHANGED: + inputMethodListener.caretPositionChanged(e); + break; + case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED: + inputMethodListener.inputMethodTextChanged(e); + break; + } + } + + /** + * Called when a hierarchy change event is dispatched and component events + * are enabled. This method passes the event along to any listeners that are + * attached. + * + * @param e the <code>HierarchyEvent</code> to process + * @throws NullPointerException if e is null + * @see HierarchyListener + * @see #addHierarchyListener(HierarchyListener) + * @see #enableEvents(long) + * @since 1.3 + */ + protected void processHierarchyEvent(HierarchyEvent e) + { + if (hierarchyListener == null) + return; + if (e.id == HierarchyEvent.HIERARCHY_CHANGED) + hierarchyListener.hierarchyChanged(e); + } + + /** + * Called when a hierarchy bounds event is dispatched and component events + * are enabled. This method passes the event along to any listeners that are + * attached. + * + * @param e the <code>HierarchyEvent</code> to process + * @throws NullPointerException if e is null + * @see HierarchyBoundsListener + * @see #addHierarchyBoundsListener(HierarchyBoundsListener) + * @see #enableEvents(long) + * @since 1.3 + */ + protected void processHierarchyBoundsEvent(HierarchyEvent e) + { + if (hierarchyBoundsListener == null) + return; + switch (e.id) + { + case HierarchyEvent.ANCESTOR_MOVED: + hierarchyBoundsListener.ancestorMoved(e); + break; + case HierarchyEvent.ANCESTOR_RESIZED: + hierarchyBoundsListener.ancestorResized(e); + break; + } + } + + /** + * AWT 1.0 event handler. + * + * This method calls one of the event-specific handler methods. For + * example for key events, either {@link #keyDown(Event,int)} + * or {@link #keyUp(Event,int)} is called. A derived + * component can override one of these event-specific methods if it + * only needs to handle certain event types. Otherwise it can + * override handleEvent itself and handle any event. + * + * @param evt the event to handle + * @return true if the event was handled, false otherwise + * @deprecated use {@link #processEvent(AWTEvent)} instead + */ + public boolean handleEvent (Event evt) + { + switch (evt.id) + { + // Handle key events. + case Event.KEY_ACTION: + case Event.KEY_PRESS: + return keyDown (evt, evt.key); + case Event.KEY_ACTION_RELEASE: + case Event.KEY_RELEASE: + return keyUp (evt, evt.key); + + // Handle mouse events. + case Event.MOUSE_DOWN: + return mouseDown (evt, evt.x, evt.y); + case Event.MOUSE_UP: + return mouseUp (evt, evt.x, evt.y); + case Event.MOUSE_MOVE: + return mouseMove (evt, evt.x, evt.y); + case Event.MOUSE_DRAG: + return mouseDrag (evt, evt.x, evt.y); + case Event.MOUSE_ENTER: + return mouseEnter (evt, evt.x, evt.y); + case Event.MOUSE_EXIT: + return mouseExit (evt, evt.x, evt.y); + + // Handle focus events. + case Event.GOT_FOCUS: + return gotFocus (evt, evt.arg); + case Event.LOST_FOCUS: + return lostFocus (evt, evt.arg); + + // Handle action event. + case Event.ACTION_EVENT: + return action (evt, evt.arg); + } + // Unknown event. + return false; + } + + /** + * AWT 1.0 MOUSE_DOWN event handler. This method is meant to be + * overridden by components providing their own MOUSE_DOWN handler. + * The default implementation simply returns false. + * + * @param evt the event to handle + * @param x the x coordinate, ignored + * @param y the y coordinate, ignored + * @return false + * @deprecated use {@link #processMouseEvent(MouseEvent)} instead + */ + public boolean mouseDown(Event evt, int x, int y) + { + return false; + } + + /** + * AWT 1.0 MOUSE_DRAG event handler. This method is meant to be + * overridden by components providing their own MOUSE_DRAG handler. + * The default implementation simply returns false. + * + * @param evt the event to handle + * @param x the x coordinate, ignored + * @param y the y coordinate, ignored + * @return false + * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead + */ + public boolean mouseDrag(Event evt, int x, int y) + { + return false; + } + + /** + * AWT 1.0 MOUSE_UP event handler. This method is meant to be + * overridden by components providing their own MOUSE_UP handler. + * The default implementation simply returns false. + * + * @param evt the event to handle + * @param x the x coordinate, ignored + * @param y the y coordinate, ignored + * @return false + * @deprecated use {@link #processMouseEvent(MouseEvent)} instead + */ + public boolean mouseUp(Event evt, int x, int y) + { + return false; + } + + /** + * AWT 1.0 MOUSE_MOVE event handler. This method is meant to be + * overridden by components providing their own MOUSE_MOVE handler. + * The default implementation simply returns false. + * + * @param evt the event to handle + * @param x the x coordinate, ignored + * @param y the y coordinate, ignored + * @return false + * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead + */ + public boolean mouseMove(Event evt, int x, int y) + { + return false; + } + + /** + * AWT 1.0 MOUSE_ENTER event handler. This method is meant to be + * overridden by components providing their own MOUSE_ENTER handler. + * The default implementation simply returns false. + * + * @param evt the event to handle + * @param x the x coordinate, ignored + * @param y the y coordinate, ignored + * @return false + * @deprecated use {@link #processMouseEvent(MouseEvent)} instead + */ + public boolean mouseEnter(Event evt, int x, int y) + { + return false; + } + + /** + * AWT 1.0 MOUSE_EXIT event handler. This method is meant to be + * overridden by components providing their own MOUSE_EXIT handler. + * The default implementation simply returns false. + * + * @param evt the event to handle + * @param x the x coordinate, ignored + * @param y the y coordinate, ignored + * @return false + * @deprecated use {@link #processMouseEvent(MouseEvent)} instead + */ + public boolean mouseExit(Event evt, int x, int y) + { + return false; + } + + /** + * AWT 1.0 KEY_PRESS and KEY_ACTION event handler. This method is + * meant to be overridden by components providing their own key + * press handler. The default implementation simply returns false. + * + * @param evt the event to handle + * @param key the key pressed, ignored + * @return false + * @deprecated use {@link #processKeyEvent(KeyEvent)} instead + */ + public boolean keyDown(Event evt, int key) + { + return false; + } + + /** + * AWT 1.0 KEY_RELEASE and KEY_ACTION_RELEASE event handler. This + * method is meant to be overridden by components providing their + * own key release handler. The default implementation simply + * returns false. + * + * @param evt the event to handle + * @param key the key pressed, ignored + * @return false + * @deprecated use {@link #processKeyEvent(KeyEvent)} instead + */ + public boolean keyUp(Event evt, int key) + { + return false; + } + + /** + * AWT 1.0 ACTION_EVENT event handler. This method is meant to be + * overridden by components providing their own action event + * handler. The default implementation simply returns false. + * + * @param evt the event to handle + * @param what the object acted on, ignored + * @return false + * @deprecated in classes which support actions, use + * <code>processActionEvent(ActionEvent)</code> instead + */ + public boolean action(Event evt, Object what) + { + return false; + } + + /** + * Called to inform this component it has been added to a container. + * A native peer - if any - is created at this time. This method is + * called automatically by the AWT system and should not be called by + * user level code. + * + * @see #isDisplayable() + * @see #removeNotify() + */ + public void addNotify() + { + if (peer == null) + peer = getToolkit().createComponent(this); + /* Now that all the children has gotten their peers, we should + have the event mask needed for this component and its + lightweight subcomponents. */ + peer.setEventMask(eventMask); + /* We do not invalidate here, but rather leave that job up to + the peer. For efficiency, the peer can choose not to + invalidate if it is happy with the current dimensions, + etc. */ + } + + /** + * Called to inform this component is has been removed from its + * container. Its native peer - if any - is destroyed at this time. + * This method is called automatically by the AWT system and should + * not be called by user level code. + * + * @see #isDisplayable() + * @see #addNotify() + */ + public void removeNotify() + { + // We null our peer field before disposing of it, such that if we're + // not the event dispatch thread and the dispatch thread is awoken by + // the dispose call, there will be no race checking the peer's null + // status. + + ComponentPeer tmp = peer; + peer = null; + if (tmp != null) + tmp.dispose(); + } + + /** + * AWT 1.0 GOT_FOCUS event handler. This method is meant to be + * overridden by components providing their own GOT_FOCUS handler. + * The default implementation simply returns false. + * + * @param evt the event to handle + * @param what the Object focused, ignored + * @return false + * @deprecated use {@link #processFocusEvent(FocusEvent)} instead + */ + public boolean gotFocus(Event evt, Object what) + { + return false; + } + + /** + * AWT 1.0 LOST_FOCUS event handler. This method is meant to be + * overridden by components providing their own LOST_FOCUS handler. + * The default implementation simply returns false. + * + * @param evt the event to handle + * @param what the Object focused, ignored + * @return false + * @deprecated use {@link #processFocusEvent(FocusEvent)} instead + */ + public boolean lostFocus(Event evt, Object what) + { + return false; + } + + /** + * Tests whether or not this component is in the group that can be + * traversed using the keyboard traversal mechanism (such as the TAB key). + * + * @return true if the component is traversed via the TAB key + * @see #setFocusable(boolean) + * @since 1.1 + * @deprecated use {@link #isFocusable()} instead + */ + public boolean isFocusTraversable() + { + return enabled && visible && (peer == null || isLightweight() || peer.isFocusTraversable()); + } + + /** + * Tests if this component can receive focus. + * + * @return true if this component can receive focus + * @since 1.4 + */ + public boolean isFocusable() + { + return focusable; + } + + /** + * Specify whether this component can receive focus. This method also + * sets the {@link #isFocusTraversableOverridden} field to 1, which + * appears to be the undocumented way {@link + * DefaultFocusTraversalPolicy#accept(Component)} determines whether to + * respect the {@link #isFocusable()} method of the component. + * + * @param focusable the new focusable status + * @since 1.4 + */ + public void setFocusable(boolean focusable) + { + firePropertyChange("focusable", this.focusable, focusable); + this.focusable = focusable; + this.isFocusTraversableOverridden = 1; + } + + /** + * Sets the focus traversal keys for one of the three focus + * traversal directions supported by Components: + * {@link KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS}, + * {@link KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS}, or + * {@link KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS}. Normally, the + * default values should match the operating system's native + * choices. To disable a given traversal, use + * <code>Collections.EMPTY_SET</code>. The event dispatcher will + * consume PRESSED, RELEASED, and TYPED events for the specified + * key, although focus can only transfer on PRESSED or RELEASED. + * + * <p>The defaults are: + * <table> + * <th><td>Identifier</td><td>Meaning</td><td>Default</td></th> + * <tr><td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td> + * <td>Normal forward traversal</td> + * <td>TAB on KEY_PRESSED, Ctrl-TAB on KEY_PRESSED</td></tr> + * <tr><td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td> + * <td>Normal backward traversal</td> + * <td>Shift-TAB on KEY_PRESSED, Ctrl-Shift-TAB on KEY_PRESSED</td></tr> + * <tr><td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td> + * <td>Go up a traversal cycle</td><td>None</td></tr> + * </table> + * + * If keystrokes is null, this component's focus traversal key set + * is inherited from one of its ancestors. If none of its ancestors + * has its own set of focus traversal keys, the focus traversal keys + * are set to the defaults retrieved from the current + * KeyboardFocusManager. If not null, the set must contain only + * AWTKeyStrokes that are not already focus keys and are not + * KEY_TYPED events. + * + * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, or + * UP_CYCLE_TRAVERSAL_KEYS + * @param keystrokes a set of keys, or null + * @throws IllegalArgumentException if id or keystrokes is invalid + * @see #getFocusTraversalKeys(int) + * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS + * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS + * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS + * @since 1.4 + */ + public void setFocusTraversalKeys(int id, Set keystrokes) + { + if (keystrokes == null) + { + Container parent = getParent (); + + while (parent != null) + { + if (parent.areFocusTraversalKeysSet (id)) + { + keystrokes = parent.getFocusTraversalKeys (id); + break; + } + parent = parent.getParent (); + } + + if (keystrokes == null) + keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager (). + getDefaultFocusTraversalKeys (id); + } + + Set sa; + Set sb; + String name; + switch (id) + { + case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS: + sa = getFocusTraversalKeys + (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); + sb = getFocusTraversalKeys + (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); + name = "forwardFocusTraversalKeys"; + break; + case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS: + sa = getFocusTraversalKeys + (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); + sb = getFocusTraversalKeys + (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); + name = "backwardFocusTraversalKeys"; + break; + case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS: + sa = getFocusTraversalKeys + (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); + sb = getFocusTraversalKeys + (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); + name = "upCycleFocusTraversalKeys"; + break; + default: + throw new IllegalArgumentException (); + } + + int i = keystrokes.size (); + Iterator iter = keystrokes.iterator (); + + while (--i >= 0) + { + Object o = iter.next (); + if (!(o instanceof AWTKeyStroke) + || sa.contains (o) || sb.contains (o) + || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED) + throw new IllegalArgumentException (); + } + + if (focusTraversalKeys == null) + focusTraversalKeys = new Set[3]; + + keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes)); + firePropertyChange (name, focusTraversalKeys[id], keystrokes); + + focusTraversalKeys[id] = keystrokes; + } + + /** + * Returns the set of keys for a given focus traversal action, as + * defined in <code>setFocusTraversalKeys</code>. If not set, this + * is inherited from the parent component, which may have gotten it + * from the KeyboardFocusManager. + * + * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, + * or UP_CYCLE_TRAVERSAL_KEYS + * + * @return set of traversal keys + * + * @throws IllegalArgumentException if id is invalid + * + * @see #setFocusTraversalKeys (int, Set) + * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS + * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS + * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS + * + * @since 1.4 + */ + public Set getFocusTraversalKeys (int id) + { + if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS) + throw new IllegalArgumentException(); + + Set s = null; + + if (focusTraversalKeys != null) + s = focusTraversalKeys[id]; + + if (s == null && parent != null) + s = parent.getFocusTraversalKeys (id); + + return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager() + .getDefaultFocusTraversalKeys(id)) : s; + } + + /** + * Tests whether the focus traversal keys for a given action are explicitly + * set or inherited. + * + * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, + * or UP_CYCLE_TRAVERSAL_KEYS + * @return true if that set is explicitly specified + * @throws IllegalArgumentException if id is invalid + * @see #getFocusTraversalKeys (int) + * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS + * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS + * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS + * @since 1.4 + */ + public boolean areFocusTraversalKeysSet (int id) + { + if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS) + throw new IllegalArgumentException (); + + return focusTraversalKeys != null && focusTraversalKeys[id] != null; + } + + /** + * Enable or disable focus traversal keys on this Component. If + * they are, then the keyboard focus manager consumes and acts on + * key press and release events that trigger focus traversal, and + * discards the corresponding key typed events. If focus traversal + * keys are disabled, then all key events that would otherwise + * trigger focus traversal are sent to this Component. + * + * @param focusTraversalKeysEnabled the new value of the flag + * @see #getFocusTraversalKeysEnabled () + * @see #setFocusTraversalKeys (int, Set) + * @see #getFocusTraversalKeys (int) + * @since 1.4 + */ + public void setFocusTraversalKeysEnabled (boolean focusTraversalKeysEnabled) + { + firePropertyChange ("focusTraversalKeysEnabled", + this.focusTraversalKeysEnabled, + focusTraversalKeysEnabled); + this.focusTraversalKeysEnabled = focusTraversalKeysEnabled; + } + + /** + * Check whether or not focus traversal keys are enabled on this + * Component. If they are, then the keyboard focus manager consumes + * and acts on key press and release events that trigger focus + * traversal, and discards the corresponding key typed events. If + * focus traversal keys are disabled, then all key events that would + * otherwise trigger focus traversal are sent to this Component. + * + * @return true if focus traversal keys are enabled + * @see #setFocusTraversalKeysEnabled (boolean) + * @see #setFocusTraversalKeys (int, Set) + * @see #getFocusTraversalKeys (int) + * @since 1.4 + */ + public boolean getFocusTraversalKeysEnabled () + { + return focusTraversalKeysEnabled; + } + + /** + * Request that this Component be given the keyboard input focus and + * that its top-level ancestor become the focused Window. + * + * For the request to be granted, the Component must be focusable, + * displayable and showing and the top-level Window to which it + * belongs must be focusable. If the request is initially denied on + * the basis that the top-level Window is not focusable, the request + * will be remembered and granted when the Window does become + * focused. + * + * Never assume that this Component is the focus owner until it + * receives a FOCUS_GAINED event. + * + * The behaviour of this method is platform-dependent. + * {@link #requestFocusInWindow()} should be used instead. + * + * @see #requestFocusInWindow () + * @see FocusEvent + * @see #addFocusListener (FocusListener) + * @see #isFocusable () + * @see #isDisplayable () + * @see KeyboardFocusManager#clearGlobalFocusOwner () + */ + public void requestFocus () + { + if (isDisplayable () + && isShowing () + && isFocusable ()) + { + synchronized (getTreeLock ()) + { + // Find this Component's top-level ancestor. + Container parent = getParent (); + + while (parent != null + && !(parent instanceof Window)) + parent = parent.getParent (); + + Window toplevel = (Window) parent; + if (toplevel.isFocusableWindow ()) + { + if (peer != null && !isLightweight()) + // This call will cause a FOCUS_GAINED event to be + // posted to the system event queue if the native + // windowing system grants the focus request. + peer.requestFocus (); + else + { + // Either our peer hasn't been created yet or we're a + // lightweight component. In either case we want to + // post a FOCUS_GAINED event. + EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue (); + synchronized (eq) + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + Component currentFocusOwner = manager.getGlobalPermanentFocusOwner (); + if (currentFocusOwner != null) + { + eq.postEvent (new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, + false, this)); + eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, false, + currentFocusOwner)); + } + else + eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, false)); + } + } + } + else + pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED); + } + } + } + + /** + * Request that this Component be given the keyboard input focus and + * that its top-level ancestor become the focused Window. + * + * For the request to be granted, the Component must be focusable, + * displayable and showing and the top-level Window to which it + * belongs must be focusable. If the request is initially denied on + * the basis that the top-level Window is not focusable, the request + * will be remembered and granted when the Window does become + * focused. + * + * Never assume that this Component is the focus owner until it + * receives a FOCUS_GAINED event. + * + * The behaviour of this method is platform-dependent. + * {@link #requestFocusInWindow()} should be used instead. + * + * If the return value is false, the request is guaranteed to fail. + * If the return value is true, the request will succeed unless it + * is vetoed or something in the native windowing system intervenes, + * preventing this Component's top-level ancestor from becoming + * focused. This method is meant to be called by derived + * lightweight Components that want to avoid unnecessary repainting + * when they know a given focus transfer need only be temporary. + * + * @param temporary true if the focus request is temporary + * @return true if the request has a chance of success + * @see #requestFocusInWindow () + * @see FocusEvent + * @see #addFocusListener (FocusListener) + * @see #isFocusable () + * @see #isDisplayable () + * @see KeyboardFocusManager#clearGlobalFocusOwner () + * @since 1.4 + */ + protected boolean requestFocus (boolean temporary) + { + if (isDisplayable () + && isShowing () + && isFocusable ()) + { + synchronized (getTreeLock ()) + { + // Find this Component's top-level ancestor. + Container parent = getParent (); + + while (parent != null + && !(parent instanceof Window)) + parent = parent.getParent (); + + Window toplevel = (Window) parent; + if (toplevel.isFocusableWindow ()) + { + if (peer != null && !isLightweight()) + // This call will cause a FOCUS_GAINED event to be + // posted to the system event queue if the native + // windowing system grants the focus request. + peer.requestFocus (); + else + { + // Either our peer hasn't been created yet or we're a + // lightweight component. In either case we want to + // post a FOCUS_GAINED event. + EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue (); + synchronized (eq) + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + Component currentFocusOwner = manager.getGlobalPermanentFocusOwner (); + if (currentFocusOwner != null) + { + eq.postEvent (new FocusEvent(currentFocusOwner, + FocusEvent.FOCUS_LOST, + temporary, this)); + eq.postEvent (new FocusEvent(this, + FocusEvent.FOCUS_GAINED, + temporary, + currentFocusOwner)); + } + else + eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary)); + } + } + } + else + // FIXME: need to add a focus listener to our top-level + // ancestor, so that we can post this event when it becomes + // the focused window. + pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary); + } + } + // Always return true. + return true; + } + + /** + * Request that this component be given the keyboard input focus, if + * its top-level ancestor is the currently focused Window. A + * <code>FOCUS_GAINED</code> event will be fired if and only if this + * request is successful. To be successful, the component must be + * displayable, showing, and focusable, and its ancestor top-level + * Window must be focused. + * + * If the return value is false, the request is guaranteed to fail. + * If the return value is true, the request will succeed unless it + * is vetoed or something in the native windowing system intervenes, + * preventing this Component's top-level ancestor from becoming + * focused. + * + * @return true if the request has a chance of success + * @see #requestFocus () + * @see FocusEvent + * @see #addFocusListener (FocusListener) + * @see #isFocusable () + * @see #isDisplayable () + * @see KeyboardFocusManager#clearGlobalFocusOwner () + * @since 1.4 + */ + public boolean requestFocusInWindow () + { + return requestFocusInWindow (false); + } + + /** + * Request that this component be given the keyboard input focus, if + * its top-level ancestor is the currently focused Window. A + * <code>FOCUS_GAINED</code> event will be fired if and only if this + * request is successful. To be successful, the component must be + * displayable, showing, and focusable, and its ancestor top-level + * Window must be focused. + * + * If the return value is false, the request is guaranteed to fail. + * If the return value is true, the request will succeed unless it + * is vetoed or something in the native windowing system intervenes, + * preventing this Component's top-level ancestor from becoming + * focused. This method is meant to be called by derived + * lightweight Components that want to avoid unnecessary repainting + * when they know a given focus transfer need only be temporary. + * + * @param temporary true if the focus request is temporary + * @return true if the request has a chance of success + * @see #requestFocus () + * @see FocusEvent + * @see #addFocusListener (FocusListener) + * @see #isFocusable () + * @see #isDisplayable () + * @see KeyboardFocusManager#clearGlobalFocusOwner () + * @since 1.4 + */ + protected boolean requestFocusInWindow (boolean temporary) + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + + Window focusedWindow = manager.getFocusedWindow (); + + if (isDisplayable () + && isShowing () + && isFocusable ()) + { + if (focusedWindow != null) + { + synchronized (getTreeLock ()) + { + Container parent = getParent (); + + while (parent != null + && !(parent instanceof Window)) + parent = parent.getParent (); + + Window toplevel = (Window) parent; + + // Check if top-level ancestor is currently focused window. + if (focusedWindow == toplevel) + { + if (peer != null + && !isLightweight() + && !(this instanceof Window)) + // This call will cause a FOCUS_GAINED event to be + // posted to the system event queue if the native + // windowing system grants the focus request. + peer.requestFocus (); + else + { + // Either our peer hasn't been created yet or we're a + // lightweight component. In either case we want to + // post a FOCUS_GAINED event. + EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue (); + synchronized (eq) + { + Component currentFocusOwner = manager.getGlobalPermanentFocusOwner (); + if (currentFocusOwner != null) + { + eq.postEvent (new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, + temporary, this)); + eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary, + currentFocusOwner)); + } + else + eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary)); + } + } + } + else + return false; + } + } + + return true; + } + return false; + } + + /** + * Transfers focus to the next component in the focus traversal + * order, as though this were the current focus owner. + * + * @see #requestFocus() + * @since 1.1 + */ + public void transferFocus () + { + nextFocus (); + } + + /** + * Returns the root container that owns the focus cycle where this + * component resides. A focus cycle root is in two cycles, one as + * the ancestor, and one as the focusable element; this call always + * returns the ancestor. + * + * @return the ancestor container that owns the focus cycle + * @since 1.4 + */ + public Container getFocusCycleRootAncestor () + { + if (this instanceof Window + && ((Container) this).isFocusCycleRoot ()) + return (Container) this; + + Container parent = getParent (); + + while (parent != null + && !parent.isFocusCycleRoot ()) + parent = parent.getParent (); + + return parent; + } + + /** + * Tests if the container is the ancestor of the focus cycle that + * this component belongs to. + * + * @param c the container to test + * @return true if c is the focus cycle root + * @since 1.4 + */ + public boolean isFocusCycleRoot (Container c) + { + return c == getFocusCycleRootAncestor (); + } + + /** + * AWT 1.0 focus event processor. Transfers focus to the next + * component in the focus traversal order, as though this were the + * current focus owner. + * + * @deprecated use {@link #transferFocus ()} instead + */ + public void nextFocus () + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + + manager.focusNextComponent (this); + } + + /** + * Transfers focus to the previous component in the focus traversal + * order, as though this were the current focus owner. + * + * @see #requestFocus () + * @since 1.4 + */ + public void transferFocusBackward () + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + + manager.focusPreviousComponent (this); + } + + /** + * Transfers focus to the focus cycle root of this component. + * However, if this is a Window, the default focus owner in the + * window in the current focus cycle is focused instead. + * + * @see #requestFocus() + * @see #isFocusCycleRoot(Container) + * @since 1.4 + */ + public void transferFocusUpCycle () + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + + manager.upFocusCycle (this); + } + + /** + * Tests if this component is the focus owner. Use {@link + * #isFocusOwner ()} instead. + * + * @return true if this component owns focus + * @since 1.2 + */ + public boolean hasFocus () + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + + Component focusOwner = manager.getFocusOwner (); + + return this == focusOwner; + } + + /** + * Tests if this component is the focus owner. + * + * @return true if this component owns focus + * @since 1.4 + */ + public boolean isFocusOwner() + { + return hasFocus (); + } + + /** + * Adds the specified popup menu to this component. + * + * @param popup the popup menu to be added + * + * @see #remove(MenuComponent) + * + * @since 1.1 + */ + public synchronized void add(PopupMenu popup) + { + if (popups == null) + popups = new Vector(); + popups.add(popup); + + if (popup.parent != null) + popup.parent.remove(popup); + popup.parent = this; + if (peer != null) + popup.addNotify(); + } + + /** + * Removes the specified popup menu from this component. + * + * @param popup the popup menu to remove + * @see #add(PopupMenu) + * @since 1.1 + */ + public synchronized void remove(MenuComponent popup) + { + if (popups != null) + popups.remove(popup); + } + + /** + * Returns a debugging string representing this component. The string may + * be empty but not null. + * + * @return a string representing this component + */ + protected String paramString() + { + StringBuffer param = new StringBuffer(); + String name = getName(); + if (name != null) + param.append(name).append(","); + param.append(x).append(",").append(y).append(",").append(width) + .append("x").append(height); + if (! isValid()) + param.append(",invalid"); + if (! isVisible()) + param.append(",invisible"); + if (! isEnabled()) + param.append(",disabled"); + if (! isOpaque()) + param.append(",translucent"); + if (isDoubleBuffered()) + param.append(",doublebuffered"); + return param.toString(); + } + + /** + * Returns a string representation of this component. This is implemented + * as <code>getClass().getName() + '[' + paramString() + ']'</code>. + * + * @return a string representation of this component + */ + public String toString() + { + return getClass().getName() + '[' + paramString() + ']'; + } + + /** + * Prints a listing of this component to <code>System.out</code>. + * + * @see #list(PrintStream) + */ + public void list() + { + list(System.out, 0); + } + + /** + * Prints a listing of this component to the specified print stream. + * + * @param out the <code>PrintStream</code> to print to + */ + public void list(PrintStream out) + { + list(out, 0); + } + + /** + * Prints a listing of this component to the specified print stream, + * starting at the specified indentation point. + * + * @param out the <code>PrintStream</code> to print to + * @param indent the indentation point + */ + public void list(PrintStream out, int indent) + { + for (int i = 0; i < indent; ++i) + out.print(' '); + out.println(toString()); + } + + /** + * Prints a listing of this component to the specified print writer. + * + * @param out the <code>PrintWrinter</code> to print to + * @since 1.1 + */ + public void list(PrintWriter out) + { + list(out, 0); + } + + /** + * Prints a listing of this component to the specified print writer, + * starting at the specified indentation point. + * + * @param out the <code>PrintWriter</code> to print to + * @param indent the indentation point + * @since 1.1 + */ + public void list(PrintWriter out, int indent) + { + for (int i = 0; i < indent; ++i) + out.print(' '); + out.println(toString()); + } + + /** + * Adds the specified property listener to this component. This is harmless + * if the listener is null, but if the listener has already been registered, + * it will now be registered twice. The property listener ignores inherited + * properties. Recognized properties include:<br> + * <ul> + * <li>the font (<code>"font"</code>)</li> + * <li>the background color (<code>"background"</code>)</li> + * <li>the foreground color (<code>"foreground"</code>)</li> + * <li>the focusability (<code>"focusable"</code>)</li> + * <li>the focus key traversal enabled state + * (<code>"focusTraversalKeysEnabled"</code>)</li> + * <li>the set of forward traversal keys + * (<code>"forwardFocusTraversalKeys"</code>)</li> + * <li>the set of backward traversal keys + * (<code>"backwardFocusTraversalKeys"</code>)</li> + * <li>the set of up-cycle traversal keys + * (<code>"upCycleFocusTraversalKeys"</code>)</li> + * </ul> + * + * @param listener the new listener to add + * @see #removePropertyChangeListener(PropertyChangeListener) + * @see #getPropertyChangeListeners() + * @see #addPropertyChangeListener(String, PropertyChangeListener) + * @since 1.1 + */ + public void addPropertyChangeListener(PropertyChangeListener listener) + { + if (changeSupport == null) + changeSupport = new PropertyChangeSupport(this); + changeSupport.addPropertyChangeListener(listener); + } + + /** + * Removes the specified property listener from the component. This is + * harmless if the listener was not previously registered. + * + * @param listener the listener to remove + * @see #addPropertyChangeListener(PropertyChangeListener) + * @see #getPropertyChangeListeners() + * @see #removePropertyChangeListener(String, PropertyChangeListener) + * @since 1.1 + */ + public void removePropertyChangeListener(PropertyChangeListener listener) + { + if (changeSupport != null) + changeSupport.removePropertyChangeListener(listener); + } + + /** + * Returns an array of all specified listeners registered on this component. + * + * @return an array of listeners + * @see #addPropertyChangeListener(PropertyChangeListener) + * @see #removePropertyChangeListener(PropertyChangeListener) + * @see #getPropertyChangeListeners(String) + * @since 1.4 + */ + public PropertyChangeListener[] getPropertyChangeListeners() + { + return changeSupport == null ? new PropertyChangeListener[0] + : changeSupport.getPropertyChangeListeners(); + } + + /** + * Adds the specified property listener to this component. This is harmless + * if the listener is null, but if the listener has already been registered, + * it will now be registered twice. The property listener ignores inherited + * properties. The listener is keyed to a single property. Recognized + * properties include:<br> + * <ul> + * <li>the font (<code>"font"</code>)</li> + * <li>the background color (<code>"background"</code>)</li> + * <li>the foreground color (<code>"foreground"</code>)</li> + * <li>the focusability (<code>"focusable"</code>)</li> + * <li>the focus key traversal enabled state + * (<code>"focusTraversalKeysEnabled"</code>)</li> + * <li>the set of forward traversal keys + * (<code>"forwardFocusTraversalKeys"</code>)</li> +p * <li>the set of backward traversal keys + * (<code>"backwardFocusTraversalKeys"</code>)</li> + * <li>the set of up-cycle traversal keys + * (<code>"upCycleFocusTraversalKeys"</code>)</li> + * </ul> + * + * @param propertyName the property name to filter on + * @param listener the new listener to add + * @see #removePropertyChangeListener(String, PropertyChangeListener) + * @see #getPropertyChangeListeners(String) + * @see #addPropertyChangeListener(PropertyChangeListener) + * @since 1.1 + */ + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) + { + if (changeSupport == null) + changeSupport = new PropertyChangeSupport(this); + changeSupport.addPropertyChangeListener(propertyName, listener); + } + + /** + * Removes the specified property listener on a particular property from + * the component. This is harmless if the listener was not previously + * registered. + * + * @param propertyName the property name to filter on + * @param listener the listener to remove + * @see #addPropertyChangeListener(String, PropertyChangeListener) + * @see #getPropertyChangeListeners(String) + * @see #removePropertyChangeListener(PropertyChangeListener) + * @since 1.1 + */ + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) + { + if (changeSupport != null) + changeSupport.removePropertyChangeListener(propertyName, listener); + } + + /** + * Returns an array of all specified listeners on the named property that + * are registered on this component. + * + * @return an array of listeners + * @see #addPropertyChangeListener(String, PropertyChangeListener) + * @see #removePropertyChangeListener(String, PropertyChangeListener) + * @see #getPropertyChangeListeners() + * @since 1.4 + */ + public PropertyChangeListener[] getPropertyChangeListeners(String property) + { + return changeSupport == null ? new PropertyChangeListener[0] + : changeSupport.getPropertyChangeListeners(property); + } + + /** + * Report a change in a bound property to any registered property listeners. + * + * @param propertyName the property that changed + * @param oldValue the old property value + * @param newValue the new property value + */ + protected void firePropertyChange(String propertyName, Object oldValue, + Object newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * Report a change in a bound property to any registered property listeners. + * + * @param propertyName the property that changed + * @param oldValue the old property value + * @param newValue the new property value + */ + protected void firePropertyChange(String propertyName, boolean oldValue, + boolean newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * Report a change in a bound property to any registered property listeners. + * + * @param propertyName the property that changed + * @param oldValue the old property value + * @param newValue the new property value + */ + protected void firePropertyChange(String propertyName, int oldValue, + int newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * Sets the text layout orientation of this component. New components default + * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects only + * the current component, while + * {@link #applyComponentOrientation(ComponentOrientation)} affects the + * entire hierarchy. + * + * @param o the new orientation + * @throws NullPointerException if o is null + * @see #getComponentOrientation() + */ + public void setComponentOrientation(ComponentOrientation o) + { + if (o == null) + throw new NullPointerException(); + ComponentOrientation oldOrientation = orientation; + orientation = o; + firePropertyChange("componentOrientation", oldOrientation, o); + } + + /** + * Determines the text layout orientation used by this component. + * + * @return the component orientation + * @see #setComponentOrientation(ComponentOrientation) + */ + public ComponentOrientation getComponentOrientation() + { + return orientation; + } + + /** + * Sets the text layout orientation of this component. New components default + * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects the + * entire hierarchy, while + * {@link #setComponentOrientation(ComponentOrientation)} affects only the + * current component. + * + * @param o the new orientation + * @throws NullPointerException if o is null + * @see #getComponentOrientation() + * @since 1.4 + */ + public void applyComponentOrientation(ComponentOrientation o) + { + setComponentOrientation(o); + } + + /** + * Returns the accessibility framework context of this class. Component is + * not accessible, so the default implementation returns null. Subclasses + * must override this behavior, and return an appropriate subclass of + * {@link AccessibleAWTComponent}. + * + * @return the accessibility context + */ + public AccessibleContext getAccessibleContext() + { + return null; + } + + + // Helper methods; some are package visible for use by subclasses. + + /** + * Subclasses should override this to return unique component names like + * "menuitem0". + * + * @return the generated name for this component + */ + String generateName() + { + // Component is abstract. + return null; + } + + /** + * Sets the peer for this component. + * + * @param peer the new peer + */ + final void setPeer(ComponentPeer peer) + { + this.peer = peer; + } + + /** + * Implementation method that allows classes such as Canvas and Window to + * override the graphics configuration without violating the published API. + * + * @return the graphics configuration + */ + GraphicsConfiguration getGraphicsConfigurationImpl() + { + if (peer != null) + { + GraphicsConfiguration config = peer.getGraphicsConfiguration(); + if (config != null) + return config; + } + + if (parent != null) + return parent.getGraphicsConfiguration(); + + return null; + } + + /** + * Translate an AWT 1.1 event ({@link AWTEvent}) into an AWT 1.0 + * event ({@link Event}). + * + * @param e an AWT 1.1 event to translate + * + * @return an AWT 1.0 event representing e + */ + static Event translateEvent (AWTEvent e) + { + Component target = (Component) e.getSource (); + Event translated = null; + + if (e instanceof InputEvent) + { + InputEvent ie = (InputEvent) e; + long when = ie.getWhen (); + + int oldID = 0; + int id = e.getID (); + + int oldMods = 0; + int mods = ie.getModifiersEx (); + + if ((mods & InputEvent.BUTTON2_DOWN_MASK) != 0) + oldMods |= Event.META_MASK; + else if ((mods & InputEvent.BUTTON3_DOWN_MASK) != 0) + oldMods |= Event.ALT_MASK; + + if ((mods & InputEvent.SHIFT_DOWN_MASK) != 0) + oldMods |= Event.SHIFT_MASK; + + if ((mods & InputEvent.CTRL_DOWN_MASK) != 0) + oldMods |= Event.CTRL_MASK; + + if ((mods & InputEvent.META_DOWN_MASK) != 0) + oldMods |= Event.META_MASK; + + if ((mods & InputEvent.ALT_DOWN_MASK) != 0) + oldMods |= Event.ALT_MASK; + + if (e instanceof MouseEvent) + { + if (id == MouseEvent.MOUSE_PRESSED) + oldID = Event.MOUSE_DOWN; + else if (id == MouseEvent.MOUSE_RELEASED) + oldID = Event.MOUSE_UP; + else if (id == MouseEvent.MOUSE_MOVED) + oldID = Event.MOUSE_MOVE; + else if (id == MouseEvent.MOUSE_DRAGGED) + oldID = Event.MOUSE_DRAG; + else if (id == MouseEvent.MOUSE_ENTERED) + oldID = Event.MOUSE_ENTER; + else if (id == MouseEvent.MOUSE_EXITED) + oldID = Event.MOUSE_EXIT; + else + // No analogous AWT 1.0 mouse event. + return null; + + MouseEvent me = (MouseEvent) e; + + translated = new Event (target, when, oldID, + me.getX (), me.getY (), 0, oldMods); + } + else if (e instanceof KeyEvent) + { + if (id == KeyEvent.KEY_PRESSED) + oldID = Event.KEY_PRESS; + else if (e.getID () == KeyEvent.KEY_RELEASED) + oldID = Event.KEY_RELEASE; + else + // No analogous AWT 1.0 key event. + return null; + + int oldKey = 0; + int newKey = ((KeyEvent) e).getKeyCode (); + switch (newKey) + { + case KeyEvent.VK_BACK_SPACE: + oldKey = Event.BACK_SPACE; + break; + case KeyEvent.VK_CAPS_LOCK: + oldKey = Event.CAPS_LOCK; + break; + case KeyEvent.VK_DELETE: + oldKey = Event.DELETE; + break; + case KeyEvent.VK_DOWN: + case KeyEvent.VK_KP_DOWN: + oldKey = Event.DOWN; + break; + case KeyEvent.VK_END: + oldKey = Event.END; + break; + case KeyEvent.VK_ENTER: + oldKey = Event.ENTER; + break; + case KeyEvent.VK_ESCAPE: + oldKey = Event.ESCAPE; + break; + case KeyEvent.VK_F1: + oldKey = Event.F1; + break; + case KeyEvent.VK_F10: + oldKey = Event.F10; + break; + case KeyEvent.VK_F11: + oldKey = Event.F11; + break; + case KeyEvent.VK_F12: + oldKey = Event.F12; + break; + case KeyEvent.VK_F2: + oldKey = Event.F2; + break; + case KeyEvent.VK_F3: + oldKey = Event.F3; + break; + case KeyEvent.VK_F4: + oldKey = Event.F4; + break; + case KeyEvent.VK_F5: + oldKey = Event.F5; + break; + case KeyEvent.VK_F6: + oldKey = Event.F6; + break; + case KeyEvent.VK_F7: + oldKey = Event.F7; + break; + case KeyEvent.VK_F8: + oldKey = Event.F8; + break; + case KeyEvent.VK_F9: + oldKey = Event.F9; + break; + case KeyEvent.VK_HOME: + oldKey = Event.HOME; + break; + case KeyEvent.VK_INSERT: + oldKey = Event.INSERT; + break; + case KeyEvent.VK_LEFT: + case KeyEvent.VK_KP_LEFT: + oldKey = Event.LEFT; + break; + case KeyEvent.VK_NUM_LOCK: + oldKey = Event.NUM_LOCK; + break; + case KeyEvent.VK_PAUSE: + oldKey = Event.PAUSE; + break; + case KeyEvent.VK_PAGE_DOWN: + oldKey = Event.PGDN; + break; + case KeyEvent.VK_PAGE_UP: + oldKey = Event.PGUP; + break; + case KeyEvent.VK_PRINTSCREEN: + oldKey = Event.PRINT_SCREEN; + break; + case KeyEvent.VK_RIGHT: + case KeyEvent.VK_KP_RIGHT: + oldKey = Event.RIGHT; + break; + case KeyEvent.VK_SCROLL_LOCK: + oldKey = Event.SCROLL_LOCK; + break; + case KeyEvent.VK_TAB: + oldKey = Event.TAB; + break; + case KeyEvent.VK_UP: + case KeyEvent.VK_KP_UP: + oldKey = Event.UP; + break; + default: + oldKey = newKey; + } + + translated = new Event (target, when, oldID, + 0, 0, oldKey, oldMods); + } + } + else if (e instanceof ActionEvent) + translated = new Event (target, Event.ACTION_EVENT, + ((ActionEvent) e).getActionCommand ()); + + return translated; + } + + /** + * Implementation of dispatchEvent. Allows trusted package classes + * to dispatch additional events first. This implementation first + * translates <code>e</code> to an AWT 1.0 event and sends the + * result to {@link #postEvent}. If the AWT 1.0 event is not + * handled, and events of type <code>e</code> are enabled for this + * component, e is passed on to {@link #processEvent}. + * + * @param e the event to dispatch + */ + + void dispatchEventImpl (AWTEvent e) + { + Event oldEvent = translateEvent (e); + + if (oldEvent != null) + postEvent (oldEvent); + + if (eventTypeEnabled (e.id)) + { + // the trick we use to communicate between dispatch and redispatch + // is to have KeyboardFocusManager.redispatch synchronize on the + // object itself. we then do not redispatch to KeyboardFocusManager + // if we are already holding the lock. + if (! Thread.holdsLock(e)) + { + switch (e.id) + { + case WindowEvent.WINDOW_GAINED_FOCUS: + case WindowEvent.WINDOW_LOST_FOCUS: + case KeyEvent.KEY_PRESSED: + case KeyEvent.KEY_RELEASED: + case KeyEvent.KEY_TYPED: + case FocusEvent.FOCUS_GAINED: + case FocusEvent.FOCUS_LOST: + if (KeyboardFocusManager + .getCurrentKeyboardFocusManager() + .dispatchEvent(e)) + return; + case MouseEvent.MOUSE_PRESSED: + if (isLightweight()) + requestFocus(); + break; + } + } + processEvent (e); + } + } + + /** + * Tells whether or not an event type is enabled. + */ + boolean eventTypeEnabled (int type) + { + if (type > AWTEvent.RESERVED_ID_MAX) + return true; + + switch (type) + { + case ComponentEvent.COMPONENT_HIDDEN: + case ComponentEvent.COMPONENT_MOVED: + case ComponentEvent.COMPONENT_RESIZED: + case ComponentEvent.COMPONENT_SHOWN: + return (componentListener != null + || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0); + + case KeyEvent.KEY_PRESSED: + case KeyEvent.KEY_RELEASED: + case KeyEvent.KEY_TYPED: + return (keyListener != null + || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0); + + case MouseEvent.MOUSE_CLICKED: + case MouseEvent.MOUSE_ENTERED: + case MouseEvent.MOUSE_EXITED: + case MouseEvent.MOUSE_PRESSED: + case MouseEvent.MOUSE_RELEASED: + case MouseEvent.MOUSE_MOVED: + case MouseEvent.MOUSE_DRAGGED: + return (mouseListener != null + || mouseMotionListener != null + || (eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0); + + case FocusEvent.FOCUS_GAINED: + case FocusEvent.FOCUS_LOST: + return (focusListener != null + || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0); + + case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED: + case InputMethodEvent.CARET_POSITION_CHANGED: + return (inputMethodListener != null + || (eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0); + + case PaintEvent.PAINT: + case PaintEvent.UPDATE: + return (eventMask & AWTEvent.PAINT_EVENT_MASK) != 0; + + default: + return false; + } + } + + /** + * Coalesce paint events. Current heuristic is: Merge if the union of + * areas is less than twice that of the sum of the areas. The X server + * tend to create a lot of paint events that are adjacent but not + * overlapping. + * + * <pre> + * +------+ + * | +-----+ ...will be merged + * | | | + * | | | + * +------+ | + * +-----+ + * + * +---------------+--+ + * | | | ...will not be merged + * +---------------+ | + * | | + * | | + * | | + * | | + * | | + * +--+ + * </pre> + * + * @param queuedEvent the first paint event + * @param newEvent the second paint event + * @return the combined paint event, or null + */ + private PaintEvent coalescePaintEvents(PaintEvent queuedEvent, + PaintEvent newEvent) + { + Rectangle r1 = queuedEvent.getUpdateRect(); + Rectangle r2 = newEvent.getUpdateRect(); + Rectangle union = r1.union(r2); + + int r1a = r1.width * r1.height; + int r2a = r2.width * r2.height; + int ua = union.width * union.height; + + if (ua > (r1a+r2a)*2) + return null; + /* The 2 factor should maybe be reconsidered. Perhaps 3/2 + would be better? */ + + newEvent.setUpdateRect(union); + return newEvent; + } + + /** + * This method is used to implement transferFocus(). CHILD is the child + * making the request. This is overridden by Container; when called for an + * ordinary component there is no child and so we always return null. + * + * FIXME: is this still needed, in light of focus traversal policies? + * + * @param child the component making the request + * @return the next component to focus on + */ + Component findNextFocusComponent(Component child) + { + return null; + } + + /** + * Deserializes this component. This regenerates all serializable listeners + * which were registered originally. + * + * @param s the stream to read from + * @throws ClassNotFoundException if deserialization fails + * @throws IOException if the stream fails + */ + private void readObject(ObjectInputStream s) + throws ClassNotFoundException, IOException + { + s.defaultReadObject(); + String key = (String) s.readObject(); + while (key != null) + { + Object listener = s.readObject(); + if ("componentL".equals(key)) + addComponentListener((ComponentListener) listener); + else if ("focusL".equals(key)) + addFocusListener((FocusListener) listener); + else if ("keyL".equals(key)) + addKeyListener((KeyListener) listener); + else if ("mouseL".equals(key)) + addMouseListener((MouseListener) listener); + else if ("mouseMotionL".equals(key)) + addMouseMotionListener((MouseMotionListener) listener); + else if ("inputMethodL".equals(key)) + addInputMethodListener((InputMethodListener) listener); + else if ("hierarchyL".equals(key)) + addHierarchyListener((HierarchyListener) listener); + else if ("hierarchyBoundsL".equals(key)) + addHierarchyBoundsListener((HierarchyBoundsListener) listener); + else if ("mouseWheelL".equals(key)) + addMouseWheelListener((MouseWheelListener) listener); + key = (String) s.readObject(); + } + } + + /** + * Serializes this component. This ignores all listeners which do not + * implement Serializable, but includes those that do. + * + * @param s the stream to write to + * @throws IOException if the stream fails + */ + private void writeObject(ObjectOutputStream s) throws IOException + { + s.defaultWriteObject(); + AWTEventMulticaster.save(s, "componentL", componentListener); + AWTEventMulticaster.save(s, "focusL", focusListener); + AWTEventMulticaster.save(s, "keyL", keyListener); + AWTEventMulticaster.save(s, "mouseL", mouseListener); + AWTEventMulticaster.save(s, "mouseMotionL", mouseMotionListener); + AWTEventMulticaster.save(s, "inputMethodL", inputMethodListener); + AWTEventMulticaster.save(s, "hierarchyL", hierarchyListener); + AWTEventMulticaster.save(s, "hierarchyBoundsL", hierarchyBoundsListener); + AWTEventMulticaster.save(s, "mouseWheelL", mouseWheelListener); + s.writeObject(null); + } + + + // Nested classes. + + /** + * This class provides accessibility support for subclasses of container. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + * @status updated to 1.4 + */ + protected abstract class AccessibleAWTComponent extends AccessibleContext + implements Serializable, AccessibleComponent + { + /** + * Compatible with JDK 1.3+. + */ + private static final long serialVersionUID = 642321655757800191L; + + /** + * Converts show/hide events to PropertyChange events, and is registered + * as a component listener on this component. + * + * @serial the component handler + */ + protected ComponentListener accessibleAWTComponentHandler + = new AccessibleAWTComponentHandler(); + + /** + * Converts focus events to PropertyChange events, and is registered + * as a focus listener on this component. + * + * @serial the focus handler + */ + protected FocusListener accessibleAWTFocusHandler + = new AccessibleAWTFocusHandler(); + + /** + * The default constructor. + */ + protected AccessibleAWTComponent() + { + Component.this.addComponentListener(accessibleAWTComponentHandler); + Component.this.addFocusListener(accessibleAWTFocusHandler); + } + + /** + * Adds a global property change listener to the accessible component. + * + * @param l the listener to add + * @see #ACCESSIBLE_NAME_PROPERTY + * @see #ACCESSIBLE_DESCRIPTION_PROPERTY + * @see #ACCESSIBLE_STATE_PROPERTY + * @see #ACCESSIBLE_VALUE_PROPERTY + * @see #ACCESSIBLE_SELECTION_PROPERTY + * @see #ACCESSIBLE_TEXT_PROPERTY + * @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY + */ + public void addPropertyChangeListener(PropertyChangeListener l) + { + Component.this.addPropertyChangeListener(l); + super.addPropertyChangeListener(l); + } + + /** + * Removes a global property change listener from this accessible + * component. + * + * @param l the listener to remove + */ + public void removePropertyChangeListener(PropertyChangeListener l) + { + Component.this.removePropertyChangeListener(l); + super.removePropertyChangeListener(l); + } + + /** + * Returns the accessible name of this component. It is almost always + * wrong to return getName(), since it is not localized. In fact, for + * things like buttons, this should be the text of the button, not the + * name of the object. The tooltip text might also be appropriate. + * + * @return the name + * @see #setAccessibleName(String) + */ + public String getAccessibleName() + { + return accessibleName == null ? getName() : accessibleName; + } + + /** + * Returns a brief description of this accessible context. This should + * be localized. + * + * @return a description of this component + * @see #setAccessibleDescription(String) + */ + public String getAccessibleDescription() + { + return accessibleDescription; + } + + /** + * Returns the role of this component. + * + * @return the accessible role + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.AWT_COMPONENT; + } + + /** + * Returns a state set describing this component's state. + * + * @return a new state set + * @see AccessibleState + */ + public AccessibleStateSet getAccessibleStateSet() + { + AccessibleStateSet s = new AccessibleStateSet(); + if (Component.this.isEnabled()) + s.add(AccessibleState.ENABLED); + if (isFocusable()) + s.add(AccessibleState.FOCUSABLE); + if (isFocusOwner()) + s.add(AccessibleState.FOCUSED); + if (isOpaque()) + s.add(AccessibleState.OPAQUE); + if (Component.this.isShowing()) + s.add(AccessibleState.SHOWING); + if (Component.this.isVisible()) + s.add(AccessibleState.VISIBLE); + return s; + } + + /** + * Returns the parent of this component, if it is accessible. + * + * @return the accessible parent + */ + public Accessible getAccessibleParent() + { + if (accessibleParent == null) + { + Container parent = getParent(); + accessibleParent = parent instanceof Accessible + ? (Accessible) parent : null; + } + return accessibleParent; + } + + /** + * Returns the index of this component in its accessible parent. + * + * @return the index, or -1 if the parent is not accessible + * @see #getAccessibleParent() + */ + public int getAccessibleIndexInParent() + { + if (getAccessibleParent() == null) + return -1; + AccessibleContext context + = ((Component) accessibleParent).getAccessibleContext(); + if (context == null) + return -1; + for (int i = context.getAccessibleChildrenCount(); --i >= 0; ) + if (context.getAccessibleChild(i) == Component.this) + return i; + return -1; + } + + /** + * Returns the number of children of this component which implement + * Accessible. Subclasses must override this if they can have children. + * + * @return the number of accessible children, default 0 + */ + public int getAccessibleChildrenCount() + { + return 0; + } + + /** + * Returns the ith accessible child. Subclasses must override this if + * they can have children. + * + * @return the ith accessible child, or null + * @see #getAccessibleChildrenCount() + */ + public Accessible getAccessibleChild(int i) + { + return null; + } + + /** + * Returns the locale of this component. + * + * @return the locale + * @throws IllegalComponentStateException if the locale is unknown + */ + public Locale getLocale() + { + return Component.this.getLocale(); + } + + /** + * Returns this, since it is an accessible component. + * + * @return the accessible component + */ + public AccessibleComponent getAccessibleComponent() + { + return this; + } + + /** + * Gets the background color. + * + * @return the background color + * @see #setBackground(Color) + */ + public Color getBackground() + { + return Component.this.getBackground(); + } + + /** + * Sets the background color. + * + * @param c the background color + * @see #getBackground() + * @see #isOpaque() + */ + public void setBackground(Color c) + { + Component.this.setBackground(c); + } + + /** + * Gets the foreground color. + * + * @return the foreground color + * @see #setForeground(Color) + */ + public Color getForeground() + { + return Component.this.getForeground(); + } + + /** + * Sets the foreground color. + * + * @param c the foreground color + * @see #getForeground() + */ + public void setForeground(Color c) + { + Component.this.setForeground(c); + } + + /** + * Gets the cursor. + * + * @return the cursor + * @see #setCursor(Cursor) + */ + public Cursor getCursor() + { + return Component.this.getCursor(); + } + + /** + * Sets the cursor. + * + * @param cursor the cursor + * @see #getCursor() + */ + public void setCursor(Cursor cursor) + { + Component.this.setCursor(cursor); + } + + /** + * Gets the font. + * + * @return the font + * @see #setFont(Font) + */ + public Font getFont() + { + return Component.this.getFont(); + } + + /** + * Sets the font. + * + * @param f the font + * @see #getFont() + */ + public void setFont(Font f) + { + Component.this.setFont(f); + } + + /** + * Gets the font metrics for a font. + * + * @param f the font to look up + * @return its metrics + * @throws NullPointerException if f is null + * @see #getFont() + */ + public FontMetrics getFontMetrics(Font f) + { + return Component.this.getFontMetrics(f); + } + + /** + * Tests if the component is enabled. + * + * @return true if the component is enabled + * @see #setEnabled(boolean) + * @see #getAccessibleStateSet() + * @see AccessibleState#ENABLED + */ + public boolean isEnabled() + { + return Component.this.isEnabled(); + } + + /** + * Set whether the component is enabled. + * + * @param b the new enabled status + * @see #isEnabled() + */ + public void setEnabled(boolean b) + { + Component.this.setEnabled(b); + } + + /** + * Test whether the component is visible (not necesarily showing). + * + * @return true if it is visible + * @see #setVisible(boolean) + * @see #getAccessibleStateSet() + * @see AccessibleState#VISIBLE + */ + public boolean isVisible() + { + return Component.this.isVisible(); + } + + /** + * Sets the visibility of this component. + * + * @param b the desired visibility + * @see #isVisible() + */ + public void setVisible(boolean b) + { + Component.this.setVisible(b); + } + + /** + * Tests if the component is showing. + * + * @return true if this is showing + */ + public boolean isShowing() + { + return Component.this.isShowing(); + } + + /** + * Tests if the point is contained in this component. + * + * @param p the point to check + * @return true if it is contained + * @throws NullPointerException if p is null + */ + public boolean contains(Point p) + { + return Component.this.contains(p.x, p.y); + } + + /** + * Returns the location of this object on the screen, or null if it is + * not showing. + * + * @return the location relative to screen coordinates, if showing + * @see #getBounds() + * @see #getLocation() + */ + public Point getLocationOnScreen() + { + return Component.this.isShowing() ? Component.this.getLocationOnScreen() + : null; + } + + /** + * Returns the location of this object relative to its parent's coordinate + * system, or null if it is not showing. + * + * @return the location + * @see #getBounds() + * @see #getLocationOnScreen() + */ + public Point getLocation() + { + return Component.this.isShowing() ? Component.this.getLocation() : null; + } + + /** + * Sets the location of this relative to its parent's coordinate system. + * + * @param p the location + * @throws NullPointerException if p is null + * @see #getLocation() + */ + public void setLocation(Point p) + { + Component.this.setLocation(p.x, p.y); + } + + /** + * Gets the bounds of this component, or null if it is not on screen. + * + * @return the bounds + * @see #contains(Point) + * @see #setBounds(Rectangle) + */ + public Rectangle getBounds() + { + return Component.this.isShowing() ? Component.this.getBounds() : null; + } + + /** + * Sets the bounds of this component. + * + * @param r the bounds + * @throws NullPointerException if r is null + * @see #getBounds() + */ + public void setBounds(Rectangle r) + { + Component.this.setBounds(r.x, r.y, r.width, r.height); + } + + /** + * Gets the size of this component, or null if it is not showing. + * + * @return the size + * @see #setSize(Dimension) + */ + public Dimension getSize() + { + return Component.this.isShowing() ? Component.this.getSize() : null; + } + + /** + * Sets the size of this component. + * + * @param d the size + * @throws NullPointerException if d is null + * @see #getSize() + */ + public void setSize(Dimension d) + { + Component.this.setSize(d.width, d.height); + } + + /** + * Returns the Accessible child at a point relative to the coordinate + * system of this component, if one exists, or null. Since components + * have no children, subclasses must override this to get anything besides + * null. + * + * @param p the point to check + * @return the accessible child at that point + * @throws NullPointerException if p is null + */ + public Accessible getAccessibleAt(Point p) + { + return null; + } + + /** + * Tests whether this component can accept focus. + * + * @return true if this is focus traversable + * @see #getAccessibleStateSet () + * @see AccessibleState#FOCUSABLE + * @see AccessibleState#FOCUSED + */ + public boolean isFocusTraversable () + { + return Component.this.isFocusTraversable (); + } + + /** + * Requests focus for this component. + * + * @see #isFocusTraversable () + */ + public void requestFocus () + { + Component.this.requestFocus (); + } + + /** + * Adds a focus listener. + * + * @param l the listener to add + */ + public void addFocusListener(FocusListener l) + { + Component.this.addFocusListener(l); + } + + /** + * Removes a focus listener. + * + * @param l the listener to remove + */ + public void removeFocusListener(FocusListener l) + { + Component.this.removeFocusListener(l); + } + + /** + * Converts component changes into property changes. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + * @status updated to 1.4 + */ + protected class AccessibleAWTComponentHandler implements ComponentListener + { + /** + * Default constructor. + */ + protected AccessibleAWTComponentHandler() + { + } + + /** + * Convert a component hidden to a property change. + * + * @param e the event to convert + */ + public void componentHidden(ComponentEvent e) + { + AccessibleAWTComponent.this.firePropertyChange + (ACCESSIBLE_STATE_PROPERTY, AccessibleState.VISIBLE, null); + } + + /** + * Convert a component shown to a property change. + * + * @param e the event to convert + */ + public void componentShown(ComponentEvent e) + { + AccessibleAWTComponent.this.firePropertyChange + (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.VISIBLE); + } + + /** + * Moving a component does not affect properties. + * + * @param e ignored + */ + public void componentMoved(ComponentEvent e) + { + } + + /** + * Resizing a component does not affect properties. + * + * @param e ignored + */ + public void componentResized(ComponentEvent e) + { + } + } // class AccessibleAWTComponentHandler + + /** + * Converts focus changes into property changes. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + * @status updated to 1.4 + */ + protected class AccessibleAWTFocusHandler implements FocusListener + { + /** + * Default constructor. + */ + protected AccessibleAWTFocusHandler() + { + } + + /** + * Convert a focus gained to a property change. + * + * @param e the event to convert + */ + public void focusGained(FocusEvent e) + { + AccessibleAWTComponent.this.firePropertyChange + (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.FOCUSED); + } + + /** + * Convert a focus lost to a property change. + * + * @param e the event to convert + */ + public void focusLost(FocusEvent e) + { + AccessibleAWTComponent.this.firePropertyChange + (ACCESSIBLE_STATE_PROPERTY, AccessibleState.FOCUSED, null); + } + } // class AccessibleAWTComponentHandler + } // class AccessibleAWTComponent + + /** + * This class provides support for blitting offscreen surfaces to a + * component. + * + * @see BufferStrategy + * + * @since 1.4 + */ + protected class BltBufferStrategy extends BufferStrategy + { + /** + * The capabilities of the image buffer. + */ + protected BufferCapabilities caps; + + /** + * The back buffers used in this strategy. + */ + protected VolatileImage[] backBuffers; + + /** + * Whether or not the image buffer resources are allocated and + * ready to be drawn into. + */ + protected boolean validatedContents; + + /** + * The width of the back buffers. + */ + protected int width; + + /** + * The height of the back buffers. + */ + protected int height; + + /** + * The front buffer. + */ + private VolatileImage frontBuffer; + + /** + * Creates a blitting buffer strategy. + * + * @param numBuffers the number of buffers, including the front + * buffer + * @param caps the capabilities of this strategy + */ + protected BltBufferStrategy(int numBuffers, BufferCapabilities caps) + { + this.caps = caps; + createBackBuffers(numBuffers - 1); + width = getWidth(); + height = getHeight(); + } + + /** + * Initializes the backBuffers field with an array of numBuffers + * VolatileImages. + * + * @param numBuffers the number of backbuffers to create + */ + protected void createBackBuffers(int numBuffers) + { + GraphicsConfiguration c = + GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + + backBuffers = new VolatileImage[numBuffers]; + + for (int i = 0; i < numBuffers; i++) + backBuffers[i] = c.createCompatibleVolatileImage(width, height); + } + + /** + * Retrieves the capabilities of this buffer strategy. + * + * @return the capabilities of this buffer strategy + */ + public BufferCapabilities getCapabilities() + { + return caps; + } + + /** + * Retrieves a graphics object that can be used to draw into this + * strategy's image buffer. + * + * @return a graphics object + */ + public Graphics getDrawGraphics() + { + // Return the backmost buffer's graphics. + return backBuffers[0].getGraphics(); + } + + /** + * Bring the contents of the back buffer to the front buffer. + */ + public void show() + { + GraphicsConfiguration c = + GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + + // draw the front buffer. + getGraphics().drawImage(backBuffers[backBuffers.length - 1], + width, height, null); + + BufferCapabilities.FlipContents f = getCapabilities().getFlipContents(); + + // blit the back buffers. + for (int i = backBuffers.length - 1; i > 0 ; i--) + backBuffers[i] = backBuffers[i - 1]; + + // create new backmost buffer. + if (f == BufferCapabilities.FlipContents.UNDEFINED) + backBuffers[0] = c.createCompatibleVolatileImage(width, height); + + // create new backmost buffer and clear it to the background + // color. + if (f == BufferCapabilities.FlipContents.BACKGROUND) + { + backBuffers[0] = c.createCompatibleVolatileImage(width, height); + backBuffers[0].getGraphics().clearRect(0, 0, width, height); + } + + // FIXME: set the backmost buffer to the prior contents of the + // front buffer. How do we retrieve the contents of the front + // buffer? + // + // if (f == BufferCapabilities.FlipContents.PRIOR) + + // set the backmost buffer to a copy of the new front buffer. + if (f == BufferCapabilities.FlipContents.COPIED) + backBuffers[0] = backBuffers[backBuffers.length - 1]; + } + + /** + * Re-create the image buffer resources if they've been lost. + */ + protected void revalidate() + { + GraphicsConfiguration c = + GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + + for (int i = 0; i < backBuffers.length; i++) + { + int result = backBuffers[i].validate(c); + if (result == VolatileImage.IMAGE_INCOMPATIBLE) + backBuffers[i] = c.createCompatibleVolatileImage(width, height); + } + validatedContents = true; + } + + /** + * Returns whether or not the image buffer resources have been + * lost. + * + * @return true if the resources have been lost, false otherwise + */ + public boolean contentsLost() + { + for (int i = 0; i < backBuffers.length; i++) + { + if (backBuffers[i].contentsLost()) + { + validatedContents = false; + return true; + } + } + // we know that the buffer resources are valid now because we + // just checked them + validatedContents = true; + return false; + } + + /** + * Returns whether or not the image buffer resources have been + * restored. + * + * @return true if the resources have been restored, false + * otherwise + */ + public boolean contentsRestored() + { + GraphicsConfiguration c = + GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + + boolean imageRestored = false; + + for (int i = 0; i < backBuffers.length; i++) + { + int result = backBuffers[i].validate(c); + if (result == VolatileImage.IMAGE_RESTORED) + imageRestored = true; + else if (result == VolatileImage.IMAGE_INCOMPATIBLE) + return false; + } + // we know that the buffer resources are valid now because we + // just checked them + validatedContents = true; + return imageRestored; + } + } + + /** + * This class provides support for flipping component buffers. It + * can only be used on Canvases and Windows. + * + * @since 1.4 + */ + protected class FlipBufferStrategy extends BufferStrategy + { + /** + * The number of buffers. + */ + protected int numBuffers; + + /** + * The capabilities of this buffering strategy. + */ + protected BufferCapabilities caps; + + /** + * An Image reference to the drawing buffer. + */ + protected Image drawBuffer; + + /** + * A VolatileImage reference to the drawing buffer. + */ + protected VolatileImage drawVBuffer; + + /** + * Whether or not the image buffer resources are allocated and + * ready to be drawn into. + */ + protected boolean validatedContents; + + /** + * The width of the back buffer. + */ + private int width; + + /** + * The height of the back buffer. + */ + private int height; + + /** + * Creates a flipping buffer strategy. The only supported + * strategy for FlipBufferStrategy itself is a double-buffer page + * flipping strategy. It forms the basis for more complex derived + * strategies. + * + * @param numBuffers the number of buffers + * @param caps the capabilities of this buffering strategy + * + * @throws AWTException if the requested + * number-of-buffers/capabilities combination is not supported + */ + protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps) + throws AWTException + { + this.caps = caps; + width = getWidth(); + height = getHeight(); + + if (numBuffers > 1) + createBuffers(numBuffers, caps); + else + { + drawVBuffer = peer.createVolatileImage(width, height); + drawBuffer = drawVBuffer; + } + } + + /** + * Creates a multi-buffer flipping strategy. The number of + * buffers must be greater than one and the buffer capabilities + * must specify page flipping. + * + * @param numBuffers the number of flipping buffers; must be + * greater than one + * @param caps the buffering capabilities; caps.isPageFlipping() + * must return true + * + * @throws IllegalArgumentException if numBuffers is not greater + * than one or if the page flipping capability is not requested + * + * @throws AWTException if the requested flipping strategy is not + * supported + */ + protected void createBuffers(int numBuffers, BufferCapabilities caps) + throws AWTException + { + if (numBuffers <= 1) + throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:" + + " numBuffers must be greater than" + + " one."); + + if (!caps.isPageFlipping()) + throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:" + + " flipping must be a specified" + + " capability."); + + peer.createBuffers(numBuffers, caps); + } + + /** + * Return a direct reference to the back buffer image. + * + * @return a direct reference to the back buffer image. + */ + protected Image getBackBuffer() + { + return peer.getBackBuffer(); + } + + /** + * Perform a flip operation to transfer the contents of the back + * buffer to the front buffer. + */ + protected void flip(BufferCapabilities.FlipContents flipAction) + { + peer.flip(flipAction); + } + + /** + * Release the back buffer's resources. + */ + protected void destroyBuffers() + { + peer.destroyBuffers(); + } + + /** + * Retrieves the capabilities of this buffer strategy. + * + * @return the capabilities of this buffer strategy + */ + public BufferCapabilities getCapabilities() + { + return caps; + } + + /** + * Retrieves a graphics object that can be used to draw into this + * strategy's image buffer. + * + * @return a graphics object + */ + public Graphics getDrawGraphics() + { + return drawVBuffer.getGraphics(); + } + + /** + * Re-create the image buffer resources if they've been lost. + */ + protected void revalidate() + { + GraphicsConfiguration c = + GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + + if (drawVBuffer.validate(c) == VolatileImage.IMAGE_INCOMPATIBLE) + drawVBuffer = peer.createVolatileImage(width, height); + validatedContents = true; + } + + /** + * Returns whether or not the image buffer resources have been + * lost. + * + * @return true if the resources have been lost, false otherwise + */ + public boolean contentsLost() + { + if (drawVBuffer.contentsLost()) + { + validatedContents = false; + return true; + } + // we know that the buffer resources are valid now because we + // just checked them + validatedContents = true; + return false; + } + + /** + * Returns whether or not the image buffer resources have been + * restored. + * + * @return true if the resources have been restored, false + * otherwise + */ + public boolean contentsRestored() + { + GraphicsConfiguration c = + GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + + int result = drawVBuffer.validate(c); + + boolean imageRestored = false; + + if (result == VolatileImage.IMAGE_RESTORED) + imageRestored = true; + else if (result == VolatileImage.IMAGE_INCOMPATIBLE) + return false; + + // we know that the buffer resources are valid now because we + // just checked them + validatedContents = true; + return imageRestored; + } + + /** + * Bring the contents of the back buffer to the front buffer. + */ + public void show() + { + flip(caps.getFlipContents()); + } + } +} diff --git a/libjava/classpath/java/awt/ComponentOrientation.java b/libjava/classpath/java/awt/ComponentOrientation.java new file mode 100644 index 0000000..69b14c7 --- /dev/null +++ b/libjava/classpath/java/awt/ComponentOrientation.java @@ -0,0 +1,215 @@ +/* ComponentOrientation.java -- describes a component's orientation + Copyright (C) 2000, 2001, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.io.Serializable; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * This class is used to differentiate different orientations for text layout. + * It controls whether text flows left-to-right or right-to-left, and whether + * lines are horizontal or vertical, as in this table:<br> + * <pre> + * LT RT TL TR + * A B C C B A A D G G D A + * D E F F E D B E H H E B + * G H I I H G C F I I F C + * </pre> + * <b>LT</b> languages are most common (left-to-right lines, top-to-bottom). + * This includes Western European languages, and optionally includes Japanese, + * Chinese, and Korean. <b>RT</b> languages (right-to-left lines, + * top-to-bottom) are mainly middle eastern, such as Hebrew and Arabic. + * <b>TR</b> languages flow top-to-bottom in a line, right-to-left, and are + * the basis of Japanese, Chinese, and Korean. Finally, <b>TL</b> languages + * flow top-to-bottom in a line, left-to-right, as in Mongolian. + * + * <p>This is a pretty poor excuse for a type-safe enum, since it is not + * guaranteed that orientation objects are unique (thanks to serialization), + * yet there is no equals() method. You would be wise to compare the output + * of isHorizontal() and isLeftToRight() rather than comparing objects with + * ==, especially since more constants may be added in the future. + * + * @author Bryce McKinlay (bryce@albatross.co.nz) + * @since 1.0 + * @status updated to 1.4 + */ +public final class ComponentOrientation implements Serializable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -4113291392143563828L; + + /** Constant for unknown orientation. */ + private static final int UNKNOWN_ID = 1; + + /** Constant for horizontal line orientation. */ + private static final int HORIZONTAL_ID = 2; + + /** Constant for left-to-right orientation. */ + private static final int LEFT_TO_RIGHT_ID = 4; + + /** + * Items run left to right, and lines flow top to bottom. Examples: English, + * French. + */ + public static final ComponentOrientation LEFT_TO_RIGHT + = new ComponentOrientation(HORIZONTAL_ID | LEFT_TO_RIGHT_ID); + + /** + * Items run right to left, and lines flow top to bottom. Examples: Arabic, + * Hebrew. + */ + public static final ComponentOrientation RIGHT_TO_LEFT + = new ComponentOrientation(HORIZONTAL_ID); + + /** + * The orientation is unknown for the locale. For backwards compatibility, + * this behaves like LEFT_TO_RIGHT in the instance methods. + */ + public static final ComponentOrientation UNKNOWN + = new ComponentOrientation(UNKNOWN_ID | HORIZONTAL_ID | LEFT_TO_RIGHT_ID); + + /** + * The orientation of this object; bitwise-or of unknown (1), horizontal (2), + * and left-to-right (4). + * + * @serial the orientation + */ + private final int orientation; + + /** + * Construct a given orientation. + * + * @param orientation the orientation + */ + private ComponentOrientation(int orientation) + { + this.orientation = orientation; + } + + /** + * Returns true if the lines are horizontal, in which case lines flow + * top-to-bottom. For example, English, Hebrew. Counterexamples: Japanese, + * Chinese, Korean, Mongolian. + * + * @return true if this orientation has horizontal lines + */ + public boolean isHorizontal() + { + return (orientation & HORIZONTAL_ID) != 0; + } + + /** + * If isHorizontal() returns true, then this determines whether items in + * the line flow left-to-right. If isHorizontal() returns false, items in + * a line flow top-to-bottom, and this determines if lines flow + * left-to-right. + * + * @return true if this orientation flows left-to-right + */ + public boolean isLeftToRight() + { + return (orientation & LEFT_TO_RIGHT_ID) != 0; + } + + /** + * Gets an orientation appropriate for the locale. + * + * @param locale the locale + * @return the orientation for that locale + * @throws NullPointerException if locale is null + */ + public static ComponentOrientation getOrientation(Locale locale) + { + // Based on iterating over all languages defined in JDK 1.4, this behavior + // matches Sun's. However, it makes me wonder if any non-horizontal + // orientations even exist, as it sure contradicts their documentation. + String language = locale.getLanguage(); + if ("ar".equals(language) || "fa".equals(language) || "iw".equals(language) + || "ur".equals(language)) + return RIGHT_TO_LEFT; + return LEFT_TO_RIGHT; + } + + /** + * Gets an orientation from a resource bundle. This tries the following: + * + * <ul> + * <li>Use the key "Orientation" to find an instance of ComponentOrientation + * in the bundle.</li> + * <li>Get the locale of the resource bundle, and get the orientation of + * that locale.</li> + * <li>Give up and get the orientation of the default locale.</li> + * </ul> + * + * @param bdl the bundle to use + * @return the orientation + * @throws NullPointerException if bdl is null + * @deprecated use {@link #getOrientation(Locale)} instead + */ + public static ComponentOrientation getOrientation(ResourceBundle bdl) + { + ComponentOrientation r; + try + { + r = (ComponentOrientation) bdl.getObject("Orientation"); + if (r != null) + return r; + } + catch (MissingResourceException ignored) + { + } + catch (ClassCastException ignored) + { + } + try + { + r = getOrientation(bdl.getLocale()); + if (r != null) + return r; + } + catch (Exception ignored) + { + } + return getOrientation(Locale.getDefault()); + } +} // class ComponentOrientation diff --git a/libjava/classpath/java/awt/Composite.java b/libjava/classpath/java/awt/Composite.java new file mode 100644 index 0000000..ca3abe4 --- /dev/null +++ b/libjava/classpath/java/awt/Composite.java @@ -0,0 +1,73 @@ +/* Composite.java -- graphics formed from composite layers + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.image.ColorModel; + +/** + * This interface is for graphics which are formed as composites of others. + * It combines {@link Graphics2D} shapes according to defined rules to form + * the new image. Implementations of this interface must be immutable, because + * they are not cloned when a Graphics2D container is cloned. + * + * <p>Since this can expose pixels to untrusted code, there is a security + * check on custom objects, <code>readDisplayPixels</code>, to prevent leaking + * restricted information graphically. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see AlphaComposite + * @see CompositeContext + * @see Graphics2D#setComposite(Composite) + * @since 1.2 + * @status updated to 1.4 + */ +public interface Composite +{ + /** + * Create a context state for performing the compositing operation. Several + * contexts may exist for this object, in a multi-threaded environment. + * + * @param srcColorModel the color model of the source + * @param dstColorModel the color model of the destination + * @param hints hints for choosing between rendering alternatives + */ + CompositeContext createContext(ColorModel srcColorModel, + ColorModel dstColorModel, + RenderingHints hints); +} // interface Composite diff --git a/libjava/classpath/java/awt/CompositeContext.java b/libjava/classpath/java/awt/CompositeContext.java new file mode 100644 index 0000000..018a270 --- /dev/null +++ b/libjava/classpath/java/awt/CompositeContext.java @@ -0,0 +1,71 @@ +/* Composite.java -- the context for compositing graphics layers + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.image.Raster; +import java.awt.image.WritableRaster; + +/** + * This interface provides an optimized environment for compositing graphics. + * Several such contexts may exist for a given <code>Composite</code> object. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see Composite + * @since 1.2 + * @status updated to 1.4 + */ +public interface CompositeContext +{ + /** + * Release resources allocated for the compositing. + */ + void dispose(); + + /** + * Compose the two source images into the composite image. The destination + * can be the same as one of the two inputs, and the destination must be + * compatible with the ColorModel chosen in {@link Composite#createContext}. + * + * @param src the lower image source in compositing + * @param dstIn the upper image source in compositing + * @param dstOut the destination for the composite + * @see Composite + */ + void compose(Raster src, Raster dstIn, WritableRaster dstOut); +} // interface CompositeContext diff --git a/libjava/classpath/java/awt/Container.java b/libjava/classpath/java/awt/Container.java new file mode 100644 index 0000000..303d13b --- /dev/null +++ b/libjava/classpath/java/awt/Container.java @@ -0,0 +1,2026 @@ +/* Container.java -- parent container class in AWT + Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.peer.ContainerPeer; +import java.awt.peer.LightweightPeer; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Serializable; +import java.util.Collections; +import java.util.EventListener; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import javax.accessibility.Accessible; +import javax.swing.SwingUtilities; + +/** + * A generic window toolkit object that acts as a container for other objects. + * Components are tracked in a list, and new elements are at the end of the + * list or bottom of the stacking order. + * + * @author original author unknown + * @author Eric Blake (ebb9@email.byu.edu) + * + * @since 1.0 + * + * @status still missing 1.4 support + */ +public class Container extends Component +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 4613797578919906343L; + + /* Serialized fields from the serialization spec. */ + int ncomponents; + Component[] component; + LayoutManager layoutMgr; + + LightweightDispatcher dispatcher; + + Dimension maxSize; + + /** + * @since 1.4 + */ + boolean focusCycleRoot; + + int containerSerializedDataVersion; + + /* Anything else is non-serializable, and should be declared "transient". */ + transient ContainerListener containerListener; + transient PropertyChangeSupport changeSupport; + + /** The focus traversal policy that determines how focus is + transferred between this Container and its children. */ + private FocusTraversalPolicy focusTraversalPolicy; + + /** + * The focus traversal keys, if not inherited from the parent or default + * keyboard manager. These sets will contain only AWTKeyStrokes that + * represent press and release events to use as focus control. + * + * @see #getFocusTraversalKeys(int) + * @see #setFocusTraversalKeys(int, Set) + * @since 1.4 + */ + transient Set[] focusTraversalKeys; + + /** + * Default constructor for subclasses. + */ + public Container() + { + } + + /** + * Returns the number of components in this container. + * + * @return The number of components in this container. + */ + public int getComponentCount() + { + return countComponents (); + } + + /** + * Returns the number of components in this container. + * + * @return The number of components in this container. + * + * @deprecated use {@link #getComponentCount()} instead + */ + public int countComponents() + { + return ncomponents; + } + + /** + * Returns the component at the specified index. + * + * @param n The index of the component to retrieve. + * + * @return The requested component. + * + * @throws ArrayIndexOutOfBoundsException If the specified index is invalid + */ + public Component getComponent(int n) + { + synchronized (getTreeLock ()) + { + if (n < 0 || n >= ncomponents) + throw new ArrayIndexOutOfBoundsException("no such component"); + + return component[n]; + } + } + + /** + * Returns an array of the components in this container. + * + * @return The components in this container. + */ + public Component[] getComponents() + { + synchronized (getTreeLock ()) + { + Component[] result = new Component[ncomponents]; + + if (ncomponents > 0) + System.arraycopy(component, 0, result, 0, ncomponents); + + return result; + } + } + + /** + * Swaps the components at position i and j, in the container. + */ + + protected void swapComponents (int i, int j) + { + synchronized (getTreeLock ()) + { + if (i < 0 + || i >= component.length + || j < 0 + || j >= component.length) + throw new ArrayIndexOutOfBoundsException (); + Component tmp = component[i]; + component[i] = component[j]; + component[j] = tmp; + } + } + + /** + * Returns the insets for this container, which is the space used for + * borders, the margin, etc. + * + * @return The insets for this container. + */ + public Insets getInsets() + { + return insets (); + } + + /** + * Returns the insets for this container, which is the space used for + * borders, the margin, etc. + * + * @return The insets for this container. + * @deprecated use {@link #getInsets()} instead + */ + public Insets insets() + { + if (peer == null) + return new Insets (0, 0, 0, 0); + + return ((ContainerPeer) peer).getInsets (); + } + + /** + * Adds the specified component to this container at the end of the + * component list. + * + * @param comp The component to add to the container. + * + * @return The same component that was added. + */ + public Component add(Component comp) + { + addImpl(comp, null, -1); + return comp; + } + + /** + * Adds the specified component to the container at the end of the + * component list. This method should not be used. Instead, use + * <code>add(Component, Object)</code>. + * + * @param name The name of the component to be added. + * @param comp The component to be added. + * + * @return The same component that was added. + * + * @see #add(Component,Object) + */ + public Component add(String name, Component comp) + { + addImpl(comp, name, -1); + return comp; + } + + /** + * Adds the specified component to this container at the specified index + * in the component list. + * + * @param comp The component to be added. + * @param index The index in the component list to insert this child + * at, or -1 to add at the end of the list. + * + * @return The same component that was added. + * + * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. + */ + public Component add(Component comp, int index) + { + addImpl(comp, null, index); + return comp; + } + + /** + * Adds the specified component to this container at the end of the + * component list. The layout manager will use the specified constraints + * when laying out this component. + * + * @param comp The component to be added to this container. + * @param constraints The layout constraints for this component. + */ + public void add(Component comp, Object constraints) + { + addImpl(comp, constraints, -1); + } + + /** + * Adds the specified component to this container at the specified index + * in the component list. The layout manager will use the specified + * constraints when layout out this component. + * + * @param comp The component to be added. + * @param constraints The layout constraints for this component. + * @param index The index in the component list to insert this child + * at, or -1 to add at the end of the list. + * + * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. + */ + public void add(Component comp, Object constraints, int index) + { + addImpl(comp, constraints, index); + } + + /** + * This method is called by all the <code>add()</code> methods to perform + * the actual adding of the component. Subclasses who wish to perform + * their own processing when a component is added should override this + * method. Any subclass doing this must call the superclass version of + * this method in order to ensure proper functioning of the container. + * + * @param comp The component to be added. + * @param constraints The layout constraints for this component, or + * <code>null</code> if there are no constraints. + * @param index The index in the component list to insert this child + * at, or -1 to add at the end of the list. + * + * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. + */ + protected void addImpl(Component comp, Object constraints, int index) + { + synchronized (getTreeLock ()) + { + if (index > ncomponents + || (index < 0 && index != -1) + || comp instanceof Window + || (comp instanceof Container + && ((Container) comp).isAncestorOf(this))) + throw new IllegalArgumentException(); + + // Reparent component, and make sure component is instantiated if + // we are. + if (comp.parent != null) + comp.parent.remove(comp); + comp.parent = this; + if (peer != null) + { + if (comp.isLightweight ()) + { + enableEvents (comp.eventMask); + if (!isLightweight ()) + enableEvents (AWTEvent.PAINT_EVENT_MASK); + } + } + + invalidate(); + + if (component == null) + component = new Component[4]; // FIXME, better initial size? + + // This isn't the most efficient implementation. We could do less + // copying when growing the array. It probably doesn't matter. + if (ncomponents >= component.length) + { + int nl = component.length * 2; + Component[] c = new Component[nl]; + System.arraycopy(component, 0, c, 0, ncomponents); + component = c; + } + + if (index == -1) + component[ncomponents++] = comp; + else + { + System.arraycopy(component, index, component, index + 1, + ncomponents - index); + component[index] = comp; + ++ncomponents; + } + + // Notify the layout manager. + if (layoutMgr != null) + { + if (layoutMgr instanceof LayoutManager2) + { + LayoutManager2 lm2 = (LayoutManager2) layoutMgr; + lm2.addLayoutComponent(comp, constraints); + } + else if (constraints instanceof String) + layoutMgr.addLayoutComponent((String) constraints, comp); + else + layoutMgr.addLayoutComponent(null, comp); + } + + if (isShowing ()) + { + // Post event to notify of adding the component. + ContainerEvent ce = new ContainerEvent(this, + ContainerEvent.COMPONENT_ADDED, + comp); + getToolkit().getSystemEventQueue().postEvent(ce); + } + } + } + + /** + * Removes the component at the specified index from this container. + * + * @param index The index of the component to remove. + */ + public void remove(int index) + { + synchronized (getTreeLock ()) + { + Component r = component[index]; + + r.removeNotify(); + + System.arraycopy(component, index + 1, component, index, + ncomponents - index - 1); + component[--ncomponents] = null; + + invalidate(); + + if (layoutMgr != null) + layoutMgr.removeLayoutComponent(r); + + r.parent = null; + + if (isShowing ()) + { + // Post event to notify of removing the component. + ContainerEvent ce = new ContainerEvent(this, + ContainerEvent.COMPONENT_REMOVED, + r); + getToolkit().getSystemEventQueue().postEvent(ce); + } + } + } + + /** + * Removes the specified component from this container. + * + * @param comp The component to remove from this container. + */ + public void remove(Component comp) + { + synchronized (getTreeLock ()) + { + for (int i = 0; i < ncomponents; ++i) + { + if (component[i] == comp) + { + remove(i); + break; + } + } + } + } + + /** + * Removes all components from this container. + */ + public void removeAll() + { + synchronized (getTreeLock ()) + { + while (ncomponents > 0) + remove(0); + } + } + + /** + * Returns the current layout manager for this container. + * + * @return The layout manager for this container. + */ + public LayoutManager getLayout() + { + return layoutMgr; + } + + /** + * Sets the layout manager for this container to the specified layout + * manager. + * + * @param mgr The new layout manager for this container. + */ + public void setLayout(LayoutManager mgr) + { + layoutMgr = mgr; + invalidate(); + } + + /** + * Layout the components in this container. + */ + public void doLayout() + { + layout (); + } + + /** + * Layout the components in this container. + * + * @deprecated use {@link #doLayout()} instead + */ + public void layout() + { + if (layoutMgr != null) + layoutMgr.layoutContainer (this); + } + + /** + * Invalidates this container to indicate that it (and all parent + * containers) need to be laid out. + */ + public void invalidate() + { + super.invalidate(); + } + + /** + * Re-lays out the components in this container. + */ + public void validate() + { + synchronized (getTreeLock ()) + { + if (! isValid() && peer != null) + { + validateTree(); + } + } + } + + /** + * Recursively invalidates the container tree. + */ + void invalidateTree() + { + for (int i = 0; i < ncomponents; i++) + { + Component comp = component[i]; + comp.invalidate(); + if (comp instanceof Container) + ((Container) comp).invalidateTree(); + } + } + + /** + * Recursively validates the container tree, recomputing any invalid + * layouts. + */ + protected void validateTree() + { + if (valid) + return; + + ContainerPeer cPeer = null; + if (peer != null && ! (peer instanceof LightweightPeer)) + { + cPeer = (ContainerPeer) peer; + cPeer.beginValidate(); + } + + for (int i = 0; i < ncomponents; ++i) + { + Component comp = component[i]; + + if (comp.getPeer () == null) + comp.addNotify(); + } + + doLayout (); + for (int i = 0; i < ncomponents; ++i) + { + Component comp = component[i]; + + if (! comp.isValid()) + { + if (comp instanceof Container) + { + ((Container) comp).validateTree(); + } + else + { + component[i].validate(); + } + } + } + + /* children will call invalidate() when they are layed out. It + is therefore important that valid is not set to true + until after the children have been layed out. */ + valid = true; + + if (cPeer != null) + cPeer.endValidate(); + } + + public void setFont(Font f) + { + super.setFont(f); + // FIXME: Although it might make more sense to invalidate only + // those children whose font == null, Sun invalidates all children. + // So we'll do the same. + invalidateTree(); + } + + /** + * Returns the preferred size of this container. + * + * @return The preferred size of this container. + */ + public Dimension getPreferredSize() + { + return preferredSize (); + } + + /** + * Returns the preferred size of this container. + * + * @return The preferred size of this container. + * + * @deprecated use {@link #getPreferredSize()} instead + */ + public Dimension preferredSize() + { + if (layoutMgr != null) + return layoutMgr.preferredLayoutSize (this); + else + return super.preferredSize (); + } + + /** + * Returns the minimum size of this container. + * + * @return The minimum size of this container. + */ + public Dimension getMinimumSize() + { + return minimumSize (); + } + + /** + * Returns the minimum size of this container. + * + * @return The minimum size of this container. + * + * @deprecated use {@link #getMinimumSize()} instead + */ + public Dimension minimumSize() + { + if (layoutMgr != null) + return layoutMgr.minimumLayoutSize (this); + else + return super.minimumSize (); + } + + /** + * Returns the maximum size of this container. + * + * @return The maximum size of this container. + */ + public Dimension getMaximumSize() + { + if (layoutMgr != null && layoutMgr instanceof LayoutManager2) + { + LayoutManager2 lm2 = (LayoutManager2) layoutMgr; + return lm2.maximumLayoutSize(this); + } + else + return super.getMaximumSize(); + } + + /** + * Returns the preferred alignment along the X axis. This is a value + * between 0 and 1 where 0 represents alignment flush left and + * 1 means alignment flush right, and 0.5 means centered. + * + * @return The preferred alignment along the X axis. + */ + public float getAlignmentX() + { + if (layoutMgr instanceof LayoutManager2) + { + LayoutManager2 lm2 = (LayoutManager2) layoutMgr; + return lm2.getLayoutAlignmentX(this); + } + else + return super.getAlignmentX(); + } + + /** + * Returns the preferred alignment along the Y axis. This is a value + * between 0 and 1 where 0 represents alignment flush top and + * 1 means alignment flush bottom, and 0.5 means centered. + * + * @return The preferred alignment along the Y axis. + */ + public float getAlignmentY() + { + if (layoutMgr instanceof LayoutManager2) + { + LayoutManager2 lm2 = (LayoutManager2) layoutMgr; + return lm2.getLayoutAlignmentY(this); + } + else + return super.getAlignmentY(); + } + + /** + * Paints this container. The implementation of this method in this + * class forwards to any lightweight components in this container. If + * this method is subclassed, this method should still be invoked as + * a superclass method so that lightweight components are properly + * drawn. + * + * @param g The graphics context for this paint job. + */ + public void paint(Graphics g) + { + if (!isShowing()) + return; + // Paint self first. + super.paint(g); + // Visit heavyweights as well, in case they were + // erased when we cleared the background for this container. + visitChildren(g, GfxPaintVisitor.INSTANCE, false); + } + + /** + * Updates this container. The implementation of this method in this + * class forwards to any lightweight components in this container. If + * this method is subclassed, this method should still be invoked as + * a superclass method so that lightweight components are properly + * drawn. + * + * @param g The graphics context for this update. + */ + public void update(Graphics g) + { + super.update(g); + } + + /** + * Prints this container. The implementation of this method in this + * class forwards to any lightweight components in this container. If + * this method is subclassed, this method should still be invoked as + * a superclass method so that lightweight components are properly + * drawn. + * + * @param g The graphics context for this print job. + */ + public void print(Graphics g) + { + super.print(g); + visitChildren(g, GfxPrintVisitor.INSTANCE, true); + } + + /** + * Paints all of the components in this container. + * + * @param g The graphics context for this paint job. + */ + public void paintComponents(Graphics g) + { + super.paint(g); + visitChildren(g, GfxPaintAllVisitor.INSTANCE, true); + } + + /** + * Prints all of the components in this container. + * + * @param g The graphics context for this print job. + */ + public void printComponents(Graphics g) + { + super.paint(g); + visitChildren(g, GfxPrintAllVisitor.INSTANCE, true); + } + + /** + * Adds the specified container listener to this object's list of + * container listeners. + * + * @param listener The listener to add. + */ + public synchronized void addContainerListener(ContainerListener listener) + { + containerListener = AWTEventMulticaster.add(containerListener, listener); + } + + /** + * Removes the specified container listener from this object's list of + * container listeners. + * + * @param listener The listener to remove. + */ + public synchronized void removeContainerListener(ContainerListener listener) + { + containerListener = AWTEventMulticaster.remove(containerListener, listener); + } + + /** + * @since 1.4 + */ + public synchronized ContainerListener[] getContainerListeners() + { + return (ContainerListener[]) + AWTEventMulticaster.getListeners(containerListener, + ContainerListener.class); + } + + /** + * Returns an array of all the objects currently registered as FooListeners + * upon this Container. FooListeners are registered using the addFooListener + * method. + * + * @exception ClassCastException If listenerType doesn't specify a class or + * interface that implements @see java.util.EventListener. + * + * @since 1.3 + */ + public EventListener[] getListeners(Class listenerType) + { + if (listenerType == ContainerListener.class) + return getContainerListeners(); + return super.getListeners(listenerType); + } + + /** + * Processes the specified event. This method calls + * <code>processContainerEvent()</code> if this method is a + * <code>ContainerEvent</code>, otherwise it calls the superclass + * method. + * + * @param e The event to be processed. + */ + protected void processEvent(AWTEvent e) + { + if (e instanceof ContainerEvent) + processContainerEvent((ContainerEvent) e); + else + super.processEvent(e); + } + + /** + * Called when a container event occurs if container events are enabled. + * This method calls any registered listeners. + * + * @param e The event that occurred. + */ + protected void processContainerEvent(ContainerEvent e) + { + if (containerListener == null) + return; + switch (e.id) + { + case ContainerEvent.COMPONENT_ADDED: + containerListener.componentAdded(e); + break; + + case ContainerEvent.COMPONENT_REMOVED: + containerListener.componentRemoved(e); + break; + } + } + + /** + * AWT 1.0 event processor. + * + * @param e The event that occurred. + * + * @deprecated use {@link #dispatchEvent(AWTEvent)} instead + */ + public void deliverEvent(Event e) + { + if (!handleEvent (e)) + { + synchronized (getTreeLock ()) + { + Component parent = getParent (); + + if (parent != null) + parent.deliverEvent (e); + } + } + } + + /** + * Returns the component located at the specified point. This is done + * by checking whether or not a child component claims to contain this + * point. The first child component that does is returned. If no + * child component claims the point, the container itself is returned, + * unless the point does not exist within this container, in which + * case <code>null</code> is returned. + * + * @param x The X coordinate of the point. + * @param y The Y coordinate of the point. + * + * @return The component containing the specified point, or + * <code>null</code> if there is no such point. + */ + public Component getComponentAt(int x, int y) + { + return locate (x, y); + } + + /** + * Returns the component located at the specified point. This is done + * by checking whether or not a child component claims to contain this + * point. The first child component that does is returned. If no + * child component claims the point, the container itself is returned, + * unless the point does not exist within this container, in which + * case <code>null</code> is returned. + * + * @param x The x position of the point to return the component at. + * @param y The y position of the point to return the component at. + * + * @return The component containing the specified point, or <code>null</code> + * if there is no such point. + * + * @deprecated use {@link #getComponentAt(int, int)} instead + */ + public Component locate(int x, int y) + { + synchronized (getTreeLock ()) + { + if (!contains (x, y)) + return null; + for (int i = 0; i < ncomponents; ++i) + { + // Ignore invisible children... + if (!component[i].isVisible ()) + continue; + + int x2 = x - component[i].x; + int y2 = y - component[i].y; + if (component[i].contains (x2, y2)) + return component[i]; + } + return this; + } + } + + /** + * Returns the component located at the specified point. This is done + * by checking whether or not a child component claims to contain this + * point. The first child component that does is returned. If no + * child component claims the point, the container itself is returned, + * unless the point does not exist within this container, in which + * case <code>null</code> is returned. + * + * @param p The point to return the component at. + * @return The component containing the specified point, or <code>null</code> + * if there is no such point. + */ + public Component getComponentAt(Point p) + { + return getComponentAt (p.x, p.y); + } + + public Component findComponentAt(int x, int y) + { + synchronized (getTreeLock ()) + { + if (! contains(x, y)) + return null; + + for (int i = 0; i < ncomponents; ++i) + { + // Ignore invisible children... + if (!component[i].isVisible()) + continue; + + int x2 = x - component[i].x; + int y2 = y - component[i].y; + // We don't do the contains() check right away because + // findComponentAt would redundantly do it first thing. + if (component[i] instanceof Container) + { + Container k = (Container) component[i]; + Component r = k.findComponentAt(x2, y2); + if (r != null) + return r; + } + else if (component[i].contains(x2, y2)) + return component[i]; + } + + return this; + } + } + + public Component findComponentAt(Point p) + { + return findComponentAt(p.x, p.y); + } + + /** + * Called when this container is added to another container to inform it + * to create its peer. Peers for any child components will also be + * created. + */ + public void addNotify() + { + super.addNotify(); + addNotifyContainerChildren(); + } + + /** + * Called when this container is removed from its parent container to + * inform it to destroy its peer. This causes the peers of all child + * component to be destroyed as well. + */ + public void removeNotify() + { + synchronized (getTreeLock ()) + { + for (int i = 0; i < ncomponents; ++i) + component[i].removeNotify(); + super.removeNotify(); + } + } + + /** + * Tests whether or not the specified component is contained within + * this components subtree. + * + * @param comp The component to test. + * + * @return <code>true</code> if this container is an ancestor of the + * specified component, <code>false</code> otherwise. + */ + public boolean isAncestorOf(Component comp) + { + synchronized (getTreeLock ()) + { + while (true) + { + if (comp == null) + return false; + if (comp == this) + return true; + comp = comp.getParent(); + } + } + } + + /** + * Returns a string representing the state of this container for + * debugging purposes. + * + * @return A string representing the state of this container. + */ + protected String paramString() + { + if (layoutMgr == null) + return super.paramString(); + + StringBuffer sb = new StringBuffer(); + sb.append(super.paramString()); + sb.append(",layout="); + sb.append(layoutMgr.getClass().getName()); + return sb.toString(); + } + + /** + * Writes a listing of this container to the specified stream starting + * at the specified indentation point. + * + * @param out The <code>PrintStream</code> to write to. + * @param indent The indentation point. + */ + public void list(PrintStream out, int indent) + { + synchronized (getTreeLock ()) + { + super.list(out, indent); + for (int i = 0; i < ncomponents; ++i) + component[i].list(out, indent + 2); + } + } + + /** + * Writes a listing of this container to the specified stream starting + * at the specified indentation point. + * + * @param out The <code>PrintWriter</code> to write to. + * @param indent The indentation point. + */ + public void list(PrintWriter out, int indent) + { + synchronized (getTreeLock ()) + { + super.list(out, indent); + for (int i = 0; i < ncomponents; ++i) + component[i].list(out, indent + 2); + } + } + + /** + * Sets the focus traversal keys for a given traversal operation for this + * Container. + * + * @exception IllegalArgumentException If id is not one of + * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, + * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, + * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, + * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, + * or if keystrokes contains null, or if any Object in keystrokes is not an + * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, or if any + * keystroke already maps to another focus traversal operation for this + * Container. + * + * @since 1.4 + */ + public void setFocusTraversalKeys(int id, Set keystrokes) + { + if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && + id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) + throw new IllegalArgumentException (); + + if (keystrokes == null) + { + Container parent = getParent (); + + while (parent != null) + { + if (parent.areFocusTraversalKeysSet (id)) + { + keystrokes = parent.getFocusTraversalKeys (id); + break; + } + parent = parent.getParent (); + } + + if (keystrokes == null) + keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager (). + getDefaultFocusTraversalKeys (id); + } + + Set sa; + Set sb; + Set sc; + String name; + switch (id) + { + case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS: + sa = getFocusTraversalKeys + (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); + sb = getFocusTraversalKeys + (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); + sc = getFocusTraversalKeys + (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); + name = "forwardFocusTraversalKeys"; + break; + case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS: + sa = getFocusTraversalKeys + (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); + sb = getFocusTraversalKeys + (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); + sc = getFocusTraversalKeys + (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); + name = "backwardFocusTraversalKeys"; + break; + case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS: + sa = getFocusTraversalKeys + (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); + sb = getFocusTraversalKeys + (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); + sc = getFocusTraversalKeys + (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); + name = "upCycleFocusTraversalKeys"; + break; + case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS: + sa = getFocusTraversalKeys + (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); + sb = getFocusTraversalKeys + (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); + sc = getFocusTraversalKeys + (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); + name = "downCycleFocusTraversalKeys"; + break; + default: + throw new IllegalArgumentException (); + } + + int i = keystrokes.size (); + Iterator iter = keystrokes.iterator (); + + while (--i >= 0) + { + Object o = iter.next (); + if (!(o instanceof AWTKeyStroke) + || sa.contains (o) || sb.contains (o) || sc.contains (o) + || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED) + throw new IllegalArgumentException (); + } + + if (focusTraversalKeys == null) + focusTraversalKeys = new Set[3]; + + keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes)); + firePropertyChange (name, focusTraversalKeys[id], keystrokes); + + focusTraversalKeys[id] = keystrokes; + } + + /** + * Returns the Set of focus traversal keys for a given traversal operation for + * this Container. + * + * @exception IllegalArgumentException If id is not one of + * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, + * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, + * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, + * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS. + * + * @since 1.4 + */ + public Set getFocusTraversalKeys (int id) + { + if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && + id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) + throw new IllegalArgumentException (); + + Set s = null; + + if (focusTraversalKeys != null) + s = focusTraversalKeys[id]; + + if (s == null && parent != null) + s = parent.getFocusTraversalKeys (id); + + return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager() + .getDefaultFocusTraversalKeys(id)) : s; + } + + /** + * Returns whether the Set of focus traversal keys for the given focus + * traversal operation has been explicitly defined for this Container. + * If this method returns false, this Container is inheriting the Set from + * an ancestor, or from the current KeyboardFocusManager. + * + * @exception IllegalArgumentException If id is not one of + * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, + * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, + * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, + * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS. + * + * @since 1.4 + */ + public boolean areFocusTraversalKeysSet (int id) + { + if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && + id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) + throw new IllegalArgumentException (); + + return focusTraversalKeys != null && focusTraversalKeys[id] != null; + } + + /** + * Check whether the given Container is the focus cycle root of this + * Container's focus traversal cycle. If this Container is a focus + * cycle root itself, then it will be in two different focus cycles + * -- it's own, and that of its ancestor focus cycle root's. In + * that case, if <code>c</code> is either of those containers, this + * method will return true. + * + * @param c the candidate Container + * + * @return true if c is the focus cycle root of the focus traversal + * cycle to which this Container belongs, false otherwise + * + * @since 1.4 + */ + public boolean isFocusCycleRoot (Container c) + { + if (this == c + && isFocusCycleRoot ()) + return true; + + Container ancestor = getFocusCycleRootAncestor (); + + if (c == ancestor) + return true; + + return false; + } + + /** + * If this Container is a focus cycle root, set the focus traversal + * policy that determines the focus traversal order for its + * children. If non-null, this policy will be inherited by all + * inferior focus cycle roots. If <code>policy</code> is null, this + * Container will inherit its policy from the closest ancestor focus + * cycle root that's had its policy set. + * + * @param policy the new focus traversal policy for this Container or null + * + * @since 1.4 + */ + public void setFocusTraversalPolicy (FocusTraversalPolicy policy) + { + focusTraversalPolicy = policy; + } + + /** + * Return the focus traversal policy that determines the focus + * traversal order for this Container's children. This method + * returns null if this Container is not a focus cycle root. If the + * focus traversal policy has not been set explicitly, then this + * method will return an ancestor focus cycle root's policy instead. + * + * @return this Container's focus traversal policy or null + * + * @since 1.4 + */ + public FocusTraversalPolicy getFocusTraversalPolicy () + { + if (!isFocusCycleRoot ()) + return null; + + if (focusTraversalPolicy == null) + { + Container ancestor = getFocusCycleRootAncestor (); + + if (ancestor != this) + return ancestor.getFocusTraversalPolicy (); + else + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + + return manager.getDefaultFocusTraversalPolicy (); + } + } + else + return focusTraversalPolicy; + } + + /** + * Check whether this Container's focus traversal policy has been + * explicitly set. If it has not, then this Container will inherit + * its focus traversal policy from one of its ancestor focus cycle + * roots. + * + * @return true if focus traversal policy is set, false otherwise + */ + public boolean isFocusTraversalPolicySet () + { + return focusTraversalPolicy == null; + } + + /** + * Set whether or not this Container is the root of a focus + * traversal cycle. This Container's focus traversal policy + * determines the order of focus traversal. Some policies prevent + * the focus from being transferred between two traversal cycles + * until an up or down traversal operation is performed. In that + * case, normal traversal (not up or down) is limited to this + * Container and all of this Container's descendents that are not + * descendents of inferior focus cycle roots. In the default case + * however, ContainerOrderFocusTraversalPolicy is in effect, and it + * supports implicit down-cycle traversal operations. + * + * @param focusCycleRoot true if this is a focus cycle root, false otherwise + * + * @since 1.4 + */ + public void setFocusCycleRoot (boolean focusCycleRoot) + { + this.focusCycleRoot = focusCycleRoot; + } + + /** + * Check whether this Container is a focus cycle root. + * + * @return true if this is a focus cycle root, false otherwise + * + * @since 1.4 + */ + public boolean isFocusCycleRoot () + { + return focusCycleRoot; + } + + /** + * Transfer focus down one focus traversal cycle. If this Container + * is a focus cycle root, then its default component becomes the + * focus owner, and this Container becomes the current focus cycle + * root. No traversal will occur if this Container is not a focus + * cycle root. + * + * @since 1.4 + */ + public void transferFocusDownCycle () + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + + manager.downFocusCycle (this); + } + + /** + * Sets the ComponentOrientation property of this container and all components + * contained within it. + * + * @exception NullPointerException If orientation is null + * + * @since 1.4 + */ + public void applyComponentOrientation (ComponentOrientation orientation) + { + if (orientation == null) + throw new NullPointerException (); + } + + public void addPropertyChangeListener (PropertyChangeListener listener) + { + if (listener == null) + return; + + if (changeSupport == null) + changeSupport = new PropertyChangeSupport (this); + + changeSupport.addPropertyChangeListener (listener); + } + + public void addPropertyChangeListener (String name, + PropertyChangeListener listener) + { + if (listener == null) + return; + + if (changeSupport == null) + changeSupport = new PropertyChangeSupport (this); + + changeSupport.addPropertyChangeListener (name, listener); + } + + // Hidden helper methods. + + /** + * Perform a graphics operation on the children of this container. + * For each applicable child, the visitChild() method will be called + * to perform the graphics operation. + * + * @param gfx The graphics object that will be used to derive new + * graphics objects for the children. + * + * @param visitor Object encapsulating the graphics operation that + * should be performed. + * + * @param lightweightOnly If true, only lightweight components will + * be visited. + */ + private void visitChildren(Graphics gfx, GfxVisitor visitor, + boolean lightweightOnly) + { + synchronized (getTreeLock ()) + { + for (int i = ncomponents - 1; i >= 0; --i) + { + Component comp = component[i]; + // If we're visiting heavyweights as well, + // don't recurse into Containers here. This avoids + // painting the same nested child multiple times. + boolean applicable = comp.isVisible() + && (comp.isLightweight() + || !lightweightOnly && ! (comp instanceof Container)); + + if (applicable) + visitChild(gfx, visitor, comp); + } + } + } + + /** + * Perform a graphics operation on a child. A translated and clipped + * graphics object will be created, and the visit() method of the + * visitor will be called to perform the operation. + * + * @param gfx The graphics object that will be used to derive new + * graphics objects for the child. + * + * @param visitor Object encapsulating the graphics operation that + * should be performed. + * + * @param comp The child component that should be visited. + */ + private void visitChild(Graphics gfx, GfxVisitor visitor, + Component comp) + { + Rectangle bounds = comp.getBounds(); + Rectangle oldClip = gfx.getClipBounds(); + if (oldClip == null) + oldClip = bounds; + + Rectangle clip = oldClip.intersection(bounds); + + if (clip.isEmpty()) return; + + boolean clipped = false; + boolean translated = false; + try + { + gfx.setClip(clip.x, clip.y, clip.width, clip.height); + clipped = true; + gfx.translate(bounds.x, bounds.y); + translated = true; + visitor.visit(comp, gfx); + } + finally + { + if (translated) + gfx.translate (-bounds.x, -bounds.y); + if (clipped) + gfx.setClip (oldClip.x, oldClip.y, oldClip.width, oldClip.height); + } + } + + void dispatchEventImpl(AWTEvent e) + { + // Give lightweight dispatcher a chance to handle it. + if (eventTypeEnabled (e.id) + && dispatcher != null + && dispatcher.handleEvent (e)) + return; + + if ((e.id <= ContainerEvent.CONTAINER_LAST + && e.id >= ContainerEvent.CONTAINER_FIRST) + && (containerListener != null + || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)) + processEvent(e); + else + super.dispatchEventImpl(e); + } + + // This is used to implement Component.transferFocus. + Component findNextFocusComponent(Component child) + { + synchronized (getTreeLock ()) + { + int start, end; + if (child != null) + { + for (start = 0; start < ncomponents; ++start) + { + if (component[start] == child) + break; + } + end = start; + // This special case lets us be sure to terminate. + if (end == 0) + end = ncomponents; + ++start; + } + else + { + start = 0; + end = ncomponents; + } + + for (int j = start; j != end; ++j) + { + if (j >= ncomponents) + { + // The JCL says that we should wrap here. However, that + // seems wrong. To me it seems that focus order should be + // global within in given window. So instead if we reach + // the end we try to look in our parent, if we have one. + if (parent != null) + return parent.findNextFocusComponent(this); + j -= ncomponents; + } + if (component[j] instanceof Container) + { + Component c = component[j]; + c = c.findNextFocusComponent(null); + if (c != null) + return c; + } + else if (component[j].isFocusTraversable()) + return component[j]; + } + + return null; + } + } + + private void addNotifyContainerChildren() + { + synchronized (getTreeLock ()) + { + for (int i = ncomponents; --i >= 0; ) + { + component[i].addNotify(); + if (component[i].isLightweight ()) + { + + // If we're not lightweight, and we just got a lightweight + // child, we need a lightweight dispatcher to feed it events. + if (! this.isLightweight()) + { + if (dispatcher == null) + dispatcher = new LightweightDispatcher (this); + } + + + enableEvents(component[i].eventMask); + if (peer != null && !isLightweight ()) + enableEvents (AWTEvent.PAINT_EVENT_MASK); + } + } + } + } + + /** + * Deserialize this Container: + * <ol> + * <li>Read from the stream the default serializable fields.</li> + * <li>Read a list of serializable ContainerListeners as optional + * data. If the list is null, no listeners will be registered.</li> + * <li>Read this Container's FocusTraversalPolicy as optional data. + * If this is null, then this Container will use a + * DefaultFocusTraversalPolicy.</li> + * </ol> + * + * @param s the stream to read from + * @throws ClassNotFoundException if deserialization fails + * @throws IOException if the stream fails + */ + private void readObject (ObjectInputStream s) + throws ClassNotFoundException, IOException + { + s.defaultReadObject (); + String key = (String) s.readObject (); + while (key != null) + { + Object object = s.readObject (); + if ("containerL".equals (key)) + addContainerListener((ContainerListener) object); + // FIXME: under what key is the focus traversal policy stored? + else if ("focusTraversalPolicy".equals (key)) + setFocusTraversalPolicy ((FocusTraversalPolicy) object); + + key = (String) s.readObject(); + } + } + + /** + * Serialize this Container: + * <ol> + * <li>Write to the stream the default serializable fields.</li> + * <li>Write the list of serializable ContainerListeners as optional + * data.</li> + * <li>Write this Container's FocusTraversalPolicy as optional data.</li> + * </ol> + * + * @param s the stream to write to + * @throws IOException if the stream fails + */ + private void writeObject (ObjectOutputStream s) throws IOException + { + s.defaultWriteObject (); + AWTEventMulticaster.save (s, "containerL", containerListener); + if (focusTraversalPolicy instanceof Serializable) + s.writeObject (focusTraversalPolicy); + else + s.writeObject (null); + } + + // Nested classes. + + /* The following classes are used in concert with the + visitChildren() method to implement all the graphics operations + that requires traversal of the containment hierarchy. */ + + abstract static class GfxVisitor + { + public abstract void visit(Component c, Graphics gfx); + } + + static class GfxPaintVisitor extends GfxVisitor + { + public static final GfxVisitor INSTANCE = new GfxPaintVisitor(); + + public void visit(Component c, Graphics gfx) + { + c.paint(gfx); + } + } + + static class GfxPrintVisitor extends GfxVisitor + { + public static final GfxVisitor INSTANCE = new GfxPrintVisitor(); + + public void visit(Component c, Graphics gfx) + { + c.print(gfx); + } + } + + static class GfxPaintAllVisitor extends GfxVisitor + { + public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor(); + + public void visit(Component c, Graphics gfx) + { + c.paintAll(gfx); + } + } + + static class GfxPrintAllVisitor extends GfxVisitor + { + public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor(); + + public void visit(Component c, Graphics gfx) + { + c.printAll(gfx); + } + } + + /** + * This class provides accessibility support for subclasses of container. + * + * @author Eric Blake (ebb9@email.byu.edu) + * + * @since 1.3 + */ + protected class AccessibleAWTContainer extends AccessibleAWTComponent + { + /** + * Compatible with JDK 1.4+. + */ + private static final long serialVersionUID = 5081320404842566097L; + + /** + * The handler to fire PropertyChange when children are added or removed. + * + * @serial the handler for property changes + */ + protected ContainerListener accessibleContainerHandler + = new AccessibleContainerHandler(); + + /** + * The default constructor. + */ + protected AccessibleAWTContainer() + { + Container.this.addContainerListener(accessibleContainerHandler); + } + + /** + * Return the number of accessible children of the containing accessible + * object (at most the total number of its children). + * + * @return the number of accessible children + */ + public int getAccessibleChildrenCount() + { + synchronized (getTreeLock ()) + { + int count = 0; + int i = component == null ? 0 : component.length; + while (--i >= 0) + if (component[i] instanceof Accessible) + count++; + return count; + } + } + + /** + * Return the nth accessible child of the containing accessible object. + * + * @param i the child to grab, zero-based + * @return the accessible child, or null + */ + public Accessible getAccessibleChild(int i) + { + synchronized (getTreeLock ()) + { + if (component == null) + return null; + int index = -1; + while (i >= 0 && ++index < component.length) + if (component[index] instanceof Accessible) + i--; + if (i < 0) + return (Accessible) component[index]; + return null; + } + } + + /** + * Return the accessible child located at point (in the parent's + * coordinates), if one exists. + * + * @param p the point to look at + * + * @return an accessible object at that point, or null + * + * @throws NullPointerException if p is null + */ + public Accessible getAccessibleAt(Point p) + { + Component c = getComponentAt(p.x, p.y); + return c != Container.this && c instanceof Accessible ? (Accessible) c + : null; + } + + /** + * This class fires a <code>PropertyChange</code> listener, if registered, + * when children are added or removed from the enclosing accessible object. + * + * @author Eric Blake (ebb9@email.byu.edu) + * + * @since 1.3 + */ + protected class AccessibleContainerHandler implements ContainerListener + { + /** + * Default constructor. + */ + protected AccessibleContainerHandler() + { + } + + /** + * Fired when a component is added; forwards to the PropertyChange + * listener. + * + * @param e the container event for adding + */ + public void componentAdded(ContainerEvent e) + { + AccessibleAWTContainer.this.firePropertyChange + (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild()); + } + + /** + * Fired when a component is removed; forwards to the PropertyChange + * listener. + * + * @param e the container event for removing + */ + public void componentRemoved(ContainerEvent e) + { + AccessibleAWTContainer.this.firePropertyChange + (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null); + } + } // class AccessibleContainerHandler + } // class AccessibleAWTContainer +} // class Container + +/** + * There is a helper class implied from stack traces called + * LightweightDispatcher, but since it is not part of the public API, + * rather than mimic it exactly we write something which does "roughly + * the same thing". + */ + +class LightweightDispatcher implements Serializable +{ + private static final long serialVersionUID = 5184291520170872969L; + private Container nativeContainer; + private Cursor nativeCursor; + private long eventMask; + + private transient Component mouseEventTarget; + private transient Component pressedComponent; + private transient Component lastComponentEntered; + private transient Component tempComponent; + private transient int pressCount; + + LightweightDispatcher(Container c) + { + nativeContainer = c; + } + + void acquireComponentForMouseEvent(MouseEvent me) + { + int x = me.getX (); + int y = me.getY (); + + // Find the candidate which should receive this event. + Component parent = nativeContainer; + Component candidate = null; + Point p = me.getPoint(); + while (candidate == null && parent != null) + { + candidate = + SwingUtilities.getDeepestComponentAt(parent, p.x, p.y); + if (candidate == null || (candidate.eventMask & me.getID()) == 0) + { + candidate = null; + p = SwingUtilities.convertPoint(parent, p.x, p.y, parent.parent); + parent = parent.parent; + } + } + + // If the only candidate we found was the native container itself, + // don't dispatch any event at all. We only care about the lightweight + // children here. + if (candidate == nativeContainer) + candidate = null; + + // If our candidate is new, inform the old target we're leaving. + if (lastComponentEntered != null + && lastComponentEntered.isShowing() + && lastComponentEntered != candidate) + { + // Old candidate could have been removed from + // the nativeContainer so we check first. + if (SwingUtilities.isDescendingFrom(lastComponentEntered, nativeContainer)) + { + Point tp = + SwingUtilities.convertPoint(nativeContainer, + x, y, lastComponentEntered); + MouseEvent exited = new MouseEvent (lastComponentEntered, + MouseEvent.MOUSE_EXITED, + me.getWhen (), + me.getModifiersEx (), + tp.x, tp.y, + me.getClickCount (), + me.isPopupTrigger (), + me.getButton ()); + tempComponent = lastComponentEntered; + lastComponentEntered = null; + tempComponent.dispatchEvent(exited); + } + lastComponentEntered = null; + } + // If we have a candidate, maybe enter it. + if (candidate != null) + { + mouseEventTarget = candidate; + if (candidate.isLightweight() + && candidate.isShowing() + && candidate != nativeContainer + && candidate != lastComponentEntered) + { + lastComponentEntered = mouseEventTarget; + Point cp = SwingUtilities.convertPoint(nativeContainer, + x, y, lastComponentEntered); + MouseEvent entered = new MouseEvent (lastComponentEntered, + MouseEvent.MOUSE_ENTERED, + me.getWhen (), + me.getModifiersEx (), + cp.x, cp.y, + me.getClickCount (), + me.isPopupTrigger (), + me.getButton ()); + lastComponentEntered.dispatchEvent (entered); + } + } + + if (me.getID() == MouseEvent.MOUSE_RELEASED + || me.getID() == MouseEvent.MOUSE_PRESSED && pressCount > 0 + || me.getID() == MouseEvent.MOUSE_DRAGGED) + // If any of the following events occur while a button is held down, + // they should be dispatched to the same component to which the + // original MOUSE_PRESSED event was dispatched: + // - MOUSE_RELEASED + // - MOUSE_PRESSED: another button pressed while the first is held down + // - MOUSE_DRAGGED + if (SwingUtilities.isDescendingFrom(pressedComponent, nativeContainer)) + mouseEventTarget = pressedComponent; + else if (me.getID() == MouseEvent.MOUSE_CLICKED) + { + // Don't dispatch CLICKED events whose target is not the same as the + // target for the original PRESSED event. + if (candidate != pressedComponent) + mouseEventTarget = null; + else if (pressCount == 0) + pressedComponent = null; + } + } + + boolean handleEvent(AWTEvent e) + { + if (e instanceof MouseEvent) + { + MouseEvent me = (MouseEvent) e; + + acquireComponentForMouseEvent(me); + + // Avoid dispatching ENTERED and EXITED events twice. + if (mouseEventTarget != null + && mouseEventTarget.isShowing() + && e.getID() != MouseEvent.MOUSE_ENTERED + && e.getID() != MouseEvent.MOUSE_EXITED) + { + MouseEvent newEvt = + SwingUtilities.convertMouseEvent(nativeContainer, me, + mouseEventTarget); + mouseEventTarget.dispatchEvent(newEvt); + + switch (e.getID()) + { + case MouseEvent.MOUSE_PRESSED: + if (pressCount++ == 0) + pressedComponent = mouseEventTarget; + break; + + case MouseEvent.MOUSE_RELEASED: + // Clear our memory of the original PRESSED event, only if + // we're not expecting a CLICKED event after this. If + // there is a CLICKED event after this, it will do clean up. + if (--pressCount == 0 + && mouseEventTarget != pressedComponent) + pressedComponent = null; + break; + } + if (newEvt.isConsumed()) + e.consume(); + } + } + + return e.isConsumed(); + } + +} // class LightweightDispatcher diff --git a/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java b/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java new file mode 100644 index 0000000..152482c --- /dev/null +++ b/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java @@ -0,0 +1,413 @@ +/* ContainerOrderFocusTraversalPolicy.java -- + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.io.Serializable; + +/** + * ContainerOrderFocusTraversalPolicy defines a focus traversal order + * based on the order in which Components were packed in a Container. + * This policy performs a pre-order traversal of the Component + * hierarchy starting from a given focus cycle root. Portions of the + * hierarchy that are not visible and displayable are skipped. + * + * By default, this policy transfers focus down-cycle implicitly. + * That is, if a forward traversal is requested on a focus cycle root + * and the focus cycle root has focusable children, the focus will + * automatically be transfered down to the lower focus cycle. + * + * The default implementation of accept accepts only Components that + * are visible, displayable, enabled and focusable. Derived classes + * can override these acceptance criteria by overriding accept. + * + * @author Michael Koch + * @author Thomas Fitzsimmons (fitzsim@redhat.com) + * @since 1.4 + */ +public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy + implements Serializable +{ + /** + * Compatible to JDK 1.4+ + */ + static final long serialVersionUID = 486933713763926351L; + + /** + * True if implicit down cycling is enabled. + */ + private boolean implicitDownCycleTraversal = true; + + /** + * Creates the <code>ContainerOrderFocusTraversalPolicy</code> object. + */ + public ContainerOrderFocusTraversalPolicy () + { + // Nothing to do here + } + + /** + * Returns the Component that should receive the focus after current. + * root must be a focus cycle root of current. + * + * @param root a focus cycle root of current + * @param current a (possibly indirect) child of root, or root itself + * + * @return the next Component in the focus traversal order for root, + * or null if no acceptable Component exists. + * + * @exception IllegalArgumentException If root is not a focus cycle + * root of current, or if either root or current is null. + */ + public Component getComponentAfter (Container root, Component current) + { + if (root == null) + throw new IllegalArgumentException ("focus cycle root is null"); + if (current == null) + throw new IllegalArgumentException ("current component is null"); + + if (!root.isFocusCycleRoot ()) + throw new IllegalArgumentException ("root is not a focus cycle root"); + + Container ancestor = current.getFocusCycleRootAncestor (); + Container prevAncestor = ancestor; + while (ancestor != root) + { + ancestor = current.getFocusCycleRootAncestor (); + if (ancestor == prevAncestor) + { + // We've reached the top focus cycle root ancestor. Check + // if it is root. + if (ancestor != root) + throw new IllegalArgumentException ("the given container is not" + + " a focus cycle root of the" + + " current component"); + else + break; + } + prevAncestor = ancestor; + } + + // FIXME: is this the right thing to do here? It moves the context + // for traversal up one focus traversal cycle. We'll need a test + // for this. + if ((Component) root == current) + root = current.getFocusCycleRootAncestor (); + + // Check if we've reached the top of the component hierarchy. If + // so then we want to loop around to the first component in the + // focus traversal cycle. + if (current instanceof Window) + return getFirstComponent ((Container) current); + + Container parent = current.getParent (); + + synchronized (parent.getTreeLock ()) + { + Component[] components = parent.getComponents (); + int componentIndex = 0; + int numComponents = parent.getComponentCount (); + + // Find component's index. + for (int i = 0; i < numComponents; i++) + { + if (components[i] == current) + componentIndex = i; + } + + // Search forward for the next acceptable component. + for (int i = componentIndex + 1; i < numComponents; i++) + { + if (accept (components[i])) + return components[i]; + + if (components[i] instanceof Container) + { + Component result = getFirstComponent ((Container) components[i]); + + if (result != null + && implicitDownCycleTraversal) + return result; + } + } + + // No focusable components after current in its Container. So go + // to the next Component after current's Container (parent). + Component result = getComponentAfter (root, parent); + + return result; + } + } + + /** + * Returns the Component that should receive the focus before + * <code>current</code>. <code>root</code> must be a focus cycle + * root of current. + * + * @param root a focus cycle root of current + * @param current a (possibly indirect) child of root, or root itself + * + * @return the previous Component in the focus traversal order for + * root, or null if no acceptable Component exists. + * + * @exception IllegalArgumentException If root is not a focus cycle + * root of current, or if either root or current is null. + */ + public Component getComponentBefore (Container root, Component current) + { + if (root == null) + throw new IllegalArgumentException ("focus cycle root is null"); + if (current == null) + throw new IllegalArgumentException ("current component is null"); + + if (!root.isFocusCycleRoot ()) + throw new IllegalArgumentException ("root is not a focus cycle root"); + + Container ancestor = current.getFocusCycleRootAncestor (); + Container prevAncestor = ancestor; + while (ancestor != root) + { + ancestor = current.getFocusCycleRootAncestor (); + if (ancestor == prevAncestor) + { + // We've reached the top focus cycle root ancestor. Check + // if it is root. + if (ancestor != root) + throw new IllegalArgumentException ("the given container is not" + + " a focus cycle root of the" + + " current component"); + else + break; + } + prevAncestor = ancestor; + } + + // FIXME: is this the right thing to do here? It moves the context + // for traversal up one focus traversal cycle. We'll need a test + // for this. + if ((Component) root == current) + root = current.getFocusCycleRootAncestor (); + + // Check if we've reached the top of the component hierarchy. If + // so then we want to loop around to the last component in the + // focus traversal cycle. + if (current instanceof Window) + return getLastComponent ((Container) current); + + Container parent = current.getParent (); + + synchronized (parent.getTreeLock ()) + { + Component[] components = parent.getComponents (); + int componentIndex = 0; + int numComponents = parent.getComponentCount (); + + // Find component's index. + for (int i = 0; i < numComponents; i++) + { + if (components[i] == current) + componentIndex = i; + } + + // Search backward for the next acceptable component. + for (int i = componentIndex - 1; i >= 0; i--) + { + if (accept (components[i])) + return components[i]; + + if (components[i] instanceof Container) + { + Component result = getLastComponent ((Container) components[i]); + + if (result != null) + return result; + } + } + + // No focusable components before current in its Container. So go + // to the previous Component before current's Container (parent). + Component result = getComponentBefore (root, parent); + + return result; + } + } + + /** + * Returns the first Component of root that should receive the focus. + * + * @param root a focus cycle root + * + * @return the first Component in the focus traversal order for + * root, or null if no acceptable Component exists. + * + * @exception IllegalArgumentException If root is null. + */ + public Component getFirstComponent(Container root) + { + if (root == null) + throw new IllegalArgumentException (); + + if (!root.isVisible () + || !root.isDisplayable ()) + return null; + + if (accept (root)) + return root; + + Component[] componentArray = root.getComponents (); + + for (int i = 0; i < componentArray.length; i++) + { + Component component = componentArray [i]; + + if (accept (component)) + return component; + + if (component instanceof Container) + { + Component result = getFirstComponent ((Container) component); + + if (result != null) + return result; + } + } + + return null; + } + + /** + * Returns the last Component of root that should receive the focus. + * + * @param root a focus cycle root + * + * @return the last Component in the focus traversal order for + * root, or null if no acceptable Component exists. + * + * @exception IllegalArgumentException If root is null. + */ + public Component getLastComponent (Container root) + { + if (root == null) + throw new IllegalArgumentException (); + + if (!root.isVisible () + || !root.isDisplayable ()) + return null; + + if (accept (root)) + return root; + + Component[] componentArray = root.getComponents (); + + for (int i = componentArray.length - 1; i >= 0; i--) + { + Component component = componentArray [i]; + + if (accept (component)) + return component; + + if (component instanceof Container) + { + Component result = getLastComponent ((Container) component); + + if (result != null) + return result; + } + } + + return null; + } + + /** + * Returns the default Component of root that should receive the focus. + * + * @param root a focus cycle root + * + * @return the default Component in the focus traversal order for + * root, or null if no acceptable Component exists. + * + * @exception IllegalArgumentException If root is null. + */ + public Component getDefaultComponent (Container root) + { + return getFirstComponent (root); + } + + /** + * Set whether or not implicit down cycling is enabled. If it is, + * then initiating a forward focus traversal operation onto a focus + * cycle root, the focus will be implicitly transferred into the + * root container's focus cycle. + * + * @param value the setting for implicit down cycling + */ + public void setImplicitDownCycleTraversal (boolean value) + { + implicitDownCycleTraversal = value; + } + + /** + * Check whether or not implicit down cycling is enabled. If it is, + * then initiating a forward focus traversal operation onto a focus + * cycle root, the focus will be implicitly transferred into the + * root container's focus cycle. + * + * @return true if the focus will be transferred down-cycle + * implicitly + */ + public boolean getImplicitDownCycleTraversal () + { + return implicitDownCycleTraversal; + } + + /** + * Check whether the given Component is an acceptable target for the + * keyboard input focus. + * + * @param current the Component to check + * + * @return true if current is acceptable, false otherwise + */ + protected boolean accept (Component current) + { + return (current.visible + && current.isDisplayable () + && current.enabled + && current.focusable); + } +} diff --git a/libjava/classpath/java/awt/Cursor.java b/libjava/classpath/java/awt/Cursor.java new file mode 100644 index 0000000..48a63f0 --- /dev/null +++ b/libjava/classpath/java/awt/Cursor.java @@ -0,0 +1,224 @@ +/* Copyright (C) 1999, 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This class represents various predefined cursor types. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class Cursor implements java.io.Serializable +{ + static final long serialVersionUID = 8028237497568985504L; + + /** + * Constant for the system default cursor type + */ + public static final int DEFAULT_CURSOR = 0; + + /** + * Constant for a cross-hair cursor. + */ + public static final int CROSSHAIR_CURSOR = 1; + + /** + * Constant for a cursor over a text field. + */ + public static final int TEXT_CURSOR = 2; + + /** + * Constant for a cursor to display while waiting for an action to complete. + */ + public static final int WAIT_CURSOR = 3; + + /** + * Cursor used over SW corner of window decorations. + */ + public static final int SW_RESIZE_CURSOR = 4; + + /** + * Cursor used over SE corner of window decorations. + */ + public static final int SE_RESIZE_CURSOR = 5; + + /** + * Cursor used over NW corner of window decorations. + */ + public static final int NW_RESIZE_CURSOR = 6; + + /** + * Cursor used over NE corner of window decorations. + */ + public static final int NE_RESIZE_CURSOR = 7; + + /** + * Cursor used over N edge of window decorations. + */ + public static final int N_RESIZE_CURSOR = 8; + + /** + * Cursor used over S edge of window decorations. + */ + public static final int S_RESIZE_CURSOR = 9; + + /** + * Cursor used over W edge of window decorations. + */ + public static final int W_RESIZE_CURSOR = 10; + + /** + * Cursor used over E edge of window decorations. + */ + public static final int E_RESIZE_CURSOR = 11; + + /** + * Constant for a hand cursor. + */ + public static final int HAND_CURSOR = 12; + + /** + * Constant for a cursor used during window move operations. + */ + public static final int MOVE_CURSOR = 13; + + public static final int CUSTOM_CURSOR = 0xFFFFFFFF; + + private static final int PREDEFINED_COUNT = 14; + + protected static Cursor[] predefined = new Cursor[PREDEFINED_COUNT]; + protected String name; + + /** + * @serial The numeric id of this cursor. + */ + int type; + + /** + * Initializes a new instance of <code>Cursor</code> with the specified + * type. + * + * @param type The cursor type. + * + * @exception IllegalArgumentException If the specified cursor type is invalid + */ + public Cursor(int type) + { + if (type < 0 || type >= PREDEFINED_COUNT) + throw new IllegalArgumentException ("invalid cursor " + type); + + this.type = type; + // FIXME: lookup and set name? + } + + /** This constructor is used internally only. + * Application code should call Toolkit.createCustomCursor(). + */ + protected Cursor(String name) + { + this.name = name; + this.type = CUSTOM_CURSOR; + } + + /** + * Returns an instance of <code>Cursor</code> for one of the specified + * predetermined types. + * + * @param type The type contant from this class. + * + * @return The requested predefined cursor. + * + * @exception IllegalArgumentException If the constant is not one of the + * predefined cursor type constants from this class. + */ + public static Cursor getPredefinedCursor(int type) + { + if (type < 0 || type >= PREDEFINED_COUNT) + throw new IllegalArgumentException ("invalid cursor " + type); + if (predefined[type] == null) + predefined[type] = new Cursor(type); + return predefined[type]; + } + + /** + * Retrieves the system specific custom Cursor named Cursor names are, + * for example: "Invalid.16x16". + * + * @exception AWTException + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true. + */ + public static Cursor getSystemCustomCursor(String name) + throws AWTException + { + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException (); + + // FIXME + return null; + } + + /** + * Returns an instance of the system default cursor type. + * + * @return The system default cursor. + */ + public static Cursor getDefaultCursor() + { + return getPredefinedCursor(DEFAULT_CURSOR); + } + + /** + * Returns the numeric type identifier for this cursor. + * + * @return The cursor id. + */ + public int getType() + { + return type; + } + + public String getName() + { + return name; + } + + public String toString() + { + return (this.getClass() + "[" + getName() + "]"); + } +} diff --git a/libjava/classpath/java/awt/DefaultFocusTraversalPolicy.java b/libjava/classpath/java/awt/DefaultFocusTraversalPolicy.java new file mode 100644 index 0000000..46b56d3 --- /dev/null +++ b/libjava/classpath/java/awt/DefaultFocusTraversalPolicy.java @@ -0,0 +1,109 @@ +/* DefaultFocusTraversalPolicy.java -- + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * DefaultFocusTraversalPolicy is the default focus traversal policy + * used by Containers. + * + * This policy sharpens ContainerOrderFocusTraversalPolicy's + * acceptance criteria, to reject those Components that have + * unfocusable peers. Despite this extra strictness, this policy will + * always accept a Component that has explicitly been set focusable by + * any means. + * + * This AWT implementation assumes that the peers of the following + * Components are not focusable: Canvas, Panel, Label, ScrollPane, + * Scrollbar, Window, and any lightweight Component. + * + * A Component's focusability is independent of the focusability of + * its peer. + * + * @author Thomas Fitzsimmons (fitzsim@redhat.com) + * @since 1.4 + */ +public class DefaultFocusTraversalPolicy + extends ContainerOrderFocusTraversalPolicy +{ + /** + * Construct a default focus traversal policy. + */ + public DefaultFocusTraversalPolicy () + { + } + + /** + * Check whether a given Component would be acceptable as a focus + * owner. The Component must be displayable, visible and enabled to + * be acceptable. If the Component's focus traversability has been + * overridden, by overriding Component.isFocusTraversable or + * Component.isFocusable, or by calling Component.setFocusable, then + * the Component will be accepted if it is focusable. If the + * Component uses the default focus traversable behaviour, then + * <code>comp</code> will always be rejected if it is a Canvas, + * Panel, Label, ScrollPane, Scrollbar, Window or lightweight + * Component. + * + * @param comp the Component to check + * + * @return true if the Component is an acceptable target for + * keyboard input focus, false otherwise + */ + protected boolean accept (Component comp) + { + if (comp.visible + && comp.isDisplayable () + && comp.enabled) + { + if (comp.isFocusTraversableOverridden != 0 + && (comp.isFocusTraversable () || comp.isFocusable())) + return true; + + if (!(comp instanceof Canvas + || comp instanceof Panel + || comp instanceof Label + || comp instanceof ScrollPane + || comp instanceof Scrollbar + || comp instanceof Window + || comp.isLightweight ())) + return true; + } + return false; + } +} diff --git a/libjava/classpath/java/awt/DefaultKeyboardFocusManager.java b/libjava/classpath/java/awt/DefaultKeyboardFocusManager.java new file mode 100644 index 0000000..f53cc5e --- /dev/null +++ b/libjava/classpath/java/awt/DefaultKeyboardFocusManager.java @@ -0,0 +1,536 @@ +/* DefaultKeyboardFocusManager.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ActionEvent; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowEvent; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +// FIXME: finish documentation +public class DefaultKeyboardFocusManager extends KeyboardFocusManager +{ + /** + * This class models a request to delay the dispatch of events that + * arrive after a certain time, until a certain component becomes + * the focus owner. + */ + private class EventDelayRequest implements Comparable + { + /** A {@link java.util.List} of {@link java.awt.event.KeyEvent}s + that are being delayed, pending this request's {@link + Component} receiving the keyboard focus. */ + private LinkedList enqueuedKeyEvents = new LinkedList (); + + /** An event timestamp. All events that arrive after this time + should be queued in the {@link #enqueuedKeyEvents} {@link + java.util.List}. */ + public long timestamp; + /** When this {@link Component} becomes focused, all events + between this EventDelayRequest and the next one in will be + dispatched from {@link #enqueuedKeyEvents}. */ + public Component focusedComp; + + /** + * Construct a new EventDelayRequest. + * + * @param timestamp events that arrive after this time will be + * delayed + * @param focusedComp the Component that needs to receive focus + * before events are dispatched + */ + public EventDelayRequest (long timestamp, Component focusedComp) + { + this.timestamp = timestamp; + this.focusedComp = focusedComp; + } + + public int compareTo (Object o) + { + if (!(o instanceof EventDelayRequest)) + throw new ClassCastException (); + + EventDelayRequest request = (EventDelayRequest) o; + + if (request.timestamp < timestamp) + return -1; + else if (request.timestamp == timestamp) + return 0; + else + return 1; + } + + public boolean equals (Object o) + { + if (!(o instanceof EventDelayRequest) || o == null) + return false; + + EventDelayRequest request = (EventDelayRequest) o; + + return (request.timestamp == timestamp + && request.focusedComp == focusedComp); + } + + public void enqueueEvent (KeyEvent e) + { + KeyEvent last = (KeyEvent) enqueuedKeyEvents.getLast (); + if (last != null && e.getWhen () < last.getWhen ()) + throw new RuntimeException ("KeyEvents enqueued out-of-order"); + + if (e.getWhen () <= timestamp) + throw new RuntimeException ("KeyEvents enqueued before starting timestamp"); + + enqueuedKeyEvents.add (e); + } + + public void dispatchEvents () + { + int size = enqueuedKeyEvents.size (); + for (int i = 0; i < size; i++) + { + KeyEvent e = (KeyEvent) enqueuedKeyEvents.remove (0); + dispatchKeyEvent (e); + } + } + + public void discardEvents () + { + enqueuedKeyEvents.clear (); + } + } + + /** + * This flag indicates for which focus traversal key release event we + * possibly wait, before letting any more KEY_TYPED events through. + */ + private AWTKeyStroke waitForKeyStroke = null; + + /** The {@link java.util.SortedSet} of current {@link + #EventDelayRequest}s. */ + private SortedSet delayRequests = new TreeSet (); + + public DefaultKeyboardFocusManager () + { + } + + public boolean dispatchEvent (AWTEvent e) + { + if (e instanceof WindowEvent) + { + Window target = (Window) e.getSource (); + + if (e.id == WindowEvent.WINDOW_ACTIVATED) + setGlobalActiveWindow (target); + else if (e.id == WindowEvent.WINDOW_GAINED_FOCUS) + setGlobalFocusedWindow (target); + else if (e.id != WindowEvent.WINDOW_LOST_FOCUS + && e.id != WindowEvent.WINDOW_DEACTIVATED) + return false; + + redispatchEvent(target, e); + return true; + } + else if (e instanceof FocusEvent) + { + Component target = (Component) e.getSource (); + + if (e.id == FocusEvent.FOCUS_GAINED) + { + if (! (target instanceof Window)) + { + if (((FocusEvent) e).isTemporary ()) + setGlobalFocusOwner (target); + else + setGlobalPermanentFocusOwner (target); + } + + // Keep track of this window's focus owner. + + // Find the target Component's top-level ancestor. target + // may be a window. + Container parent = target.getParent (); + + while (parent != null + && !(parent instanceof Window)) + parent = parent.getParent (); + + // If the parent is null and target is not a window, then target is an + // unanchored component and so we don't want to set the focus owner. + if (! (parent == null && ! (target instanceof Window))) + { + Window toplevel = parent == null ? + (Window) target : (Window) parent; + + Component focusOwner = getFocusOwner (); + if (focusOwner != null + && ! (focusOwner instanceof Window)) + toplevel.setFocusOwner (focusOwner); + } + } + else if (e.id == FocusEvent.FOCUS_LOST) + { + if (((FocusEvent) e).isTemporary ()) + setGlobalFocusOwner (null); + else + setGlobalPermanentFocusOwner (null); + } + + redispatchEvent(target, e); + + return true; + } + else if (e instanceof KeyEvent) + { + // Loop through all registered KeyEventDispatchers, giving + // each a chance to handle this event. + Iterator i = getKeyEventDispatchers().iterator(); + + while (i.hasNext ()) + { + KeyEventDispatcher dispatcher = (KeyEventDispatcher) i.next (); + if (dispatcher.dispatchKeyEvent ((KeyEvent) e)) + return true; + } + + // processKeyEvent checks if this event represents a focus + // traversal key stroke. + Component focusOwner = getGlobalPermanentFocusOwner (); + + if (focusOwner != null) + processKeyEvent (focusOwner, (KeyEvent) e); + + if (e.isConsumed ()) + return true; + + if (enqueueKeyEvent ((KeyEvent) e)) + // This event was enqueued for dispatch at a later time. + return true; + else + // This event wasn't handled by any of the registered + // KeyEventDispatchers, and wasn't enqueued for dispatch + // later, so send it to the default dispatcher. + return dispatchKeyEvent ((KeyEvent) e); + } + + return false; + } + + private boolean enqueueKeyEvent (KeyEvent e) + { + Iterator i = delayRequests.iterator (); + boolean oneEnqueued = false; + while (i.hasNext ()) + { + EventDelayRequest request = (EventDelayRequest) i.next (); + if (e.getWhen () > request.timestamp) + { + request.enqueueEvent (e); + oneEnqueued = true; + } + } + return oneEnqueued; + } + + public boolean dispatchKeyEvent (KeyEvent e) + { + Component focusOwner = getGlobalPermanentFocusOwner (); + + if (focusOwner != null) + redispatchEvent(focusOwner, e); + + // Loop through all registered KeyEventPostProcessors, giving + // each a chance to process this event. + Iterator i = getKeyEventPostProcessors().iterator(); + + while (i.hasNext ()) + { + KeyEventPostProcessor processor = (KeyEventPostProcessor) i.next (); + if (processor.postProcessKeyEvent ((KeyEvent) e)) + return true; + } + + // The event hasn't been consumed yet. Check if it is an + // MenuShortcut. + if (postProcessKeyEvent (e)) + return true; + + // Always return true. + return true; + } + + public boolean postProcessKeyEvent (KeyEvent e) + { + // Check if this event represents a menu shortcut. + + // MenuShortcuts are activated by Ctrl- KeyEvents, only on KEY_PRESSED. + int modifiers = e.getModifiersEx (); + if (e.getID() == KeyEvent.KEY_PRESSED + && (modifiers & KeyEvent.CTRL_DOWN_MASK) != 0) + { + Window focusedWindow = getGlobalFocusedWindow (); + if (focusedWindow instanceof Frame) + { + MenuBar menubar = ((Frame) focusedWindow).getMenuBar (); + + if (menubar != null) + { + // If there's a menubar, loop through all menu items, + // checking whether each one has a shortcut, and if + // so, whether this key event should activate it. + int numMenus = menubar.getMenuCount (); + + for (int i = 0; i < numMenus; i++) + { + Menu menu = menubar.getMenu (i); + int numItems = menu.getItemCount (); + + for (int j = 0; j < numItems; j++) + { + MenuItem item = menu.getItem (j); + MenuShortcut shortcut = item.getShortcut (); + + if (item.isEnabled() && shortcut != null) + { + // Dispatch a new ActionEvent if: + // + // a) this is a Shift- KeyEvent, and the + // shortcut requires the Shift modifier + // + // or, b) this is not a Shift- KeyEvent, and the + // shortcut does not require the Shift + // modifier. + if (shortcut.getKey () == e.getKeyCode () + && ((shortcut.usesShiftModifier () + && (modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0) + || (! shortcut.usesShiftModifier () + && (modifiers & KeyEvent.SHIFT_DOWN_MASK) == 0))) + { + item.dispatchEvent (new ActionEvent (item, + ActionEvent.ACTION_PERFORMED, + item.getActionCommand (), + modifiers)); + // The event was dispatched. + return true; + } + } + } + } + } + } + } + return false; + } + + public void processKeyEvent (Component comp, KeyEvent e) + { + AWTKeyStroke eventKeystroke = AWTKeyStroke.getAWTKeyStrokeForEvent (e); + // For every focus traversal keystroke, we need to also consume + // the other two key event types for the same key (e.g. if + // KEY_PRESSED TAB is a focus traversal keystroke, we also need to + // consume KEY_RELEASED and KEY_TYPED TAB key events). + // consuming KEY_RELEASED is easy, because their keyCodes matches + // the KEY_PRESSED event. Consuming the intermediate KEY_TYPED is + // very difficult because their is no clean way that we can know + // which KEY_TYPED belongs to a focusTraversalKey and which not. + // To address this problem we swallow every KEY_TYPE between the + // KEY_PRESSED event that matches a focusTraversalKey and the + // corresponding KEY_RELEASED. + AWTKeyStroke oppositeKeystroke = AWTKeyStroke.getAWTKeyStroke (e.getKeyCode (), + e.getModifiersEx (), + !(e.id == KeyEvent.KEY_RELEASED)); + + // Here we check if we are currently waiting for a KEY_RELEASED and + // swallow all KeyEvents that are to be delivered in between. This + // should only be the KEY_TYPED events that correspond to the + // focusTraversalKey's KEY_PRESSED event + if (waitForKeyStroke != null) + { + if (eventKeystroke.equals(waitForKeyStroke)) + // release this lock + waitForKeyStroke = null; + + // as long as we are waiting for the KEY_RELEASED, we swallow every + // KeyEvent, including the KEY_RELEASED + e.consume(); + return; + } + + Set forwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); + Set backwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); + Set upKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); + Set downKeystrokes = null; + if (comp instanceof Container) + downKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); + + if (forwardKeystrokes.contains (eventKeystroke)) + { + waitForKeyStroke = oppositeKeystroke; + focusNextComponent (comp); + e.consume (); + } + else if (backwardKeystrokes.contains (eventKeystroke)) + { + waitForKeyStroke = oppositeKeystroke; + focusPreviousComponent (comp); + e.consume (); + } + else if (upKeystrokes.contains (eventKeystroke)) + { + waitForKeyStroke = oppositeKeystroke; + upFocusCycle (comp); + e.consume (); + } + else if (comp instanceof Container + && downKeystrokes.contains (eventKeystroke)) + { + waitForKeyStroke = oppositeKeystroke; + downFocusCycle ((Container) comp); + e.consume (); + } + } + + protected void enqueueKeyEvents (long after, Component untilFocused) + { + delayRequests.add (new EventDelayRequest (after, untilFocused)); + } + + protected void dequeueKeyEvents (long after, Component untilFocused) + { + // FIXME: need synchronization on delayRequests and enqueuedKeyEvents. + + // Remove the KeyEvent with the oldest timestamp, which should be + // the first element in the SortedSet. + if (after < 0) + { + int size = delayRequests.size (); + if (size > 0) + delayRequests.remove (delayRequests.first ()); + } + else + { + EventDelayRequest template = new EventDelayRequest (after, untilFocused); + if (delayRequests.contains (template)) + { + EventDelayRequest actual = (EventDelayRequest) delayRequests.tailSet (template).first (); + delayRequests.remove (actual); + actual.dispatchEvents (); + } + } + } + + protected void discardKeyEvents (Component comp) + { + // FIXME: need synchronization on delayRequests and enqueuedKeyEvents. + + Iterator i = delayRequests.iterator (); + + while (i.hasNext ()) + { + EventDelayRequest request = (EventDelayRequest) i.next (); + + if (request.focusedComp == comp + || (comp instanceof Container + && ((Container) comp).isAncestorOf (request.focusedComp))) + request.discardEvents (); + } + } + + public void focusPreviousComponent (Component comp) + { + Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp; + Container focusCycleRoot = focusComp.getFocusCycleRootAncestor (); + FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy (); + + Component previous = policy.getComponentBefore (focusCycleRoot, focusComp); + if (previous != null) + previous.requestFocusInWindow (); + } + + public void focusNextComponent (Component comp) + { + Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp; + Container focusCycleRoot = focusComp.getFocusCycleRootAncestor (); + FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy (); + + Component next = policy.getComponentAfter (focusCycleRoot, focusComp); + if (next != null) + next.requestFocusInWindow (); + } + + public void upFocusCycle (Component comp) + { + Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp; + Container focusCycleRoot = focusComp.getFocusCycleRootAncestor (); + + if (focusCycleRoot instanceof Window) + { + FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy (); + Component defaultComponent = policy.getDefaultComponent (focusCycleRoot); + if (defaultComponent != null) + defaultComponent.requestFocusInWindow (); + } + else + { + Container parentFocusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor (); + + focusCycleRoot.requestFocusInWindow (); + setGlobalCurrentFocusCycleRoot (parentFocusCycleRoot); + } + } + + public void downFocusCycle (Container cont) + { + if (cont == null) + return; + + if (cont.isFocusCycleRoot (cont)) + { + FocusTraversalPolicy policy = cont.getFocusTraversalPolicy (); + Component defaultComponent = policy.getDefaultComponent (cont); + if (defaultComponent != null) + defaultComponent.requestFocusInWindow (); + setGlobalCurrentFocusCycleRoot (cont); + } + } +} // class DefaultKeyboardFocusManager diff --git a/libjava/classpath/java/awt/Dialog.java b/libjava/classpath/java/awt/Dialog.java new file mode 100644 index 0000000..d3eb975 --- /dev/null +++ b/libjava/classpath/java/awt/Dialog.java @@ -0,0 +1,553 @@ +/* Dialog.java -- An AWT dialog box + Copyright (C) 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.peer.DialogPeer; + +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +/** + * A dialog box widget class. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Tom Tromey (tromey@redhat.com) + */ +public class Dialog extends Window +{ + +/* + * Static Variables + */ + +// Serialization constant +private static final long serialVersionUID = 5920926903803293709L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial Indicates whether or not this dialog box is modal. + */ +private boolean modal; + +/** + * @serial Indicates whether or not this dialog box is resizable. + */ +private boolean resizable = true; + +/** + * @serial The title string for this dialog box, which can be + * <code>null</code>. + */ +private String title; + +/** + * This field indicates whether the dialog is undecorated or not. + */ +private boolean undecorated = false; + +/** + * Indicates that we are blocked for modality in show + */ +private boolean blocked = false; + +/** + * Secondary EventQueue to handle AWT events while + * we are blocked for modality in show + */ +private EventQueue eq2 = null; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>Dialog</code> with the specified + * parent, that is resizable and not modal, and which has no title. + * + * @param parent The parent frame of this dialog box. + * + * @exception IllegalArgumentException If the owner's GraphicsConfiguration + * is not from a screen device, or if owner is null. This exception is always + * thrown when GraphicsEnvironment.isHeadless() returns true. + */ +public +Dialog(Frame parent) +{ + this(parent, "", false); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Dialog</code> with the specified + * parent and modality, that is resizable and which has no title. + * + * @param parent The parent frame of this dialog box. + * @param modal <code>true</code> if this dialog box is modal, + * <code>false</code> otherwise. + * + * @exception IllegalArgumentException If the owner's GraphicsConfiguration + * is not from a screen device, or if owner is null. This exception is always + * thrown when GraphicsEnvironment.isHeadless() returns true. + */ +public +Dialog(Frame parent, boolean modal) +{ + this(parent, "", modal); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Dialog</code> with the specified + * parent, that is resizable and not modal, and which has the specified + * title. + * + * @param parent The parent frame of this dialog box. + * @param title The title string for this dialog box. + * + * @exception IllegalArgumentException If the owner's GraphicsConfiguration + * is not from a screen device, or if owner is null. This exception is always + * thrown when GraphicsEnvironment.isHeadless() returns true. + */ +public +Dialog(Frame parent, String title) +{ + this(parent, title, false); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Dialog</code> with the specified, + * parent, title, and modality, that is resizable. + * + * @param parent The parent frame of this dialog box. + * @param title The title string for this dialog box. + * @param modal <code>true</code> if this dialog box is modal, + * <code>false</code> otherwise. + * + * @exception IllegalArgumentException If owner is null or + * GraphicsEnvironment.isHeadless() returns true. + */ +public +Dialog(Frame parent, String title, boolean modal) +{ + this (parent, title, modal, parent.getGraphicsConfiguration ()); +} + +/** + * Initializes a new instance of <code>Dialog</code> with the specified, + * parent, title, modality and <code>GraphicsConfiguration</code>, + * that is resizable. + * + * @param parent The parent frame of this dialog box. + * @param title The title string for this dialog box. + * @param modal <code>true</code> if this dialog box is modal, + * <code>false</code> otherwise. + * @param gc The <code>GraphicsConfiguration</code> object to use. + * + * @exception IllegalArgumentException If owner is null, the + * GraphicsConfiguration is not a screen device or + * GraphicsEnvironment.isHeadless() returns true. + * + * @since 1.4 + */ +public +Dialog (Frame parent, String title, boolean modal, GraphicsConfiguration gc) +{ + super (parent, gc); + + // A null title is equivalent to an empty title + this.title = (title != null) ? title : ""; + this.modal = modal; + visible = false; + + setLayout(new BorderLayout()); +} + +/** + * Initializes a new instance of <code>Dialog</code> with the specified, + * parent, that is resizable. + * + * @exception IllegalArgumentException If parent is null. This exception is + * always thrown when GraphicsEnvironment.isHeadless() returns true. + * + * @since 1.2 + */ +public +Dialog (Dialog owner) +{ + this (owner, "", false, owner.getGraphicsConfiguration ()); +} + +/** + * Initializes a new instance of <code>Dialog</code> with the specified, + * parent and title, that is resizable. + * + * @exception IllegalArgumentException If parent is null. This exception is + * always thrown when GraphicsEnvironment.isHeadless() returns true. + * + * @since 1.2 + */ +public +Dialog (Dialog owner, String title) +{ + this (owner, title, false, owner.getGraphicsConfiguration ()); +} + +/** + * Initializes a new instance of <code>Dialog</code> with the specified, + * parent, title and modality, that is resizable. + * + * @exception IllegalArgumentException If parent is null. This exception is + * always thrown when GraphicsEnvironment.isHeadless() returns true. + * + * @since 1.2 + */ +public +Dialog (Dialog owner, String title, boolean modal) +{ + this (owner, title, modal, owner.getGraphicsConfiguration ()); +} + +/** + * Initializes a new instance of <code>Dialog</code> with the specified, + * parent, title, modality and <code>GraphicsConfiguration</code>, + * that is resizable. + * + * @exception IllegalArgumentException If parent is null, the + * GraphicsConfiguration is not a screen device or + * GraphicsEnvironment.isHeadless() returns true. + * + * @since 1.4 + */ +public +Dialog (Dialog parent, String title, boolean modal, GraphicsConfiguration gc) +{ + super (parent, parent.getGraphicsConfiguration ()); + + // A null title is equivalent to an empty title + this.title = (title != null) ? title : ""; + this.modal = modal; + visible = false; + + setLayout (new BorderLayout ()); +} + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * Returns the title of this dialog box. + * + * @return The title of this dialog box. + */ +public String +getTitle() +{ + return(title); +} + +/*************************************************************************/ + +/** + * Sets the title of this dialog box to the specified string. + * + * @param title The new title. + */ +public synchronized void +setTitle(String title) +{ + // A null title is equivalent to an empty title + this.title = (title != null) ? title : ""; + + if (peer != null) + { + DialogPeer d = (DialogPeer) peer; + d.setTitle (title); + } +} + +/*************************************************************************/ + +/** + * Tests whether or not this dialog box is modal. + * + * @return <code>true</code> if this dialog box is modal, + * <code>false</code> otherwise. + */ +public boolean +isModal() +{ + return(modal); +} + +/*************************************************************************/ + +/** + * Changes the modality of this dialog box. This can only be done before + * the peer is created. + * + * @param modal <code>true</code> to make this dialog box modal, + * <code>false</code> to make it non-modal. + */ +public void +setModal(boolean modal) +{ + this.modal = modal; +} + +/*************************************************************************/ + +/** + * Tests whether or not this dialog box is resizable. + * + * @return <code>true</code> if this dialog is resizable, <code>false</code>, + * otherwise. + */ +public boolean +isResizable() +{ + return(resizable); +} + +/*************************************************************************/ + +/** + * Changes the resizability of this dialog box. + * + * @param resizable <code>true</code> to make this dialog resizable, + * <code>false</code> to make it non-resizable. + */ +public synchronized void +setResizable(boolean resizable) +{ + this.resizable = resizable; + if (peer != null) + { + DialogPeer d = (DialogPeer) peer; + d.setResizable (resizable); + } +} + +/*************************************************************************/ + +/** + * Creates this object's native peer. + */ +public synchronized void +addNotify() +{ + if (peer == null) + peer = getToolkit ().createDialog (this); + super.addNotify (); +} + +/*************************************************************************/ + +/** + * Makes this dialog visible and brings it to the front. + * If the dialog is modal and is not already visible, this call will not + * return until the dialog is hidden by someone calling hide or dispose. + * If this is the event dispatching thread we must ensure that another event + * thread runs while the one which invoked this method is blocked. + */ +public synchronized void +show() +{ + super.show(); + + if (isModal()) + { + // If already shown (and blocked) just return + if (blocked) + return; + + /* If show is called in the dispatch thread for a modal dialog it will + block so we must run another thread so the events keep being + dispatched.*/ + if (EventQueue.isDispatchThread ()) + { + EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + eq2 = new EventQueue (); + eq.push (eq2); + } + + try + { + blocked = true; + wait (); + blocked = false; + } + catch (InterruptedException e) + { + blocked = false; + } + + if (eq2 != null) + { + eq2.pop (); + eq2 = null; + } + } +} + +/*************************************************************************/ + +/** + * Hides the Dialog and then + * causes show() to return if it is currently blocked. + */ + +public synchronized void +hide () +{ + if (blocked) + { + notifyAll (); + } + + super.hide(); +} + +/*************************************************************************/ + +/** + * Disposes the Dialog and then causes show() to return + * if it is currently blocked. + */ + +public synchronized void +dispose () +{ + if (blocked) + { + notifyAll (); + } + + super.dispose(); +} + +/*************************************************************************/ + +/** + * Returns a debugging string for this component. + * + * @return A debugging string for this component. + */ +protected String +paramString() +{ + return ("title+" + title + ",modal=" + modal + + ",resizable=" + resizable + "," + super.paramString()); +} + + /** + * Returns whether this frame is undecorated or not. + * + * @since 1.4 + */ + public boolean isUndecorated () + { + return undecorated; + } + + /** + * Disables or enables decorations for this frame. This method can only be + * called while the frame is not displayable. + * + * @exception IllegalComponentStateException If this frame is displayable. + * + * @since 1.4 + */ + public void setUndecorated (boolean undecorated) + { + if (isDisplayable ()) + throw new IllegalComponentStateException (); + + this.undecorated = undecorated; + } + + protected class AccessibleAWTDialog extends AccessibleAWTWindow + { + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.DIALOG; + } + + public AccessibleStateSet getAccessibleState() + { + AccessibleStateSet states = super.getAccessibleStateSet(); + if (isResizable()) + states.add(AccessibleState.RESIZABLE); + if (isModal()) + states.add(AccessibleState.MODAL); + return states; + } + } + + /** + * Gets the AccessibleContext associated with this <code>Dialog</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTDialog(); + return accessibleContext; + } + +} // class Dialog + diff --git a/libjava/classpath/java/awt/Dimension.java b/libjava/classpath/java/awt/Dimension.java new file mode 100644 index 0000000..4c1a07b --- /dev/null +++ b/libjava/classpath/java/awt/Dimension.java @@ -0,0 +1,234 @@ +/* Dimension.java -- represents a 2-dimensional span + Copyright (C) 1999, 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.geom.Dimension2D; +import java.io.Serializable; + +/** + * This class holds a width and height value pair. This is used in plenty + * of windowing classes, but also has geometric meaning. + * + * <p>It is valid for a dimension to have negative width or height; but it + * is considered to have no area. Therefore, the behavior in various methods + * is undefined in such a case. + * + * <p>There are some public fields; if you mess with them in an inconsistent + * manner, it is your own fault when you get invalid results. Also, this + * class is not threadsafe. + * + * @author Per Bothner (bothner@cygnus.com) + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @see Component + * @see LayoutManager + * @since 1.0 + * @status updated to 1.14 + */ +public class Dimension extends Dimension2D implements Serializable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 4723952579491349524L; + + /** + * The width of this object. + * + * @see #getSize() + * @see #setSize(double, double) + * @serial the width + */ + public int width; + + /** + * The height of this object. + * + * @see #getSize() + * @see #setSize(double, double) + * @serial the height + */ + public int height; + + /** + * Create a new Dimension with a width and height of zero. + */ + public Dimension() + { + } + + /** + * Create a new Dimension with width and height identical to that of the + * specified dimension. + * + * @param d the Dimension to copy + * @throws NullPointerException if d is null + */ + public Dimension(Dimension d) + { + width = d.width; + height = d.height; + } + + /** + * Create a new Dimension with the specified width and height. + * + * @param w the width of this object + * @param h the height of this object + */ + public Dimension(int w, int h) + { + width = w; + height = h; + } + + /** + * Gets the width of this dimension. + * + * @return the width, as a double + */ + public double getWidth() + { + return width; + } + + /** + * Gets the height of this dimension. + * + * @return the height, as a double + */ + public double getHeight() + { + return height; + } + + /** + * Sets the size of this dimension. The values are rounded to int. + * + * @param w the new width + * @param h the new height + * @since 1.2 + */ + public void setSize(double w, double h) + { + width = (int) w; + height = (int) h; + } + + /** + * Returns the size of this dimension. A pretty useless method, as this is + * already a dimension. + * + * @return a copy of this dimension + * @see #setSize(Dimension) + * @since 1.1 + */ + public Dimension getSize() + { + return new Dimension(width, height); + } + + /** + * Sets the width and height of this object to match that of the + * specified object. + * + * @param d the Dimension to get the new width and height from + * @throws NullPointerException if d is null + * @see #getSize() + * @since 1.1 + */ + public void setSize(Dimension d) + { + width = d.width; + height = d.height; + } + + /** + * Sets the width and height of this object to the specified values. + * + * @param w the new width value + * @param h the new height value + */ + public void setSize(int w, int h) + { + width = w; + height = h; + } + + /** + * Tests this object for equality against the specified object. This will + * be true if and only if the specified object is an instance of + * Dimension2D, and has the same width and height. + * + * @param obj the object to test against + * @return true if the object is equal to this + */ + public boolean equals(Object obj) + { + if (! (obj instanceof Dimension)) + return false; + Dimension dim = (Dimension) obj; + return height == dim.height && width == dim.width; + } + + /** + * Return the hashcode for this object. It is not documented, but appears + * to be <code>((width + height) * (width + height + 1) / 2) + width</code>. + * + * @return the hashcode + */ + public int hashCode() + { + // Reverse engineering this was fun! + return (width + height) * (width + height + 1) / 2 + width; + } + + /** + * Returns a string representation of this object. The format is: + * <code>getClass().getName() + "[width=" + width + ",height=" + height + * + ']'</code>. + * + * @return a string representation of this object + */ + public String toString() + { + return getClass().getName() + + "[width=" + width + ",height=" + height + ']'; + } +} // class Dimension diff --git a/libjava/classpath/java/awt/DisplayMode.java b/libjava/classpath/java/awt/DisplayMode.java new file mode 100644 index 0000000..d41d4a8 --- /dev/null +++ b/libjava/classpath/java/awt/DisplayMode.java @@ -0,0 +1,164 @@ +/* DisplayMode.java -- a description of display mode configurations + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This encapsulates information about the display mode for a graphics + * device configuration. They are device dependent, and may not always be + * available. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see GraphicsDevice + * @since 1.4 + * @status updated to 1.4 + */ +public final class DisplayMode +{ + /** + * Value of the bit depth if multiple depths are supported. + * + * @see #getBitDepth() + */ + public static final int BIT_DEPTH_MULTI = -1; + + /** + * Value of an unknown refresh rate. + * + * @see #getRefreshRate() + */ + public static final int REFRESH_RATE_UNKNOWN = 0; + + /** The width. */ + private final int width; + + /** The height. */ + private final int height; + + /** The bit depth. */ + private final int bitDepth; + + /** The refresh rate. */ + private final int refreshRate; + + /** + * Create a mode with the given parameters. + * + * @param width the width + * @param height the height + * @param bitDepth the bitDepth + * @param refreshRate the refreshRate + * @see #BIT_DEPTH_MULTI + * @see #REFRESH_RATE_UNKNOWN + */ + public DisplayMode(int width, int height, int bitDepth, int refreshRate) + { + this.width = width; + this.height = height; + this.bitDepth = bitDepth; + this.refreshRate = refreshRate; + } + + /** + * Returns the height, in pixels. + * + * @return the height + */ + public int getHeight() + { + return height; + } + + /** + * Returns the width, in pixels. + * + * @return the width + */ + public int getWidth() + { + return width; + } + + /** + * Returns the bit depth, in bits per pixel. This may be BIT_DEPTH_MULTI. + * + * @return the bit depth + * @see #BIT_DEPTH_MULTI + */ + public int getBitDepth() + { + return bitDepth; + } + + /** + * Returns the refresh rate, in hertz. This may be REFRESH_RATE_UNKNOWN. + * + * @return the refresh rate + * @see #REFRESH_RATE_UNKNOWN + */ + public int getRefreshRate() + { + return refreshRate; + } + + /** + * Test for equality. This returns true for two modes with identical + * parameters. + * + * @param dm The display mode to compare to + * + * @return true if it is equal + */ + public boolean equals (DisplayMode dm) + { + return (width == dm.width + && height == dm.height + && bitDepth == dm.bitDepth + && refreshRate == dm.refreshRate); + } + + /** + * Returns a hash code for the display mode. + * + * @return the hash code + */ + public int hashCode() + { + return width + height + bitDepth + refreshRate; + } +} // class DisplayMode diff --git a/libjava/classpath/java/awt/Event.java b/libjava/classpath/java/awt/Event.java new file mode 100644 index 0000000..648139c --- /dev/null +++ b/libjava/classpath/java/awt/Event.java @@ -0,0 +1,185 @@ +/* Copyright (C) 1999, 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * Written using on-line Java Platform 1.2 API Specification, as well + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). + * Status: Believed complete and correct. + */ + +public class Event implements java.io.Serializable +{ + static final long serialVersionUID = 5488922509400504703L; + + public static final int SHIFT_MASK = 1; + public static final int CTRL_MASK = 2; + public static final int META_MASK = 4; + public static final int ALT_MASK = 8; + + public static final int ACTION_EVENT = 1001; + public static final int BACK_SPACE = 8; + public static final int CAPS_LOCK = 1022; + public static final int DELETE = 127; + public static final int DOWN = 1005; + public static final int END = 1001; + public static final int ENTER = 10; + public static final int ESCAPE = 27; + public static final int F1 = 1008; + public static final int F10 = 1017; + public static final int F11 = 1018; + public static final int F12 = 1019; + public static final int F2 = 1009; + public static final int F3 = 1010; + public static final int F4 = 1011; + public static final int F5 = 1012; + public static final int F6 = 1013; + public static final int F7 = 1014; + public static final int F8 = 1015; + public static final int F9 = 1016; + public static final int GOT_FOCUS = 1004; + public static final int HOME = 1000; + public static final int INSERT = 1025; + public static final int KEY_ACTION = 403; + public static final int KEY_ACTION_RELEASE = 404; + public static final int KEY_PRESS = 401; + public static final int KEY_RELEASE = 402; + public static final int LEFT = 1006; + public static final int LIST_DESELECT = 702; + public static final int LIST_SELECT = 701; + public static final int LOAD_FILE = 1002; + public static final int LOST_FOCUS = 1005; + public static final int MOUSE_DOWN = 501; + public static final int MOUSE_DRAG = 506; + public static final int MOUSE_ENTER = 504; + public static final int MOUSE_EXIT = 505; + public static final int MOUSE_MOVE = 503; + public static final int MOUSE_UP = 502; + public static final int NUM_LOCK = 1023; + public static final int PAUSE = 1024; + public static final int PGDN = 1003; + public static final int PGUP = 1002; + public static final int PRINT_SCREEN = 1020; + public static final int RIGHT = 1007; + public static final int SAVE_FILE = 1003; + public static final int SCROLL_ABSOLUTE = 605; + public static final int SCROLL_BEGIN = 606; + public static final int SCROLL_END = 607; + public static final int SCROLL_LINE_DOWN = 602; + public static final int SCROLL_LINE_UP = 601; + public static final int SCROLL_LOCK = 1021; + public static final int SCROLL_PAGE_DOWN = 604; + public static final int SCROLL_PAGE_UP = 603; + public static final int TAB = 9; + public static final int UP = 1004; + public static final int WINDOW_DEICONIFY = 204; + public static final int WINDOW_DESTROY = 201; + public static final int WINDOW_EXPOSE = 202; + public static final int WINDOW_ICONIFY = 203; + public static final int WINDOW_MOVED = 205; + + public Object arg; + public int clickCount; + boolean consumed; // Required by serialization spec. + public Event evt; + public int id; + public int key; + public int modifiers; + public Object target; + public long when; + public int x; + public int y; + + public Event (Object target, int id, Object arg) + { + this.id = id; + this.target = target; + this.arg = arg; + } + + public Event (Object target, long when, int id, int x, int y, int key, + int modifiers) + { + this.target = target; + this.when = when; + this.id = id; + this.x = x; + this.y = y; + this.key = key; + this.modifiers = modifiers; + } + + public Event (Object target, long when, int id, int x, int y, int key, + int modifiers, Object arg) + { + this (target, when, id, x, y, key, modifiers); + this.arg = arg; + } + + public boolean controlDown () + { + return ((modifiers & CTRL_MASK) == 0 ? false : true); + } + + public boolean metaDown () + { + return ((modifiers & META_MASK) == 0 ? false : true); + } + + protected String paramString () + { + return "id=" + id + ",x=" + x + ",y=" + y + + ",target=" + target + ",arg=" + arg; + } + + public boolean shiftDown() + { + return ((modifiers & SHIFT_MASK) == 0 ? false : true); + } + + public String toString() + { + return getClass().getName() + "[" + paramString() + "]"; + } + + public void translate (int x, int y) + { + this.x += x; + this.y += y; + } +} diff --git a/libjava/classpath/java/awt/EventDispatchThread.java b/libjava/classpath/java/awt/EventDispatchThread.java new file mode 100644 index 0000000..a64cdae --- /dev/null +++ b/libjava/classpath/java/awt/EventDispatchThread.java @@ -0,0 +1,94 @@ +/* EventDispatchThread.java - + Copyright (C) 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt; + +/** + * @author Bryce McKinlay + * @status believed complete, but untested. + */ +class EventDispatchThread extends Thread +{ + private static int dispatchThreadNum; + + private EventQueue queue; + + EventDispatchThread(EventQueue queue) + { + super(); + setName("AWT-EventQueue-" + ++dispatchThreadNum); + this.queue = queue; + setPriority(NORM_PRIORITY + 1); + } + + public void run() + { + while (true) + { + try + { + AWTEvent evt = queue.getNextEvent(); + + KeyboardFocusManager manager; + manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + + // Try to dispatch this event to the current keyboard focus + // manager. It will dispatch all FocusEvents, all + // WindowEvents related to focus, and all KeyEvents, + // returning true. Otherwise, it returns false and we + // dispatch the event normally. + if (!manager.dispatchEvent (evt)) + queue.dispatchEvent(evt); + } + catch (ThreadDeath death) + { + // If someone wants to kill us, let them. + return; + } + catch (InterruptedException ie) + { + // We are interrupted when we should finish executing + return; + } + catch (Throwable x) + { + System.err.println("Exception during event dispatch:"); + x.printStackTrace(System.err); + } + } + } +} diff --git a/libjava/classpath/java/awt/EventQueue.java b/libjava/classpath/java/awt/EventQueue.java new file mode 100644 index 0000000..a8b0078 --- /dev/null +++ b/libjava/classpath/java/awt/EventQueue.java @@ -0,0 +1,552 @@ +/* EventQueue.java -- + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import gnu.java.awt.ClasspathToolkit; + +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.InputMethodEvent; +import java.awt.event.InvocationEvent; +import java.awt.event.WindowEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.EmptyStackException; + +/* Written using on-line Java 2 Platform Standard Edition v1.3 API + * Specification, as well as "The Java Class Libraries", 2nd edition + * (Addison-Wesley, 1998). + * Status: Believed complete, but untested. + */ + +/** + * This class manages a queue of <code>AWTEvent</code> objects that + * are posted to it. The AWT system uses only one event queue for all + * events. + * + * @author Bryce McKinlay + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class EventQueue +{ + private static final int INITIAL_QUEUE_DEPTH = 8; + private AWTEvent[] queue = new AWTEvent[INITIAL_QUEUE_DEPTH]; + + private int next_in = 0; // Index where next event will be added to queue + private int next_out = 0; // Index of next event to be removed from queue + + private EventQueue next; + private EventQueue prev; + private AWTEvent currentEvent; + private long lastWhen = System.currentTimeMillis(); + + private EventDispatchThread dispatchThread = new EventDispatchThread(this); + private boolean shutdown = false; + + private long lastNativeQueueAccess = 0; + private long humanLatencyThreshold = 100; + + synchronized void setShutdown (boolean b) + { + shutdown = b; + } + + synchronized boolean isShutdown () + { + if (shutdown) + return true; + + // This is the exact self-shutdown condition specified in J2SE: + // http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/AWTThreadIssues.html + + if (peekEvent() == null + && ((ClasspathToolkit) Toolkit.getDefaultToolkit()).nativeQueueEmpty()) + { + Frame[] frames = Frame.getFrames(); + for (int i = 0; i < frames.length; ++i) + if (frames[i].isDisplayable()) + return false; + return true; + } + return false; + } + + /** + * Initializes a new instance of <code>EventQueue</code>. + */ + public EventQueue() + { + } + + /** + * Returns the next event in the queue. This method will block until + * an event is available or until the thread is interrupted. + * + * @return The next event in the queue. + * + * @exception InterruptedException If this thread is interrupted while + * waiting for an event to be posted to the queue. + */ + public synchronized AWTEvent getNextEvent() + throws InterruptedException + { + if (next != null) + return next.getNextEvent(); + + ClasspathToolkit tk = ((ClasspathToolkit) Toolkit.getDefaultToolkit()); + long curr = System.currentTimeMillis(); + + if (! tk.nativeQueueEmpty() && + (curr - lastNativeQueueAccess > humanLatencyThreshold)) + { + tk.iterateNativeQueue(this, false); + lastNativeQueueAccess = curr; + } + + while (next_in == next_out) + { + // Only the EventDispatchThread associated with the top of the stack is + // allowed to get events from the native source; everyone else just + // waits on the head of the queue. + + if (isDispatchThread()) + { + // We are not allowed to return null from this method, yet it + // is possible that we actually have run out of native events + // in the enclosing while() loop, and none of the native events + // happened to cause AWT events. We therefore ought to check + // the isShutdown() condition here, before risking a "native + // wait". If we check it before entering this function we may + // wait forever for events after the shutdown condition has + // arisen. + + if (isShutdown()) + throw new InterruptedException(); + + tk.iterateNativeQueue(this, true); + lastNativeQueueAccess = System.currentTimeMillis(); + } + else + { + try + { + wait(); + } + catch (InterruptedException ie) + { + } + } + } + + AWTEvent res = queue[next_out]; + + if (++next_out == queue.length) + next_out = 0; + return res; + } + + /** + * Returns the next event in the queue without removing it from the queue. + * This method will block until an event is available or until the thread + * is interrupted. + * + * @return The next event in the queue. + * @specnote Does not block. Returns null if there are no events on the + * queue. + */ + public synchronized AWTEvent peekEvent() + { + if (next != null) + return next.peekEvent(); + + if (next_in != next_out) + return queue[next_out]; + else + return null; + } + + /** + * Returns the next event in the queue that has the specified id + * without removing it from the queue. + * This method will block until an event is available or until the thread + * is interrupted. + * + * @param id The event id to return. + * + * @return The next event in the queue. + * + * @specnote Does not block. Returns null if there are no matching events + * on the queue. + */ + public synchronized AWTEvent peekEvent(int id) + { + if (next != null) + return next.peekEvent(id); + + int i = next_out; + while (i != next_in) + { + AWTEvent qevt = queue[i]; + if (qevt.id == id) + return qevt; + } + return null; + } + + /** + * Posts a new event to the queue. + * + * @param evt The event to post to the queue. + * + * @exception NullPointerException If event is null. + */ + public synchronized void postEvent(AWTEvent evt) + { + if (evt == null) + throw new NullPointerException(); + + if (next != null) + { + next.postEvent(evt); + return; + } + + /* Check for any events already on the queue with the same source + and ID. */ + int i = next_out; + while (i != next_in) + { + AWTEvent qevt = queue[i]; + Object src; + if (qevt.id == evt.id + && (src = qevt.getSource()) == evt.getSource() + && src instanceof Component) + { + /* If there are, call coalesceEvents on the source component + to see if they can be combined. */ + Component srccmp = (Component) src; + AWTEvent coalesced_evt = srccmp.coalesceEvents(qevt, evt); + if (coalesced_evt != null) + { + /* Yes. Replace the existing event with the combined event. */ + queue[i] = coalesced_evt; + return; + } + break; + } + if (++i == queue.length) + i = 0; + } + + queue[next_in] = evt; + if (++next_in == queue.length) + next_in = 0; + + if (next_in == next_out) + { + /* Queue is full. Extend it. */ + AWTEvent[] oldQueue = queue; + queue = new AWTEvent[queue.length * 2]; + + int len = oldQueue.length - next_out; + System.arraycopy(oldQueue, next_out, queue, 0, len); + if (next_out != 0) + System.arraycopy(oldQueue, 0, queue, len, next_out); + + next_out = 0; + next_in = oldQueue.length; + } + + if (dispatchThread == null || !dispatchThread.isAlive()) + { + dispatchThread = new EventDispatchThread(this); + dispatchThread.start(); + } + + // Window events might represent the closing of a window, which + // might cause the end of the dispatch thread's life, so we'll wake + // it up here to give it a chance to check for shutdown. + + if (!isDispatchThread() + || (evt.getID() == WindowEvent.WINDOW_CLOSED) + || (evt.getID() == WindowEvent.WINDOW_CLOSING)) + ((ClasspathToolkit) Toolkit.getDefaultToolkit()).wakeNativeQueue(); + + notify(); + } + + /** + * Causes runnable to have its run method called in the dispatch thread of the + * EventQueue. This will happen after all pending events are processed. The + * call blocks until this has happened. This method will throw an Error if + * called from the event dispatcher thread. + * + * @exception InterruptedException If another thread has interrupted + * this thread. + * @exception InvocationTargetException If an exception is thrown when running + * runnable. + * + * @since 1.2 + */ + public static void invokeAndWait(Runnable runnable) + throws InterruptedException, InvocationTargetException + { + if (isDispatchThread ()) + throw new Error("Can't call invokeAndWait from event dispatch thread"); + + EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + Thread current = Thread.currentThread(); + + InvocationEvent ie = + new InvocationEvent(eq, runnable, current, true); + + synchronized (current) + { + eq.postEvent(ie); + current.wait(); + } + + Exception exception; + + if ((exception = ie.getException()) != null) + throw new InvocationTargetException(exception); + } + + /** + * This arranges for runnable to have its run method called in the + * dispatch thread of the EventQueue. This will happen after all + * pending events are processed. + * + * @since 1.2 + */ + public static void invokeLater(Runnable runnable) + { + EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + + InvocationEvent ie = + new InvocationEvent(eq, runnable, null, false); + + eq.postEvent(ie); + } + + /** + * Return true if the current thread is the current AWT event dispatch + * thread. + */ + public static boolean isDispatchThread() + { + EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + + /* Find last EventQueue in chain */ + while (eq.next != null) + eq = eq.next; + + return (Thread.currentThread() == eq.dispatchThread); + } + + /** + * Return the event currently being dispatched by the event + * dispatch thread. If the current thread is not the event + * dispatch thread, this method returns null. + * + * @since 1.4 + */ + public static AWTEvent getCurrentEvent() + { + EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + Thread ct = Thread.currentThread(); + + /* Find out if this thread is the dispatch thread for any of the + EventQueues in the chain */ + while (ct != eq.dispatchThread) + { + // Try next EventQueue, if any + if (eq.next == null) + return null; // Not an event dispatch thread + eq = eq.next; + } + + return eq.currentEvent; + } + + /** + * Allows a custom EventQueue implementation to replace this one. + * All pending events are transferred to the new queue. Calls to postEvent, + * getNextEvent, and peekEvent and others are forwarded to the pushed queue + * until it is removed with a pop(). + * + * @exception NullPointerException if newEventQueue is null. + */ + public synchronized void push(EventQueue newEventQueue) + { + if (newEventQueue == null) + throw new NullPointerException (); + + /* Make sure we are at the top of the stack because callers can + only get a reference to the one at the bottom using + Toolkit.getDefaultToolkit().getSystemEventQueue() */ + if (next != null) + { + next.push (newEventQueue); + return; + } + + /* Make sure we have a live dispatch thread to drive the queue */ + if (dispatchThread == null) + dispatchThread = new EventDispatchThread(this); + + int i = next_out; + while (i != next_in) + { + newEventQueue.postEvent(queue[i]); + next_out = i; + if (++i == queue.length) + i = 0; + } + + next = newEventQueue; + newEventQueue.prev = this; + } + + /** Transfer any pending events from this queue back to the parent queue that + * was previously push()ed. Event dispatch from this queue is suspended. + * + * @exception EmptyStackException If no previous push was made on this + * EventQueue. + */ + protected void pop() throws EmptyStackException + { + if (prev == null) + throw new EmptyStackException(); + + /* The order is important here, we must get the prev lock first, + or deadlock could occur as callers usually get here following + prev's next pointer, and thus obtain prev's lock before trying + to get this lock. */ + synchronized (prev) + { + prev.next = next; + if (next != null) + next.prev = prev; + + synchronized (this) + { + int i = next_out; + while (i != next_in) + { + prev.postEvent(queue[i]); + next_out = i; + if (++i == queue.length) + i = 0; + } + // Empty the queue so it can be reused + next_in = 0; + next_out = 0; + + ((ClasspathToolkit) Toolkit.getDefaultToolkit()).wakeNativeQueue(); + setShutdown(true); + dispatchThread = null; + this.notifyAll(); + } + } + } + + /** + * Dispatches an event. The manner in which the event is dispatched depends + * upon the type of the event and the type of the event's source object. + * + * @exception NullPointerException If event is null. + */ + protected void dispatchEvent(AWTEvent evt) + { + currentEvent = evt; + + if (evt instanceof InputEvent) + lastWhen = ((InputEvent) evt).getWhen(); + else if (evt instanceof ActionEvent) + lastWhen = ((ActionEvent) evt).getWhen(); + else if (evt instanceof InvocationEvent) + lastWhen = ((InvocationEvent) evt).getWhen(); + + if (evt instanceof ActiveEvent) + { + ActiveEvent active_evt = (ActiveEvent) evt; + active_evt.dispatch(); + } + else + { + Object source = evt.getSource(); + + if (source instanceof Component) + { + Component srccmp = (Component) source; + srccmp.dispatchEvent(evt); + } + else if (source instanceof MenuComponent) + { + MenuComponent srccmp = (MenuComponent) source; + srccmp.dispatchEvent(evt); + } + } + } + + /** + * Returns the timestamp of the most recent event that had a timestamp, or + * the initialization time of the event queue if no events have been fired. + * At present, only <code>InputEvent</code>s, <code>ActionEvent</code>s, + * <code>InputMethodEvent</code>s, and <code>InvocationEvent</code>s have + * timestamps, but this may be added to other events in future versions. + * If this is called by the event dispatching thread, it can be any + * (sequential) value, but to other threads, the safest bet is to return + * System.currentTimeMillis(). + * + * @return the most recent timestamp + * @see InputEvent#getWhen() + * @see ActionEvent#getWhen() + * @see InvocationEvent#getWhen() + * @see InputMethodEvent#getWhen() + * @since 1.4 + */ + public static long getMostRecentEventTime() + { + EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + if (Thread.currentThread() != eq.dispatchThread) + return System.currentTimeMillis(); + return eq.lastWhen; + } +} diff --git a/libjava/classpath/java/awt/FileDialog.java b/libjava/classpath/java/awt/FileDialog.java new file mode 100644 index 0000000..7f2723e --- /dev/null +++ b/libjava/classpath/java/awt/FileDialog.java @@ -0,0 +1,318 @@ +/* FileDialog.java -- A filename selection dialog box + Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.peer.FileDialogPeer; +import java.io.FilenameFilter; +import java.io.Serializable; + +/** + * This class implements a file selection dialog box widget. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Tom Tromey (tromey@redhat.com) + */ +public class FileDialog extends Dialog implements Serializable +{ + +/* + * Static Variables + */ + +/** + * Indicates that the purpose of the dialog is for opening a file. + */ +public static final int LOAD = 0; + +/** + * Indicates that the purpose of the dialog is for saving a file. + */ +public static final int SAVE = 1; + +// Serialization constant +private static final long serialVersionUID = 5035145889651310422L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial The directory for this file dialog. + */ +private String dir; + +/** + * @serial The filename for this file dialog + */ +private String file; + +/** + * @serial The filter for selecting filenames to display + */ +private FilenameFilter filter; + +/** + * @serial The mode of this dialog, either <code>LOAD</code> or + * <code>SAVE</code>. + */ +private int mode; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>FileDialog</code> with the + * specified parent. This dialog will have no title and will be for + * loading a file. + * + * @param parent The parent frame for this dialog. + */ +public +FileDialog(Frame parent) +{ + this(parent, "", LOAD); +} + +/*************************************************************************/ + +/** + * Initialized a new instance of <code>FileDialog</code> with the + * specified parent and title. This dialog will be for opening a file. + * + * @param parent The parent frame for this dialog. + * @param title The title for this dialog. + */ +public +FileDialog(Frame parent, String title) +{ + this(parent, title, LOAD); +} + +/*************************************************************************/ + +/** + * Initialized a new instance of <code>FileDialog</code> with the + * specified parent, title, and mode. + * + * @param parent The parent frame for this dialog. + * @param title The title for this dialog. + * @param mode The mode of the dialog, either <code>LOAD</code> or + * <code>SAVE</code>. + * + * @exception IllegalArgumentException If an illegal file dialog mode + * is supplied. + */ +public +FileDialog(Frame parent, String title, int mode) +{ + super(parent, title, true); + + if ((mode != LOAD) && (mode != SAVE)) + throw new IllegalArgumentException ( + "Mode argument must be either LOAD or SAVE"); + + setMode (mode); +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns the mode of this dialog, either <code>LOAD</code> or + * <code>SAVE</code>. + * + * @return The mode of this dialog. + */ +public int +getMode() +{ + return(mode); +} + +/*************************************************************************/ + +/** + * Sets the mode of this dialog to either <code>LOAD</code> or + * <code>SAVE</code>. This method is only effective before the native + * peer is created. + * + * @param mode The new mode of this file dialog. + * + * @exception IllegalArgumentException If an illegal file dialog mode + * is supplied. + */ +public void +setMode(int mode) +{ + if ((mode != LOAD) && (mode != SAVE)) + throw new IllegalArgumentException("Bad mode: " + mode); + + this.mode = mode; +} + +/*************************************************************************/ + +/** + * Returns the directory for this file dialog. + * + * @return The directory for this file dialog. + */ +public String +getDirectory() +{ + return(dir); +} + +/*************************************************************************/ + +/** + * Sets the directory for this file dialog. + * + * @param dir The new directory for this file dialog. + */ +public synchronized void +setDirectory(String dir) +{ + this.dir = dir; + if (peer != null) + { + FileDialogPeer f = (FileDialogPeer) peer; + f.setDirectory (dir); + } +} + +/*************************************************************************/ + +/** + * Returns the file that is selected in this dialog. + * + * @return The file that is selected in this dialog. + */ +public String +getFile() +{ + return(file); +} + +/*************************************************************************/ + +/** + * Sets the selected file for this dialog. + * + * @param file The selected file for this dialog. + */ +public synchronized void +setFile(String file) +{ + this.file = file; + if (peer != null) + { + FileDialogPeer f = (FileDialogPeer) peer; + f.setFile (file); + } +} + +/*************************************************************************/ + +/** + * Returns the filename filter being used by this dialog. + * + * @return The filename filter being used by this dialog. + */ +public FilenameFilter +getFilenameFilter() +{ + return(filter); +} + +/*************************************************************************/ + +/** + * Sets the filename filter used by this dialog. + * + * @param filter The new filename filter for this file dialog box. + */ +public synchronized void +setFilenameFilter(FilenameFilter filter) +{ + this.filter = filter; + if (peer != null) + { + FileDialogPeer f = (FileDialogPeer) peer; + f.setFilenameFilter (filter); + } +} + +/*************************************************************************/ + +/** + * Creates the native peer for this file dialog box. + */ +public void +addNotify() +{ + if (peer == null) + peer = getToolkit ().createFileDialog (this); + super.addNotify (); +} + +/*************************************************************************/ + +/** + * Returns a debugging string for this object. + * + * @return A debugging string for this object. + */ +protected String +paramString() +{ + return ("dir=" + dir + ",file=" + file + + ",mode=" + mode + "," + super.paramString()); +} + +} // class FileDialog + diff --git a/libjava/classpath/java/awt/FlowLayout.java b/libjava/classpath/java/awt/FlowLayout.java new file mode 100644 index 0000000..4674990 --- /dev/null +++ b/libjava/classpath/java/awt/FlowLayout.java @@ -0,0 +1,364 @@ +/* FlowLayout.java -- Grid-based layout engine + Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.io.Serializable; + +/** This class implements a flow-based layout. Components are laid + * out in order from left to right. When a component cannot be placed + * without horizontal clipping, a new row is started. This class + * supports horizontal and vertical gaps. These are used for spacing + * between components. + * + * @author Tom Tromey (tromey@redhat.com) + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class FlowLayout implements LayoutManager, Serializable +{ + /** Constant that specifies left alignment. */ + public static final int LEFT = 0; + /** Constant that specifies center alignment. */ + public static final int CENTER = 1; + /** Constant that specifies right alignment. */ + public static final int RIGHT = 2; + + /** Constant that specifies alignment to leading edge of container's + * orientation. */ + public static final int LEADING = 3; + /** Constant that specifies alignment to trailing edge of container's + * orientation. */ + public static final int TRAILING = 4; + + // Serialization constant + private static final long serialVersionUID = -7262534875583282631L; + + /** + * Add a new component to the layout. This particular implementation + * does nothing. + * + * @param name the name + * @param comp the component + */ + public void addLayoutComponent (String name, Component comp) + { + // Nothing. + } + + /** + * Returns the current justification value for this object. + * + * @return The current justification value for this object. + */ + public int getAlignment () + { + return align; + } + + /** + * Returns the horizontal gap between components. + * + * @return The horizontal gap between components. + */ + public int getHgap () + { + return hgap; + } + + /** + * Returns the vertical gap between lines of components. + * + * @return The vertical gap between lines of components. + */ + public int getVgap () + { + return vgap; + } + + /** + * Initializes a new instance of <code>FlowLayout</code> with a center + * justification and a default horizontal and vertical gap of 5. + */ + public FlowLayout () + { + this (CENTER, 5, 5); + } + + /** + * Initializes a new instance of <code>FlowLayout</code> with the specified + * justification and a default horizontal and vertical gap of 5. + * + * @param align The justification setting, which should be one of the + * contants in this class. + */ + public FlowLayout (int align) + { + this (align, 5, 5); + } + + /** + * Initializes a new instance of <code>FlowLayout</code> with the specified + * justification and gap values + * @param align Alignment + * @param hgap The horizontal gap + * @param vgap The vertical gap + * @exception IllegalArgumentException If either gap is negative + */ + public FlowLayout (int align, int hgap, int vgap) + { + // Use methods to set fields so that we can have all the checking + // in one place. + setVgap (vgap); + setHgap (hgap); + setAlignment (align); + } + + /** Lay out the container's components based on current settings. + * @param parent The parent container + */ + public void layoutContainer (Container parent) + { + synchronized (parent.getTreeLock ()) + { + int num = parent.getComponentCount (); + // This is more efficient than calling getComponents(). + Component[] comps = parent.component; + + Dimension d = parent.getSize (); + Insets ins = parent.getInsets (); + + ComponentOrientation orient = parent.getComponentOrientation (); + boolean left_to_right = orient.isLeftToRight (); + + int y = ins.top + vgap; + int i = 0; + while (i < num) + { + // Find the components which go in the current row. + int new_w = ins.left + hgap + ins.right; + int new_h = 0; + int j; + boolean found_one = false; + for (j = i; j < num; ++j) + { + // Skip invisible items. + if (! comps[j].visible) + continue; + + Dimension c = comps[j].getPreferredSize (); + + int next_w = new_w + hgap + c.width; + if (next_w <= d.width || ! found_one) + { + new_w = next_w; + new_h = Math.max (new_h, c.height); + found_one = true; + } + else + { + // Must start a new row, and we already found an item + break; + } + } + + // Set the location of each component for this row. + int x; + + int myalign = align; + if (align == LEADING) + myalign = left_to_right ? LEFT : RIGHT; + else if (align == TRAILING) + myalign = left_to_right ? RIGHT : LEFT; + + if (myalign == LEFT) + x = ins.left + hgap; + else if (myalign == CENTER) + x = ins.left + (d.width - new_w) / 2 + hgap; + else + x = ins.left + (d.width - new_w) + hgap; + + for (int k = i; k < j; ++k) + { + if (comps[k].visible) + { + Dimension c = comps[k].getPreferredSize (); + comps[k].setBounds (x, y + (new_h - c.height) / 2, + c.width, c.height); + x += c.width + hgap; + } + } + + // Advance to next row. + i = j; + y += new_h + vgap; + } + } + } + + /** + * Returns the minimum layout size for the specified container using + * this layout. + * @param cont The parent container + * @return The minimum layout size. + */ + public Dimension minimumLayoutSize (Container cont) + { + return getSize (cont, true); + } + + /** + * Returns the preferred layout size for the specified container using + * this layout. + * @param cont The parent container + * @return The preferred layout size. + */ + public Dimension preferredLayoutSize (Container cont) + { + return getSize (cont, false); + } + + /** Remove the indicated component from this layout manager. + * This particular implementation does nothing. + * @param comp The component to remove + */ + public void removeLayoutComponent (Component comp) + { + // Nothing. + } + + /** + * Sets the justification value for this object to the specified value. + * + * @param align The new justification value for this object, which must + * be one of the constants in this class. + */ + public void setAlignment (int align) + { + if (align != LEFT && align != RIGHT && align != CENTER + && align != LEADING && align != TRAILING) + throw new IllegalArgumentException ("invalid alignment: " + align); + this.align = align; + } + + /** + * Sets the horizontal gap between components to the specified value. + * + * @param hgap The new horizontal gap between components. + */ + public void setHgap (int hgap) + { + if (hgap < 0) + throw new IllegalArgumentException ("horizontal gap must be nonnegative"); + this.hgap = hgap; + } + + /** + * Sets the vertical gap between lines of components to the specified value. + * + * @param vgap The new vertical gap. + */ + public void setVgap (int vgap) + { + if (vgap < 0) + throw new IllegalArgumentException ("vertical gap must be nonnegative"); + this.vgap = vgap; + } + + /** Return String description of this object. + * @return A string representation of this object. + */ + public String toString () + { + return ("[" + getClass ().getName () + ",hgap=" + hgap + ",vgap=" + vgap + + ",align=" + align + "]"); + } + + // This method is used to compute the various sizes. + private Dimension getSize (Container parent, boolean is_min) + { + synchronized (parent.getTreeLock ()) + { + int w, h, num = parent.getComponentCount (); + // This is more efficient than calling getComponents(). + Component[] comps = parent.component; + + w = 0; + h = 0; + for (int i = 0; i < num; ++i) + { + if (! comps[i].visible) + continue; + + // FIXME: can we just directly read the fields in Component? + // Or will that not work with subclassing? + Dimension d; + + if (is_min) + d = comps[i].getMinimumSize (); + else + d = comps[i].getPreferredSize (); + + w += d.width; + h = Math.max (d.height, h); + } + + Insets ins = parent.getInsets (); + + w += (num + 1) * hgap + ins.left + ins.right; + h += 2 * vgap + ins.top + ins.bottom; + + return new Dimension (w, h); + } + } + + /** + * @serial The justification alignment of the lines of components, which + * will be one of the constants defined in this class. + */ + private int align; + + /** + * @serial The horizontal gap between components. + */ + private int hgap; + + /** + * @serial The vertical gap between lines of components. + */ + private int vgap; +} diff --git a/libjava/classpath/java/awt/FocusTraversalPolicy.java b/libjava/classpath/java/awt/FocusTraversalPolicy.java new file mode 100644 index 0000000..a7f1558 --- /dev/null +++ b/libjava/classpath/java/awt/FocusTraversalPolicy.java @@ -0,0 +1,103 @@ +/* FocusTraversalPolicy.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * @since 1.4 + */ +public abstract class FocusTraversalPolicy +{ + /** + * Creates a <code>FocusTraversalPolicy</code> object. + */ + public FocusTraversalPolicy() + { + // Do nothing in here. + } + + /** + * Returns the Component that should receive the focus after a Component. + * + * @exception IllegalArgumentException If root or current is null, + * or if root is not a focus cycle root of current. + */ + public abstract Component getComponentAfter(Container root, + Component current); + + /** + * Returns the Component that should receive the focus before a Component. + * + * @exception IllegalArgumentException If root or current is null, + * or if root is not a focus cycle root of current. + */ + public abstract Component getComponentBefore(Container root, + Component current); + + /** + * Returns the first Component in the traversal cycle. + * + * @exception IllegalArgumentException If root is null. + */ + public abstract Component getFirstComponent(Container root); + + /** + * Returns the last Component in the traversal cycle. + * + * @exception IllegalArgumentException If root is null. + */ + public abstract Component getLastComponent(Container root); + + /** + * Returns the default Component to focus. + * + * @exception IllegalArgumentException If root is null. + */ + public abstract Component getDefaultComponent(Container root); + + /** + * Returns the Component that should receive the focus when a Window is made + * visible for the first time. + * + * @exception IllegalArgumentException If window is null. + */ + public Component getInitialComponent(Window window) + { + return getDefaultComponent(window); + } +} // class FocusTraversalPolicy diff --git a/libjava/classpath/java/awt/Font.java b/libjava/classpath/java/awt/Font.java new file mode 100644 index 0000000..30961ab --- /dev/null +++ b/libjava/classpath/java/awt/Font.java @@ -0,0 +1,1336 @@ +/* Font.java -- Font object + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import gnu.java.awt.ClasspathToolkit; +import gnu.java.awt.peer.ClasspathFontPeer; + +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.LineMetrics; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.peer.FontPeer; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.text.AttributedCharacterIterator; +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * This class represents a windowing system font. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Warren Levy (warrenl@cygnus.com) + * @author Graydon Hoare (graydon@redhat.com) + */ +public class Font implements Serializable +{ + +/* + * Static Variables + */ + +/** + * Constant indicating a "plain" font. + */ +public static final int PLAIN = 0; + +/** + * Constant indicating a "bold" font. + */ +public static final int BOLD = 1; + +/** + * Constant indicating an "italic" font. + */ +public static final int ITALIC = 2; + +/** + * Constant indicating the baseline mode characteristic of Roman. + */ +public static final int ROMAN_BASELINE = 0; + +/** + * Constant indicating the baseline mode characteristic of Chinese. + */ +public static final int CENTER_BASELINE = 1; + +/** + * Constant indicating the baseline mode characteristic of Devanigri. + */ +public static final int HANGING_BASELINE = 2; + + + /** + * Indicates to <code>createFont</code> that the supplied font data + * is in TrueType format. + * + * <p><em>Specification Note:</em> The Sun JavaDoc for J2SE 1.4 does + * not indicate whether this value also subsumes OpenType. OpenType + * is essentially the same format as TrueType, but allows to define + * glyph shapes in the same way as PostScript, using cubic bezier + * curves. + * + * @since 1.3 + */ + public static final int TRUETYPE_FONT = 0; + + + /** + * A flag for <code>layoutGlyphVector</code>, indicating that the + * orientation of a text run is from left to right. + * + * @since 1.4 + */ + public static final int LAYOUT_LEFT_TO_RIGHT = 0; + + + /** + * A flag for <code>layoutGlyphVector</code>, indicating that the + * orientation of a text run is from right to left. + * + * @since 1.4 + */ + public static final int LAYOUT_RIGHT_TO_LEFT = 1; + + + /** + * A flag for <code>layoutGlyphVector</code>, indicating that the + * text does not contain valid characters before the + * <code>start</code> position. If this flag is set, + * <code>layoutGlyphVector</code> does not examine the text before + * <code>start</code>, even if this would be necessary to select the + * correct glyphs (e.g., for Arabic text). + * + * @since 1.4 + */ + public static final int LAYOUT_NO_START_CONTEXT = 2; + + + /** + * A flag for <code>layoutGlyphVector</code>, indicating that the + * text does not contain valid characters after the + * <code>limit</code> position. If this flag is set, + * <code>layoutGlyphVector</code> does not examine the text after + * <code>limit</code>, even if this would be necessary to select the + * correct glyphs (e.g., for Arabic text). + * + * @since 1.4 + */ + public static final int LAYOUT_NO_LIMIT_CONTEXT = 4; + + /** + * The logical name of this font. + * + * @since 1.0 + */ + protected String name; + + /** + * The size of this font in pixels. + * + * @since 1.0 + */ + protected int size; + + /** + * The style of this font -- PLAIN, BOLD, ITALIC or BOLD+ITALIC. + * + * @since 1.0 + */ + protected int style; + +// Serialization constant +private static final long serialVersionUID = -4206021311591459213L; + + + // The ClasspathToolkit-provided peer which implements this font + private ClasspathFontPeer peer; + +/*************************************************************************/ + +/* + * Static Methods + */ + +/** + * Creates a <code>Font</code> object from the specified string, which + * is in one of the following formats: + * <p> + * <ul> + * <li>fontname-style-pointsize + * <li>fontname-style + * <li>fontname-pointsize + * <li>fontname + * </ul> + * <p> + * The style should be one of BOLD, ITALIC, or BOLDITALIC. The default + * style if none is specified is PLAIN. The default size if none + * is specified is 12. + * + * @param fontspec a string specifying the required font (<code>null</code> + * permitted, interpreted as 'Dialog-PLAIN-12'). + * + * @return A font. + */ + public static Font decode (String fontspec) +{ + if (fontspec == null) + fontspec = "Dialog-PLAIN-12"; + String name = null; + int style = PLAIN; + int size = 12; + + StringTokenizer st = new StringTokenizer(fontspec, "- "); + while (st.hasMoreTokens()) + { + String token = st.nextToken(); + if (name == null) + { + name = token; + continue; + } + + if (token.toUpperCase().equals("BOLD")) + { + style = BOLD; + continue; + } + if (token.toUpperCase().equals("ITALIC")) + { + style = ITALIC; + continue; + } + if (token.toUpperCase().equals("BOLDITALIC")) + { + style = BOLD | ITALIC; + continue; + } + + int tokenval = 0; + try + { + tokenval = Integer.parseInt(token); + } + catch(NumberFormatException e) + { + // Ignored. + } + + if (tokenval != 0) + size = tokenval; + } + + HashMap attrs = new HashMap(); + ClasspathFontPeer.copyStyleToAttrs (style, attrs); + ClasspathFontPeer.copySizeToAttrs (size, attrs); + + return getFontFromToolkit (name, attrs); +} + + /* These methods delegate to the toolkit. */ + + protected static ClasspathToolkit tk () + { + return (ClasspathToolkit)(Toolkit.getDefaultToolkit ()); + } + + /* Every factory method in Font should eventually call this. */ + protected static Font getFontFromToolkit (String name, Map attribs) + { + return tk ().getFont (name, attribs); + } + + /* Every Font constructor should eventually call this. */ + protected static ClasspathFontPeer getPeerFromToolkit (String name, Map attrs) + { + return tk ().getClasspathFontPeer (name, attrs); + } + + +/*************************************************************************/ + +/** + * Returns a <code>Font</code> object from the passed property name. + * + * @param propname The name of the system property. + * @param defval Value to use if the property is not found. + * + * @return The requested font, or <code>default</code> if the property + * not exist or is malformed. + */ + public static Font getFont (String propname, Font defval) +{ + String propval = System.getProperty(propname); + if (propval != null) + return decode (propval); + return defval; +} + +/*************************************************************************/ + +/** + * Returns a <code>Font</code> object from the passed property name. + * + * @param propname The name of the system property. + * + * @return The requested font, or <code>null</code> if the property + * not exist or is malformed. + */ + public static Font getFont (String propname) +{ + return getFont (propname, (Font)null); +} + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>Font</code> with the specified + * attributes. + * + * @param name The name of the font. + * @param style The font style. + * @param size The font point size. + */ + + public Font (String name, int style, int size) + { + HashMap attrs = new HashMap(); + ClasspathFontPeer.copyStyleToAttrs (style, attrs); + ClasspathFontPeer.copySizeToAttrs (size, attrs); + this.peer = getPeerFromToolkit (name, attrs); + } + + public Font (Map attrs) + { + this(null, attrs); + } + + /* This extra constructor is here to permit ClasspathToolkit and to build + a font with a "logical name" as well as attrs. */ + public Font (String name, Map attrs) + { + // If attrs is null, setting it to an empty HashMap will give this + // Font default attributes. + if (attrs == null) + attrs = new HashMap(); + this.peer = getPeerFromToolkit (name, attrs); + } + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns the logical name of the font. A logical name is the name the + * font was constructed with. It may be the name of a logical font (one + * of 6 required names in all java environments) or it may be a face + * name. + * + * @return The logical name of the font. + * + * @see #getFamily() + * @see #getFontName() + */ + public String getName () +{ + return peer.getName (this); +} + +/*************************************************************************/ + +/** + * Returns the style of the font. + * + * @return The font style. + */ + public int getSize () +{ + return (int) peer.getSize (this); +} + + public float getSize2D () +{ + return peer.getSize (this); +} + +/*************************************************************************/ + +/** + * Tests whether or not this is a plain font. This will be true if + * and only if neither the bold nor the italics style is set. + * + * @return <code>true</code> if this is a plain font, <code>false</code> + * otherwise. + */ + public boolean isPlain () +{ + return peer.isPlain (this); +} + +/*************************************************************************/ + +/** + * Tests whether or not this font is bold. + * + * @return <code>true</code> if this font is bold, <code>false</code> + * otherwise. + */ + public boolean isBold () +{ + return peer.isBold (this); +} + +/*************************************************************************/ + +/** + * Tests whether or not this font is italic. + * + * @return <code>true</code> if this font is italic, <code>false</code> + * otherwise. + */ + public boolean isItalic () +{ + return peer.isItalic (this); +} + +/*************************************************************************/ + +/** + * Returns the family name of this font. A family name describes a design + * or "brand name" (such as Helvetica or Palatino). It is less specific + * than a font face name (such as Helvetica Bold). + * + * @return A string containing the font family name. + * + * @since 1.2 + * + * @see #getName() + * @see #getFontName() + * @see GraphicsEnvironment#getAvailableFontFamilyNames() + */ + public String getFamily () +{ + return peer.getFamily (this); +} + +/** + * Returns integer code representing the sum of style flags of this font, a + * combination of either {@link #PLAIN}, {@link #BOLD}, or {@link #ITALIC}. + * + * @return code representing the style of this font. + * + * @see #isPlain() + * @see #isBold() + * @see #isItalic() + */ + public int getStyle () +{ + return peer.getStyle (this); +} + +/** + * Checks if specified character maps to a glyph in this font. + * + * @param c The character to check. + * + * @return Whether the character has a corresponding glyph in this font. + * + * @since 1.2 + */ + public boolean canDisplay (char c) +{ + return peer.canDisplay (this, c); +} + +/** + * Checks how much of a given string can be mapped to glyphs in + * this font. + * + * @param s The string to check. + * + * @return The index of the first character in <code>s</code> which cannot + * be converted to a glyph by this font, or <code>-1</code> if all + * characters can be mapped to glyphs. + * + * @since 1.2 + */ + public int canDisplayUpTo (String s) +{ + return peer.canDisplayUpTo (this, new StringCharacterIterator (s), + 0, s.length () - 1); +} + +/** + * Checks how much of a given sequence of text can be mapped to glyphs in + * this font. + * + * @param text Array containing the text to check. + * @param start Position of first character to check in <code>text</code>. + * @param limit Position of last character to check in <code>text</code>. + * + * @return The index of the first character in the indicated range which + * cannot be converted to a glyph by this font, or <code>-1</code> if all + * characters can be mapped to glyphs. + * + * @since 1.2 + * + * @throws IndexOutOfBoundsException if the range [start, limit] is + * invalid in <code>text</code>. + */ + public int canDisplayUpTo (char[] text, int start, int limit) +{ + return peer.canDisplayUpTo + (this, new StringCharacterIterator (new String (text)), start, limit); +} + +/** + * Checks how much of a given sequence of text can be mapped to glyphs in + * this font. + * + * @param i Iterator over the text to check. + * @param start Position of first character to check in <code>i</code>. + * @param limit Position of last character to check in <code>i</code>. + * + * @return The index of the first character in the indicated range which + * cannot be converted to a glyph by this font, or <code>-1</code> if all + * characters can be mapped to glyphs. + * + * @since 1.2 + * + * @throws IndexOutOfBoundsException if the range [start, limit] is + * invalid in <code>i</code>. + */ + public int canDisplayUpTo (CharacterIterator i, int start, int limit) +{ + return peer.canDisplayUpTo (this, i, start, limit); +} + +/** + * Creates a new font with point size 1 and {@link #PLAIN} style, + * reading font data from the provided input stream. The resulting font + * can have further fonts derived from it using its + * <code>deriveFont</code> method. + * + * @param fontFormat Integer code indicating the format the font data is + * in.Currently this can only be {@link #TRUETYPE_FONT}. + * @param is {@link InputStream} from which font data will be read. This + * stream is not closed after font data is extracted. + * + * @return A new {@link Font} of the format indicated. + * + * @throws IllegalArgumentException if <code>fontType</code> is not + * recognized. + * @throws FontFormatException if data in InputStream is not of format + * indicated. + * @throws IOException if insufficient data is present on InputStream. + * + * @since 1.3 + */ + public static Font createFont (int fontFormat, InputStream is) + throws FontFormatException, IOException +{ + return tk().createFont (fontFormat, is); +} + +/** + * Maps characters to glyphs in a one-to-one relationship, returning a new + * {@link GlyphVector} with a mapped glyph for each input character. This + * sort of mapping is often sufficient for some scripts such as Roman, but + * is inappropriate for scripts with special shaping or contextual layout + * requirements such as Arabic, Indic, Hebrew or Thai. + * + * @param ctx The rendering context used for precise glyph placement. + * @param str The string to convert to Glyphs. + * + * @return A new {@link GlyphVector} containing glyphs mapped from str, + * through the font's cmap table. + * + * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int) + */ + public GlyphVector createGlyphVector (FontRenderContext ctx, String str) +{ + return peer.createGlyphVector (this, ctx, new StringCharacterIterator (str)); +} + +/** + * Maps characters to glyphs in a one-to-one relationship, returning a new + * {@link GlyphVector} with a mapped glyph for each input character. This + * sort of mapping is often sufficient for some scripts such as Roman, but + * is inappropriate for scripts with special shaping or contextual layout + * requirements such as Arabic, Indic, Hebrew or Thai. + * + * @param ctx The rendering context used for precise glyph placement. + * @param i Iterator over the text to convert to glyphs. + * + * @return A new {@link GlyphVector} containing glyphs mapped from str, + * through the font's cmap table. + * + * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int) + */ + public GlyphVector createGlyphVector (FontRenderContext ctx, CharacterIterator i) +{ + return peer.createGlyphVector (this, ctx, i); +} + +/** + * Maps characters to glyphs in a one-to-one relationship, returning a new + * {@link GlyphVector} with a mapped glyph for each input character. This + * sort of mapping is often sufficient for some scripts such as Roman, but + * is inappropriate for scripts with special shaping or contextual layout + * requirements such as Arabic, Indic, Hebrew or Thai. + * + * @param ctx The rendering context used for precise glyph placement. + * @param chars Array of characters to convert to glyphs. + * + * @return A new {@link GlyphVector} containing glyphs mapped from str, + * through the font's cmap table. + * + * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int) + */ + public GlyphVector createGlyphVector (FontRenderContext ctx, char[] chars) +{ + return peer.createGlyphVector + (this, ctx, new StringCharacterIterator (new String (chars))); +} + +/** + * Extracts a sequence of glyphs from a font, returning a new {@link + * GlyphVector} with a mapped glyph for each input glyph code. + * + * @param ctx The rendering context used for precise glyph placement. + * @param glyphCodes Array of characters to convert to glyphs. + * + * @return A new {@link GlyphVector} containing glyphs mapped from str, + * through the font's cmap table. + * + * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int) + * + * @specnote This method is documented to perform character-to-glyph + * conversions, in the Sun documentation, but its second parameter name is + * "glyphCodes" and it is not clear to me why it would exist if its + * purpose was to transport character codes inside integers. I assume it + * is mis-documented in the Sun documentation. + */ + + public GlyphVector createGlyphVector (FontRenderContext ctx, int[] glyphCodes) +{ + return peer.createGlyphVector (this, ctx, glyphCodes); +} + +/** + * Produces a new {@link Font} based on the current font, adjusted to a + * new size and style. + * + * @param style The style of the newly created font. + * @param size The size of the newly created font. + * + * @return A clone of the current font, with the specified size and style. + * + * @since 1.2 + */ + public Font deriveFont (int style, float size) +{ + return peer.deriveFont (this, style, size); +} + +/** + * Produces a new {@link Font} based on the current font, adjusted to a + * new size. + * + * @param size The size of the newly created font. + * + * @return A clone of the current font, with the specified size. + * + * @since 1.2 + */ + public Font deriveFont (float size) +{ + return peer.deriveFont (this, size); +} + +/** + * Produces a new {@link Font} based on the current font, adjusted to a + * new style. + * + * @param style The style of the newly created font. + * + * @return A clone of the current font, with the specified style. + * + * @since 1.2 + */ + public Font deriveFont (int style) +{ + return peer.deriveFont (this, style); +} + +/** + * Produces a new {@link Font} based on the current font, adjusted to a + * new style and subjected to a new affine transformation. + * + * @param style The style of the newly created font. + * @param a The transformation to apply. + * + * @return A clone of the current font, with the specified style and + * transform. + * + * @throws IllegalArgumentException If transformation is + * <code>null</code>. + * + * @since 1.2 + */ + public Font deriveFont (int style, AffineTransform a) +{ + if (a == null) + throw new IllegalArgumentException ("Affine transformation is null"); + + return peer.deriveFont (this, style, a); +} + +/** + * Produces a new {@link Font} based on the current font, subjected + * to a new affine transformation. + * + * @param a The transformation to apply. + * + * @return A clone of the current font, with the specified transform. + * + * @throws IllegalArgumentException If transformation is + * <code>null</code>. + * + * @since 1.2 + */ + public Font deriveFont (AffineTransform a) +{ + if (a == null) + throw new IllegalArgumentException ("Affine transformation is null"); + + return peer.deriveFont (this, a); +} + +/** + * Produces a new {@link Font} based on the current font, adjusted to a + * new set of attributes. + * + * @param attributes Attributes of the newly created font. + * + * @return A clone of the current font, with the specified attributes. + * + * @since 1.2 + */ + public Font deriveFont (Map attributes) +{ + return peer.deriveFont (this, attributes); +} + +/** + * Returns a map of chracter attributes which this font currently has set. + * + * @return A map of chracter attributes which this font currently has set. + * + * @see #getAvailableAttributes() + * @see java.text.AttributedCharacterIterator.Attribute + * @see java.awt.font.TextAttribute + */ + public Map getAttributes () +{ + return peer.getAttributes (this); +} + +/** + * Returns an array of chracter attribute keys which this font understands. + * + * @return An array of chracter attribute keys which this font understands. + * + * @see #getAttributes() + * @see java.text.AttributedCharacterIterator.Attribute + * @see java.awt.font.TextAttribute + */ + public AttributedCharacterIterator.Attribute[] getAvailableAttributes() +{ + return peer.getAvailableAttributes (this); +} + +/** + * Returns a baseline code (one of {@link #ROMAN_BASELINE}, {@link + * #CENTER_BASELINE} or {@link #HANGING_BASELINE}) indicating which baseline + * this font will measure baseline offsets for, when presenting glyph + * metrics for a given character. + * + * Baseline offsets describe the position of a glyph relative to an + * invisible line drawn under, through the center of, or over a line of + * rendered text, respectively. Different scripts use different baseline + * modes, so clients should not assume all baseline offsets in a glyph + * vector are from a common baseline. + * + * @param c The character code to select a baseline mode for. + * + * @return The baseline mode which would be used in a glyph associated + * with the provided character. + * + * @since 1.2 + * + * @see LineMetrics#getBaselineOffsets() + */ + public byte getBaselineFor (char c) +{ + return peer.getBaselineFor (this, c); +} + +/** + * Returns the family name of this font. A family name describes a + * typographic style (such as Helvetica or Palatino). It is more specific + * than a logical font name (such as Sans Serif) but less specific than a + * font face name (such as Helvetica Bold). + * + * @param lc The locale in which to describe the name of the font family. + * + * @return A string containing the font family name, localized for the + * provided locale. + * + * @since 1.2 + * + * @see #getName() + * @see #getFontName() + * @see GraphicsEnvironment#getAvailableFontFamilyNames() + * @see Locale + */ + public String getFamily (Locale lc) +{ + return peer.getFamily (this, lc); +} + +/** + * Returns a font appropriate for the given attribute set. + * + * @param attributes The attributes required for the new font. + * + * @return A new Font with the given attributes. + * + * @since 1.2 + * + * @see java.awt.font.TextAttribute + */ + public static Font getFont (Map attributes) +{ + return getFontFromToolkit (null, attributes); +} + +/** + * Returns the font face name of the font. A font face name describes a + * specific variant of a font family (such as Helvetica Bold). It is more + * specific than both a font family name (such as Helvetica) and a logical + * font name (such as Sans Serif). + * + * @return The font face name of the font. + * + * @since 1.2 + * + * @see #getName() + * @see #getFamily() + */ + public String getFontName () +{ + return peer.getFontName (this); +} + +/** + * Returns the font face name of the font. A font face name describes a + * specific variant of a font family (such as Helvetica Bold). It is more + * specific than both a font family name (such as Helvetica). + * + * @param lc The locale in which to describe the name of the font face. + * + * @return A string containing the font face name, localized for the + * provided locale. + * + * @since 1.2 + * + * @see #getName() + * @see #getFamily() + */ + public String getFontName (Locale lc) +{ + return peer.getFontName (this, lc); +} + +/** + * Returns the italic angle of this font, a measurement of its slant when + * style is {@link #ITALIC}. The precise meaning is the inverse slope of a + * caret line which "best measures" the font's italic posture. + * + * @return The italic angle. + * + * @see java.awt.font.TextAttribute#POSTURE + */ + public float getItalicAngle () +{ + return peer.getItalicAngle (this); +} + +/** + * Returns a {@link LineMetrics} object constructed with the specified + * text and {@link FontRenderContext}. + * + * @param text The string to calculate metrics from. + * @param begin Index of first character in <code>text</code> to measure. + * @param limit Index of last character in <code>text</code> to measure. + * @param rc Context for calculating precise glyph placement and hints. + * + * @return A new {@link LineMetrics} object. + * + * @throws IndexOutOfBoundsException if the range [begin, limit] is + * invalid in <code>text</code>. + */ + public LineMetrics getLineMetrics(String text, int begin, + int limit, FontRenderContext rc) +{ + return peer.getLineMetrics (this, new StringCharacterIterator (text), + begin, limit, rc); +} + +/** + * Returns a {@link LineMetrics} object constructed with the specified + * text and {@link FontRenderContext}. + * + * @param chars The string to calculate metrics from. + * @param begin Index of first character in <code>text</code> to measure. + * @param limit Index of last character in <code>text</code> to measure. + * @param rc Context for calculating precise glyph placement and hints. + * + * @return A new {@link LineMetrics} object. + * + * @throws IndexOutOfBoundsException if the range [begin, limit] is + * invalid in <code>chars</code>. + */ + public LineMetrics getLineMetrics(char[] chars, int begin, + int limit, FontRenderContext rc) +{ + return peer.getLineMetrics (this, new StringCharacterIterator (new String(chars)), + begin, limit, rc); +} + +/** + * Returns a {@link LineMetrics} object constructed with the specified + * text and {@link FontRenderContext}. + * + * @param ci The string to calculate metrics from. + * @param begin Index of first character in <code>text</code> to measure. + * @param limit Index of last character in <code>text</code> to measure. + * @param rc Context for calculating precise glyph placement and hints. + * + * @return A new {@link LineMetrics} object. + * + * @throws IndexOutOfBoundsException if the range [begin, limit] is + * invalid in <code>ci</code>. + */ + public LineMetrics getLineMetrics (CharacterIterator ci, int begin, + int limit, FontRenderContext rc) +{ + return peer.getLineMetrics (this, ci, begin, limit, rc); +} + +/** + * Returns the maximal bounding box of all the bounding boxes in this + * font, when the font's bounding boxes are evaluated in a given {@link + * FontRenderContext} + * + * @param rc Context in which to evaluate bounding boxes. + * + * @return The maximal bounding box. + */ + public Rectangle2D getMaxCharBounds (FontRenderContext rc) +{ + return peer.getMaxCharBounds (this, rc); +} + +/** + * Returns the glyph code this font uses to represent missing glyphs. This + * code will be present in glyph vectors when the font was unable to + * locate a glyph to represent a particular character code. + * + * @return The missing glyph code. + * + * @since 1.2 + */ + public int getMissingGlyphCode () +{ + return peer.getMissingGlyphCode (this); +} + +/** + * Returns the overall number of glyphs in this font. This number is one + * more than the greatest glyph code used in any glyph vectors this font + * produces. In other words, glyph codes are taken from the range + * <code>[ 0, getNumGlyphs() - 1 ]</code>. + * + * @return The number of glyphs in this font. + * + * @since 1.2 + */ + public int getNumGlyphs () +{ + return peer.getMissingGlyphCode (this); +} + +/** + * Returns the PostScript Name of this font. + * + * @return The PostScript Name of this font. + * + * @since 1.2 + * + * @see #getName() + * @see #getFamily() + * @see #getFontName() + */ + public String getPSName () +{ + return peer.getPostScriptName (this); +} + +/** + * Returns the logical bounds of the specified string when rendered with this + * font in the specified {@link FontRenderContext}. This box will include the + * glyph origin, ascent, advance, height, and leading, but may not include all + * diacritics or accents. To get the complete visual bounding box of all the + * glyphs in a run of text, use the {@link TextLayout#getBounds} method of + * {@link TextLayout}. + * + * @param str The string to measure. + * @param frc The context in which to make the precise glyph measurements. + * + * @return A bounding box covering the logical bounds of the specified text. + * + * @see #createGlyphVector(FontRenderContext, String) + */ + public Rectangle2D getStringBounds (String str, FontRenderContext frc) +{ + return getStringBounds (str, 0, str.length () - 1, frc); +} + +/** + * Returns the logical bounds of the specified string when rendered with this + * font in the specified {@link FontRenderContext}. This box will include the + * glyph origin, ascent, advance, height, and leading, but may not include all + * diacritics or accents. To get the complete visual bounding box of all the + * glyphs in a run of text, use the {@link TextLayout#getBounds} method of + * {@link TextLayout}. + * + * @param str The string to measure. + * @param begin Index of the first character in <code>str</code> to measure. + * @param limit Index of the last character in <code>str</code> to measure. + * @param frc The context in which to make the precise glyph measurements. + * + * @return A bounding box covering the logical bounds of the specified text. + * + * @throws IndexOutOfBoundsException if the range [begin, limit] is + * invalid in <code>str</code>. + * + * @since 1.2 + * + * @see #createGlyphVector(FontRenderContext, String) + */ + public Rectangle2D getStringBounds (String str, int begin, + int limit, FontRenderContext frc) +{ + return peer.getStringBounds (this, new StringCharacterIterator(str), begin, limit, frc); +} + +/** + * Returns the logical bounds of the specified string when rendered with this + * font in the specified {@link FontRenderContext}. This box will include the + * glyph origin, ascent, advance, height, and leading, but may not include all + * diacritics or accents. To get the complete visual bounding box of all the + * glyphs in a run of text, use the {@link TextLayout#getBounds} method of + * {@link TextLayout}. + * + * @param ci The text to measure. + * @param begin Index of the first character in <code>ci</code> to measure. + * @param limit Index of the last character in <code>ci</code> to measure. + * @param frc The context in which to make the precise glyph measurements. + * + * @return A bounding box covering the logical bounds of the specified text. + * + * @throws IndexOutOfBoundsException if the range [begin, limit] is + * invalid in <code>ci</code>. + * + * @since 1.2 + * + * @see #createGlyphVector(FontRenderContext, CharacterIterator) + */ + public Rectangle2D getStringBounds (CharacterIterator ci, int begin, + int limit, FontRenderContext frc) +{ + return peer.getStringBounds (this, ci, begin, limit, frc); +} + +/** + * Returns the logical bounds of the specified string when rendered with this + * font in the specified {@link FontRenderContext}. This box will include the + * glyph origin, ascent, advance, height, and leading, but may not include all + * diacritics or accents. To get the complete visual bounding box of all the + * glyphs in a run of text, use the {@link TextLayout#getBounds} method of + * {@link TextLayout}. + * + * @param chars The text to measure. + * @param begin Index of the first character in <code>ci</code> to measure. + * @param limit Index of the last character in <code>ci</code> to measure. + * @param frc The context in which to make the precise glyph measurements. + * + * @return A bounding box covering the logical bounds of the specified text. + * + * @throws IndexOutOfBoundsException if the range [begin, limit] is + * invalid in <code>chars</code>. + * + * @since 1.2 + * + * @see #createGlyphVector(FontRenderContext, char[]) + */ + public Rectangle2D getStringBounds (char[] chars, int begin, + int limit, FontRenderContext frc) +{ + return peer.getStringBounds (this, new StringCharacterIterator (new String (chars)), + begin, limit, frc); +} + +/** + * Returns a copy of the affine transformation this font is currently + * subject to, if any. + * + * @return The current transformation. + */ + public AffineTransform getTransform () +{ + return peer.getTransform (this); +} + +/** + * Indicates whether this font's line metrics are uniform. A font may be + * composed of several "subfonts", each covering a different code range, + * and each with their own line metrics. A font with no subfonts, or + * subfonts with identical line metrics, is said to have "uniform" line + * metrics. + * + * @return Whether this font has uniform line metrics. + * + * @see LineMetrics + * @see #getLineMetrics(String, FontRenderContext) + */ + public boolean hasUniformLineMetrics () +{ + return peer.hasUniformLineMetrics (this); +} + +/** + * Indicates whether this font is subject to a non-identity affine + * transformation. + * + * @return <code>true</code> iff the font has a non-identity affine + * transformation applied to it. + */ + public boolean isTransformed () +{ + return peer.isTransformed (this); +} + +/** + * Produces a glyph vector representing a full layout fo the specified + * text in this font. Full layouts may include complex shaping and + * reordering operations, for scripts such as Arabic or Hindi. + * + * Bidirectional (bidi) layout is not performed in this method; text + * should have its bidi direction specified with one of the flags {@link + * #LAYOUT_LEFT_TO_RIGHT} or {@link #LAYOUT_RIGHT_TO_LEFT}. + * + * Some types of layout (notably Arabic glyph shaping) may examine context + * characters beyond the bounds of the indicated range, in order to select + * an appropriate shape. The flags {@link #LAYOUT_NO_START_CONTEXT} and + * {@link #LAYOUT_NO_LIMIT_CONTEXT} can be provided to prevent these extra + * context areas from being examined, for instance if they contain invalid + * characters. + * + * @param frc Context in which to perform the layout. + * @param chars Text to perform layout on. + * @param start Index of first character to perform layout on. + * @param limit Index of last character to perform layout on. + * @param flags Combination of flags controlling layout. + * + * @return A new {@link GlyphVector} representing the specified text. + * + * @throws IndexOutOfBoundsException if the range [begin, limit] is + * invalid in <code>chars</code>. + */ + public GlyphVector layoutGlyphVector (FontRenderContext frc, + char[] chars, int start, + int limit, int flags) +{ + return peer.layoutGlyphVector (this, frc, chars, start, limit, flags); +} + + +/** + * Returns a native peer object for this font. + * + * @return A native peer object for this font. + * + * @deprecated + */ + public FontPeer getPeer () +{ + return peer; +} + + +/** + * Returns a hash value for this font. + * + * @return A hash for this font. + */ + public int hashCode() +{ + return this.toString().hashCode(); +} + + +/** + * Tests whether or not the specified object is equal to this font. This + * will be true if and only if: + * <P> + * <ul> + * <li>The object is not <code>null</code>. + * <li>The object is an instance of <code>Font</code>. + * <li>The object has the same names, style, size, and transform as this object. + * </ul> + * + * @return <code>true</code> if the specified object is equal to this + * object, <code>false</code> otherwise. + */ +public boolean +equals(Object obj) +{ + if (obj == null) + return(false); + + if (!(obj instanceof Font)) + return(false); + + Font f = (Font)obj; + + return (f.getName ().equals (this.getName ()) && + f.getFamily ().equals (this.getFamily ()) && + f.getFontName ().equals (this.getFontName ()) && + f.getTransform ().equals (this.getTransform ()) && + f.getSize() == this.getSize() && + f.getStyle() == this.getStyle()); +} + +/*************************************************************************/ + +/** + * Returns a string representation of this font. + * + * @return A string representation of this font. + */ +public String +toString() +{ + String styleString = ""; + + switch (getStyle ()) + { + case 0: + styleString = "plain"; + break; + case 1: + styleString = "bold"; + break; + case 2: + styleString = "italic"; + break; + default: + styleString = "unknown"; + } + + return getClass ().getName () + + "[family=" + getFamily () + + ",name=" + getFontName () + + ",style=" + styleString + + ",size=" + getSize () + "]"; +} + + + /** + * Determines the line metrics for a run of text. + * + * @param str the text run to be measured. + * + * @param frc the font rendering parameters that are used for the + * measurement. The exact placement and size of text slightly + * depends on device-specific characteristics, for instance + * the device resolution or anti-aliasing. For this reason, + * the returned measurement will only be accurate if the + * passed <code>FontRenderContext</code> correctly reflects + * the relevant parameters. Hence, <code>frc</code> should be + * obtained from the same <code>Graphics2D</code> that will + * be used for drawing, and any rendering hints should be set + * to the desired values before obtaining <code>frc</code>. + * + * @see java.awt.Graphics2D#getFontRenderContext() + */ + public LineMetrics getLineMetrics(String str, FontRenderContext frc) + { + return getLineMetrics (str, 0, str.length () - 1, frc); + } + +} // class Font + diff --git a/libjava/classpath/java/awt/FontFormatException.java b/libjava/classpath/java/awt/FontFormatException.java new file mode 100644 index 0000000..6ec8757 --- /dev/null +++ b/libjava/classpath/java/awt/FontFormatException.java @@ -0,0 +1,65 @@ +/* FontFormatException.java -- the specified font is bad + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * Thrown when a specified font is bad. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see Font + * @since 1.3 + * @status updated to 1.4 + */ +public class FontFormatException extends Exception +{ + /** + * Compatible with JDK 1.4+. + */ + private static final long serialVersionUID = -4481290147811361272L; + + /** + * Create a new instance with the specified detailed error message. + * + * @param message the detailed error message + */ + public FontFormatException(String message) + { + super(message); + } +} // class FontFormatException diff --git a/libjava/classpath/java/awt/FontMetrics.java b/libjava/classpath/java/awt/FontMetrics.java new file mode 100644 index 0000000..e702a62 --- /dev/null +++ b/libjava/classpath/java/awt/FontMetrics.java @@ -0,0 +1,425 @@ +/* FontMetrics.java -- Information about about a fonts display characteristics + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.font.FontRenderContext; +import java.awt.font.LineMetrics; +import java.awt.geom.Rectangle2D; +import java.text.CharacterIterator; + +// FIXME: I leave many methods basically unimplemented. This +// should be reviewed. + +/** + * This class returns information about the display characteristics of + * a font. It is abstract, and concrete subclasses should implement at + * least the following methods: + * + * <ul> + * <li>getAscent()</li> + * <li>getDescent()</li> + * <li>getLeading()</li> + * <li>getMaxAdvance()</li> + * <li>charWidth(char)</li> + * <li>charsWidth(char[], int, int)</li> + * </ul> + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public abstract class FontMetrics implements java.io.Serializable +{ + // Serialization constant. + private static final long serialVersionUID = 1681126225205050147L; + + /** + * This is the font for which metrics will be returned. + */ + protected Font font; + + /** + * Initializes a new instance of <code>FontMetrics</code> for the + * specified font. + * + * @param font The font to return metric information for. + */ + protected FontMetrics(Font font) + { + this.font = font; + } + + /** + * Returns the font that this object is creating metric information fo. + * + * @return The font for this object. + */ + public Font getFont() + { + return font; + } + + /** + * Returns the leading, or spacing between lines, for this font. + * + * @return The font leading. + */ + public int getLeading() + { + return 0; + } + + /** + * Returns the ascent of the font, which is the distance from the base + * to the top of the majority of characters in the set. Some characters + * can exceed this value however. + * + * @return The font ascent. + */ + public int getAscent() + { + return 1; + } + + /** + * Returns the descent of the font, which is the distance from the base + * to the bottom of the majority of characters in the set. Some characters + * can exceed this value however. + * + * @return The font descent. + */ + public int getDescent() + { + return 1; + } + + /** + * Returns the height of a line in this font. This will be the sum + * of the leading, the ascent, and the descent. + * + * @return The height of the font. + */ + public int getHeight() + { + return getAscent() + getDescent() + getLeading(); + } + + /** + * Returns the maximum ascent value. This is the maximum distance any + * character in the font rised above the baseline. + * + * @return The maximum ascent for this font. + */ + public int getMaxAscent() + { + return getAscent(); + } + + /** + * Returns the maximum descent value. This is the maximum distance any + * character in the font extends below the baseline. + * + * @return The maximum descent for this font. + */ + public int getMaxDescent() + { + return getMaxDecent(); + } + + /** + * Returns the maximum descent value. This is the maximum distance any + * character in the font extends below the baseline. + * + * @return The maximum descent for this font. + * + * @deprecated This method is deprecated in favor of + * <code>getMaxDescent()</code>. + */ + public int getMaxDecent() + { + return getDescent(); + } + + /** + * Returns the width of the widest character in the font. + * + * @return The width of the widest character in the font. + */ + public int getMaxAdvance() + { + return -1; + } + + /** + * Returns the width of the specified character. + * + * @param ch The character to return the width of. + * + * @return The width of the specified character. + */ + public int charWidth(int ch) + { + return charWidth((char) ch); + } + + /** + * Returns the width of the specified character. + * + * @param ch The character to return the width of. + * + * @return The width of the specified character. + */ + public int charWidth(char ch) + { + return 1; + } + + /** + * Returns the total width of the specified string + * + * @param str The string to return the width of. + * + * @return The width of the string. + */ + public int stringWidth(String str) + { + char[] buf = new char[str.length()]; + str.getChars(0, str.length(), buf, 0); + + return charsWidth(buf, 0, buf.length); + } + + /** + * Returns the total width of the specified character array. + * + * @param buf The character array containing the data. + * @param offset The offset into the array to start calculating from. + * @param len The total number of bytes to process. + * + * @return The width of the requested characters. + */ + public int charsWidth(char[] buf, int offset, int len) + { + int total_width = 0; + for (int i = offset; i < len; i++) + total_width += charWidth(buf[i]); + return total_width; + } + + /** + * Returns the total width of the specified byte array. + * + * @param buf The byte array containing the data. + * @param offset The offset into the array to start calculating from. + * @param len The total number of bytes to process. + * + * @return The width of the requested characters. + */ + public int bytesWidth(byte[] buf, int offset, int len) + { + int total_width = 0; + for (int i = offset; i < len; i++) + total_width = charWidth((char) buf[i]); + + return total_width; + } + + /** + * Returns the widths of the first 256 characters in the font. + * + * @return The widths of the first 256 characters in the font. + */ + public int[] getWidths() + { + int[] result = new int[256]; + for (char i = 0; i < 256; i++) + result[i] = charWidth(i); + return result; + } + + /** + * Returns a string representation of this object. + * + * @return A string representation of this object. + */ + public String toString() + { + return (this.getClass() + "[font=" + font + ",ascent=" + getAscent() + + ",descent=" + getDescent() + ",height=" + getHeight() + "]"); + } + + // Generic FontRenderContext used when getLineMetrics is called with a + // plain Graphics object. + private static final FontRenderContext gRC = new FontRenderContext(null, + false, + false); + + /** + * Returns a {@link LineMetrics} object constructed with the + * specified text and the {@link FontRenderContext} of the Graphics + * object when it is an instance of Graphics2D or a generic + * FontRenderContext with a null transform, not anti-aliased and not + * using fractional metrics. + * + * @param text The string to calculate metrics from. + * @param g The Graphics object that will be used. + * + * @return A new {@link LineMetrics} object. + */ + public LineMetrics getLineMetrics(String text, Graphics g) + { + return getLineMetrics(text, 0, text.length(), g); + } + + /** + * Returns a {@link LineMetrics} object constructed with the + * specified text and the {@link FontRenderContext} of the Graphics + * object when it is an instance of Graphics2D or a generic + * FontRenderContext with a null transform, not anti-aliased and not + * using fractional metrics. + * + * @param text The string to calculate metrics from. + * @param begin Index of first character in <code>text</code> to measure. + * @param limit Index of last character in <code>text</code> to measure. + * @param g The Graphics object that will be used. + * + * @return A new {@link LineMetrics} object. + * + * @throws IndexOutOfBoundsException if the range [begin, limit] is + * invalid in <code>text</code>. + */ + public LineMetrics getLineMetrics(String text, int begin, int limit, + Graphics g) + { + FontRenderContext rc; + if (g instanceof Graphics2D) + rc = ((Graphics2D) g).getFontRenderContext(); + else + rc = gRC; + return font.getLineMetrics(text, begin, limit, rc); + } + + /** + * Returns a {@link LineMetrics} object constructed with the + * specified text and the {@link FontRenderContext} of the Graphics + * object when it is an instance of Graphics2D or a generic + * FontRenderContext with a null transform, not anti-aliased and not + * using fractional metrics. + * + * @param chars The string to calculate metrics from. + * @param begin Index of first character in <code>text</code> to measure. + * @param limit Index of last character in <code>text</code> to measure. + * @param g The Graphics object that will be used. + * + * @return A new {@link LineMetrics} object. + * + * @throws IndexOutOfBoundsException if the range [begin, limit] is + * invalid in <code>text</code>. + */ + public LineMetrics getLineMetrics(char[] chars, int begin, int limit, + Graphics g) + { + FontRenderContext rc; + if (g instanceof Graphics2D) + rc = ((Graphics2D) g).getFontRenderContext(); + else + rc = gRC; + return font.getLineMetrics(chars, begin, limit, rc); + } + + /** + * Returns a {@link LineMetrics} object constructed with the + * specified text and the {@link FontRenderContext} of the Graphics + * object when it is an instance of Graphics2D or a generic + * FontRenderContext with a null transform, not anti-aliased and not + * using fractional metrics. + * + * @param ci An iterator over the string to calculate metrics from. + * @param begin Index of first character in <code>text</code> to measure. + * @param limit Index of last character in <code>text</code> to measure. + * @param g The Graphics object that will be used. + * + * @return A new {@link LineMetrics} object. + * + * @throws IndexOutOfBoundsException if the range [begin, limit] is + * invalid in <code>text</code>. + */ + public LineMetrics getLineMetrics(CharacterIterator ci, int begin, + int limit, Graphics g) + { + FontRenderContext rc; + if (g instanceof Graphics2D) + rc = ((Graphics2D) g).getFontRenderContext(); + else + rc = gRC; + return font.getLineMetrics(ci, begin, limit, rc); + } + + public Rectangle2D getStringBounds(String str, Graphics context) + { + return font.getStringBounds(str, getFontRenderContext(context)); + } + + public Rectangle2D getStringBounds(String str, int beginIndex, int limit, + Graphics context) + { + return font.getStringBounds(str, beginIndex, limit, + getFontRenderContext(context)); + } + + public Rectangle2D getStringBounds(char[] chars, int beginIndex, int limit, + Graphics context) + { + return font.getStringBounds(chars, beginIndex, limit, + getFontRenderContext(context)); + } + + public Rectangle2D getStringBounds(CharacterIterator ci, int beginIndex, + int limit, Graphics context) + { + return font.getStringBounds(ci, beginIndex, limit, + getFontRenderContext(context)); + } + + private FontRenderContext getFontRenderContext(Graphics context) + { + if (context instanceof Graphics2D) + return ((Graphics2D) context).getFontRenderContext(); + + return gRC; + } +} diff --git a/libjava/classpath/java/awt/Frame.java b/libjava/classpath/java/awt/Frame.java new file mode 100644 index 0000000..0cb97f8 --- /dev/null +++ b/libjava/classpath/java/awt/Frame.java @@ -0,0 +1,649 @@ +/* Frame.java -- AWT toplevel window + Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.peer.FramePeer; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Vector; + +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +/** + * This class is a top-level window with a title bar and window + * decorations. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class Frame extends Window implements MenuContainer +{ +/** + * Constant for the default cursor. + * @deprecated Replaced by <code>Cursor.DEFAULT_CURSOR</code> instead. + */ +public static final int DEFAULT_CURSOR = Cursor.DEFAULT_CURSOR; + +/** + * Constant for a cross-hair cursor. + * @deprecated Use <code>Cursor.CROSSHAIR_CURSOR</code> instead. + */ +public static final int CROSSHAIR_CURSOR = Cursor.CROSSHAIR_CURSOR; + +/** + * Constant for a cursor over a text field. + * @deprecated Use <code>Cursor.TEXT_CURSOR</code> instead. + */ +public static final int TEXT_CURSOR = Cursor.TEXT_CURSOR; + +/** + * Constant for a cursor to display while waiting for an action to complete. + * @deprecated Use <code>Cursor.WAIT_CURSOR</code>. + */ +public static final int WAIT_CURSOR = Cursor.WAIT_CURSOR; + +/** + * Cursor used over SW corner of window decorations. + * @deprecated Use <code>Cursor.SW_RESIZE_CURSOR</code> instead. + */ +public static final int SW_RESIZE_CURSOR = Cursor.SW_RESIZE_CURSOR; + +/** + * Cursor used over SE corner of window decorations. + * @deprecated Use <code>Cursor.SE_RESIZE_CURSOR</code> instead. + */ +public static final int SE_RESIZE_CURSOR = Cursor.SE_RESIZE_CURSOR; + +/** + * Cursor used over NW corner of window decorations. + * @deprecated Use <code>Cursor.NW_RESIZE_CURSOR</code> instead. + */ +public static final int NW_RESIZE_CURSOR = Cursor.NW_RESIZE_CURSOR; + +/** + * Cursor used over NE corner of window decorations. + * @deprecated Use <code>Cursor.NE_RESIZE_CURSOR</code> instead. + */ +public static final int NE_RESIZE_CURSOR = Cursor.NE_RESIZE_CURSOR; + +/** + * Cursor used over N edge of window decorations. + * @deprecated Use <code>Cursor.N_RESIZE_CURSOR</code> instead. + */ +public static final int N_RESIZE_CURSOR = Cursor.N_RESIZE_CURSOR; + +/** + * Cursor used over S edge of window decorations. + * @deprecated Use <code>Cursor.S_RESIZE_CURSOR</code> instead. + */ +public static final int S_RESIZE_CURSOR = Cursor.S_RESIZE_CURSOR; + +/** + * Cursor used over E edge of window decorations. + * @deprecated Use <code>Cursor.E_RESIZE_CURSOR</code> instead. + */ +public static final int E_RESIZE_CURSOR = Cursor.E_RESIZE_CURSOR; + +/** + * Cursor used over W edge of window decorations. + * @deprecated Use <code>Cursor.W_RESIZE_CURSOR</code> instead. + */ +public static final int W_RESIZE_CURSOR = Cursor.W_RESIZE_CURSOR; + +/** + * Constant for a hand cursor. + * @deprecated Use <code>Cursor.HAND_CURSOR</code> instead. + */ +public static final int HAND_CURSOR = Cursor.HAND_CURSOR; + +/** + * Constant for a cursor used during window move operations. + * @deprecated Use <code>Cursor.MOVE_CURSOR</code> instead. + */ +public static final int MOVE_CURSOR = Cursor.MOVE_CURSOR; + +public static final int ICONIFIED = 1; +public static final int MAXIMIZED_BOTH = 6; +public static final int MAXIMIZED_HORIZ = 2; +public static final int MAXIMIZED_VERT = 4; +public static final int NORMAL = 0; + +// Serialization version constant +private static final long serialVersionUID = 2673458971256075116L; + +/** + * @serial The version of the class data being serialized + * // FIXME: what is this value? + */ +private int frameSerializedDataVersion; + +/** + * @serial Image used as the icon when this frame is minimized. + */ +private Image icon; + +/** + * @serial Constant used by the JDK Motif peer set. Not used in + * this implementation. + */ +private boolean mbManagement; + +/** + * @serial The menu bar for this frame. + */ +//private MenuBar menuBar = new MenuBar(); +private MenuBar menuBar; + +/** + * @serial A list of other top-level windows owned by this window. + */ +Vector ownedWindows = new Vector(); + +/** + * @serial Indicates whether or not this frame is resizable. + */ +private boolean resizable = true; + +/** + * @serial The state of this frame. + * // FIXME: What are the values here? + * This is package-private to avoid an accessor method. + */ +int state; + +/** + * @serial The title of the frame. + */ +private String title = ""; + + /** + * Maximized bounds for this frame. + */ + private Rectangle maximizedBounds; + + /** + * This field indicates whether the frame is undecorated or not. + */ + private boolean undecorated = false; + + /* + * The number used to generate the name returned by getName. + */ + private static transient long next_frame_number; + +/** + * Initializes a new instance of <code>Frame</code> that is not visible + * and has no title. + */ +public +Frame() +{ + this(""); + noteFrame(this); +} + +/** + * Initializes a new instance of <code>Frame</code> that is not visible + * and has the specified title. + * + * @param title The title of this frame. + */ +public +Frame(String title) +{ + super(); + this.title = title; + // Top-level frames are initially invisible. + visible = false; + noteFrame(this); +} + +public +Frame(GraphicsConfiguration gc) +{ + super(gc); + visible = false; + noteFrame(this); +} + +public +Frame(String title, GraphicsConfiguration gc) +{ + super(gc); + setTitle(title); + visible = false; + noteFrame(this); +} + +/** + * Returns this frame's title string. + * + * @return This frame's title string. + */ +public String +getTitle() +{ + return(title); +} + +/* + * Sets this frame's title to the specified value. + * + * @param title The new frame title. + */ +public synchronized void +setTitle(String title) +{ + this.title = title; + if (peer != null) + ((FramePeer) peer).setTitle(title); +} + +/** + * Returns this frame's icon. + * + * @return This frame's icon, or <code>null</code> if this frame does not + * have an icon. + */ +public Image +getIconImage() +{ + return(icon); +} + +/** + * Sets this frame's icon to the specified value. + * + * @icon The new icon for this frame. + */ +public synchronized void +setIconImage(Image icon) +{ + this.icon = icon; + if (peer != null) + ((FramePeer) peer).setIconImage(icon); +} + +/** + * Returns this frame's menu bar. + * + * @return This frame's menu bar, or <code>null</code> if this frame + * does not have a menu bar. + */ +public MenuBar +getMenuBar() +{ + return(menuBar); +} + +/** + * Sets this frame's menu bar. + * + * @param menuBar The new menu bar for this frame. + */ +public synchronized void +setMenuBar(MenuBar menuBar) +{ + if (peer != null) + { + if (this.menuBar != null) + this.menuBar.removeNotify(); + if (menuBar != null) + menuBar.addNotify(); + invalidateTree (); + ((FramePeer) peer).setMenuBar(menuBar); + } + this.menuBar = menuBar; +} + +/** + * Tests whether or not this frame is resizable. This will be + * <code>true</code> by default. + * + * @return <code>true</code> if this frame is resizable, <code>false</code> + * otherwise. + */ +public boolean +isResizable() +{ + return(resizable); +} + +/** + * Sets the resizability of this frame to the specified value. + * + * @param resizable <code>true</code> to make the frame resizable, + * <code>false</code> to make it non-resizable. + */ +public synchronized void +setResizable(boolean resizable) +{ + this.resizable = resizable; + if (peer != null) + ((FramePeer) peer).setResizable(resizable); +} + +/** + * Returns the cursor type of the cursor for this window. This will + * be one of the constants in this class. + * + * @return The cursor type for this frame. + * + * @deprecated Use <code>Component.getCursor()</code> instead. + */ +public int +getCursorType() +{ + return(getCursor().getType()); +} + +/** + * Sets the cursor for this window to the specified type. The specified + * type should be one of the constants in this class. + * + * @param type The cursor type. + * + * @deprecated Use <code>Component.setCursor(Cursor)</code> instead. + */ +public void +setCursor(int type) +{ + setCursor(new Cursor(type)); +} + +/** + * Removes the specified component from this frame's menu. + * + * @param menu The menu component to remove. + */ +public void +remove(MenuComponent menu) +{ + menuBar.remove(menu); +} + +/** + * Notifies this frame that it should create its native peer. + */ +private static void fireDummyEvent() +{ + EventQueue.invokeLater(new Runnable() + { + public void run() + { + // Do nothing here. + } + }); +} + +public void +addNotify() +{ + if (menuBar != null) + menuBar.addNotify(); + if (peer == null) + peer = getToolkit ().createFrame (this); + + // We now know there's a Frame (us) with a live peer, so we can start the + // fundamental queue and dispatch thread, by inserting a dummy event. + if (parent != null && parent.isDisplayable()) + fireDummyEvent(); + + super.addNotify(); +} + +public void removeNotify() +{ + if (menuBar != null) + menuBar.removeNotify(); + super.removeNotify(); + + // By now we've been disconnected from the peer, and the peer set to + // null. This is formally the same as saying "we just became + // un-displayable", so we wake up the event queue with a dummy event to + // see if it's time to shut down. + fireDummyEvent(); +} + + /** + * Returns a debugging string describing this window. + * + * @return A debugging string describing this window. + */ + protected String paramString () + { + String title = getTitle (); + + String resizable = ""; + if (isResizable ()) + resizable = ",resizable"; + + String state = ""; + switch (getState ()) + { + case NORMAL: + state = ",normal"; + break; + case ICONIFIED: + state = ",iconified"; + break; + case MAXIMIZED_BOTH: + state = ",maximized-both"; + break; + case MAXIMIZED_HORIZ: + state = ",maximized-horiz"; + break; + case MAXIMIZED_VERT: + state = ",maximized-vert"; + break; + } + + return super.paramString () + ",title=" + title + resizable + state; + } + +private static ArrayList weakFrames = new ArrayList(); + +private static void noteFrame(Frame f) +{ + weakFrames.add(new WeakReference(f)); +} + +public static Frame[] getFrames() +{ + int n = 0; + synchronized (weakFrames) + { + Iterator i = weakFrames.iterator(); + while (i.hasNext()) + { + WeakReference wr = (WeakReference) i.next(); + if (wr.get() != null) + ++n; + } + if (n == 0) + return new Frame[0]; + else + { + Frame[] frames = new Frame[n]; + n = 0; + i = weakFrames.iterator(); + while (i.hasNext()) + { + WeakReference wr = (WeakReference) i.next(); + if (wr.get() != null) + frames[n++] = (Frame) wr.get(); + } + return frames; + } + } +} + + public void setState (int state) + { + int current_state = getExtendedState (); + + if (state == NORMAL + && (current_state & ICONIFIED) != 0) + setExtendedState (current_state | ICONIFIED); + + if (state == ICONIFIED + && (current_state & ~ICONIFIED) == 0) + setExtendedState (current_state & ~ICONIFIED); + } + + public int getState () + { + /* FIXME: State might have changed in the peer... Must check. */ + + return (state & ICONIFIED) != 0 ? ICONIFIED : NORMAL; + } + + /** + * @since 1.4 + */ + public void setExtendedState (int state) + { + this.state = state; + } + + /** + * @since 1.4 + */ + public int getExtendedState () + { + return state; + } + + /** + * @since 1.4 + */ + public void setMaximizedBounds (Rectangle maximizedBounds) + { + this.maximizedBounds = maximizedBounds; + } + + /** + * Returns the maximized bounds of this frame. + * + * @return the maximized rectangle, may be null. + * + * @since 1.4 + */ + public Rectangle getMaximizedBounds () + { + return maximizedBounds; + } + + /** + * Returns whether this frame is undecorated or not. + * + * @since 1.4 + */ + public boolean isUndecorated () + { + return undecorated; + } + + /** + * Disables or enables decorations for this frame. This method can only be + * called while the frame is not displayable. + * + * @exception IllegalComponentStateException If this frame is displayable. + * + * @since 1.4 + */ + public void setUndecorated (boolean undecorated) + { + if (isDisplayable ()) + throw new IllegalComponentStateException (); + + this.undecorated = undecorated; + } + + /** + * Generate a unique name for this frame. + * + * @return A unique name for this frame. + */ + String generateName () + { + return "frame" + getUniqueLong (); + } + + private static synchronized long getUniqueLong () + { + return next_frame_number++; + } + + protected class AccessibleAWTFrame extends AccessibleAWTWindow + { + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.FRAME; + } + + public AccessibleStateSet getAccessibleState() + { + AccessibleStateSet states = super.getAccessibleStateSet(); + if (isResizable()) + states.add(AccessibleState.RESIZABLE); + if ((state & ICONIFIED) != 0) + states.add(AccessibleState.ICONIFIED); + return states; + } + } + + /** + * Gets the AccessibleContext associated with this <code>Frame</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTFrame(); + return accessibleContext; + } + +} diff --git a/libjava/classpath/java/awt/GradientPaint.java b/libjava/classpath/java/awt/GradientPaint.java new file mode 100644 index 0000000..74067f4 --- /dev/null +++ b/libjava/classpath/java/awt/GradientPaint.java @@ -0,0 +1,229 @@ +/* GradientPaint.java -- + Copyright (C) 2002, 2005, Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.ColorModel; +import gnu.java.awt.GradientPaintContext; + +/** + * A paint object that can be used to color a region by blending two colors. + * Instances of this class are immutable. + */ +public class GradientPaint implements Paint +{ + private final float x1; + private final float y1; + private final Color c1; + private final float x2; + private final float y2; + private final Color c2; + private final boolean cyclic; + + /** + * Creates a new acyclic <code>GradientPaint</code>. + * + * @param x1 the x-coordinate of the anchor point for color 1. + * @param y1 the y-coordinate of the anchor point for color 1. + * @param c1 color 1 (<code>null</code> not permitted). + * @param x2 the x-coordinate of the anchor point for color 2. + * @param y2 the y-coordinate of the anchor point for color 2. + * @param c2 the second color (<code>null</code> not permitted). + */ + public GradientPaint(float x1, float y1, Color c1, + float x2, float y2, Color c2) + { + this(x1, y1, c1, x2, y2, c2, false); + } + + /** + * Creates a new acyclic <code>GradientPaint</code>. + * + * @param p1 anchor point 1 (<code>null</code> not permitted). + * @param c1 color 1 (<code>null</code> not permitted). + * @param p2 anchor point 2 (<code>null</code> not permitted). + * @param c2 color 2 (<code>null</code> not permitted). + */ + public GradientPaint(Point2D p1, Color c1, Point2D p2, Color c2) + { + this((float) p1.getX(), (float) p1.getY(), c1, + (float) p2.getX(), (float) p2.getY(), c2, false); + } + + /** + * Creates a new cyclic or acyclic <code>GradientPaint</code>. + * + * @param x1 the x-coordinate of the anchor point for color 1. + * @param y1 the y-coordinate of the anchor point for color 1. + * @param c1 color 1 (<code>null</code> not permitted). + * @param x2 the x-coordinate of the anchor point for color 2. + * @param y2 the y-coordinate of the anchor point for color 2. + * @param c2 the second color (<code>null</code> not permitted). + * @param cyclic a flag that controls whether the gradient is cyclic or + * acyclic. + */ + public GradientPaint(float x1, float y1, Color c1, + float x2, float y2, Color c2, boolean cyclic) + { + if (c1 == null || c2 == null) + throw new NullPointerException(); + this.x1 = x1; + this.y1 = y1; + this.c1 = c1; + this.x2 = x2; + this.y2 = y2; + this.c2 = c2; + this.cyclic = cyclic; + } + + /** + * Creates a new cyclic or acyclic <code>GradientPaint</code>. + * + * @param p1 anchor point 1 (<code>null</code> not permitted). + * @param c1 color 1 (<code>null</code> not permitted). + * @param p2 anchor point 2 (<code>null</code> not permitted). + * @param c2 color 2 (<code>null</code> not permitted). + * @param cyclic a flag that controls whether the gradient is cyclic or + * acyclic. + */ + public GradientPaint(Point2D p1, Color c1, Point2D p2, Color c2, + boolean cyclic) + { + this((float) p1.getX(), (float) p1.getY(), c1, + (float) p2.getX(), (float) p2.getY(), c2, cyclic); + } + + /** + * Returns a point with the same coordinates as the anchor point for color 1. + * Note that if you modify this point, the <code>GradientPaint</code> remains + * unchanged. + * + * @return A point with the same coordinates as the anchor point for color 1. + */ + public Point2D getPoint1() + { + return new Point2D.Float(x1, y1); + } + + /** + * Returns the first color. + * + * @return The color (never <code>null</code>). + */ + public Color getColor1() + { + return c1; + } + + /** + * Returns a point with the same coordinates as the anchor point for color 2. + * Note that if you modify this point, the <code>GradientPaint</code> remains + * unchanged. + * + * @return A point with the same coordinates as the anchor point for color 2. + */ + public Point2D getPoint2() + { + return new Point2D.Float(x2, y2); + } + + /** + * Returns the second color. + * + * @return The color (never <code>null</code>). + */ + public Color getColor2() + { + return c2; + } + + /** + * Returns <code>true</code> if this <code>GradientPaint</code> instance is + * cyclic, and <code>false</code> otherwise. + * + * @return A boolean. + */ + public boolean isCyclic() + { + return cyclic; + } + + /** + * Returns the {@link PaintContext} used to generate the color pattern. + * + * @param cm the color model, used as a hint (ignored in this + * implementation). + * @param deviceBounds the device space bounding box of the painted area. + * @param userBounds the user space bounding box of the painted area. + * @param xform the transformation from user space to device space. + * @param hints any hints for choosing between rendering alternatives. + * + * @return The context for performing the paint + */ + public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, + Rectangle2D userBounds, + AffineTransform xform, + RenderingHints hints) + { + Point2D xp1 = xform.transform(getPoint1(), null); + Point2D xp2 = xform.transform(getPoint2(), null); + return new GradientPaintContext((float) xp1.getX(), (float) xp1.getY(), c1, + (float) xp2.getX(), (float) xp2.getY(), c2, cyclic); + } + + /** + * Returns the transparency code for this <code>GradientPaint</code> instance. + * This is derived from the two {@link Color} objects used in creating this + * object: if both colors are opaque, this method returns + * {@link Transparency#OPAQUE}, otherwise it returns + * {@link Transparency#TRANSLUCENT}. + * + * @return {@link Transparency#OPAQUE} or {@link Transparency#TRANSLUCENT}. + */ + public int getTransparency() + { + if (c1.getAlpha() == 255 && c2.getAlpha() == 255) + return Transparency.OPAQUE; + else + return Transparency.TRANSLUCENT; + } + +} // class GradientPaint diff --git a/libjava/classpath/java/awt/Graphics.java b/libjava/classpath/java/awt/Graphics.java new file mode 100644 index 0000000..ff26190 --- /dev/null +++ b/libjava/classpath/java/awt/Graphics.java @@ -0,0 +1,767 @@ +/* Graphics.java -- Abstract Java drawing class + Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.image.ImageObserver; +import java.text.AttributedCharacterIterator; + +/** + * This is the abstract superclass of classes for drawing to graphics + * devices such as the screen or printers. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Warren Levy (warrenl@cygnus.com) + */ +public abstract class Graphics +{ + +/* + * Instance Variables + */ + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Default constructor for subclasses. + */ +protected +Graphics() +{ +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns a copy of this <code>Graphics</code> object. + * + * @return A copy of this object. + */ +public abstract Graphics +create(); + +/*************************************************************************/ + +/** + * Returns a copy of this <code>Graphics</code> object. The origin point + * will be translated to the point (x, y) and the cliping rectangle set + * to the intersection of the clipping rectangle in this object and the + * rectangle specified by the parameters to this method. + * + * @param x The new X coordinate of the clipping region rect. + * @param y The new Y coordinate of the clipping region rect. + * @param width The width of the clipping region intersect rectangle. + * @param height The height of the clipping region intersect rectangle. + * + * @return A copy of this object, modified as specified. + */ +public Graphics +create(int x, int y, int width, int height) +{ + Graphics g = create(); + + g.translate(x, y); + // FIXME: I'm not sure if this will work. Are the old clip rect bounds + // translated above? + g.clipRect(0, 0, width, height); + + return(g); +} + +/*************************************************************************/ + +/** + * Translates this context so that its new origin point is the point + * (x, y). + * + * @param x The new X coordinate of the origin. + * @param y The new Y coordinate of the origin. + */ +public abstract void +translate(int x, int y); + +/*************************************************************************/ + +/** + * Returns the current color for this object. + * + * @return The color for this object. + */ +public abstract Color +getColor(); + +/*************************************************************************/ + +/** + * Sets the current color for this object. + * + * @param color The new color. + */ +public abstract void +setColor(Color color); + +/*************************************************************************/ + +/** + * Sets this context into "paint" mode, where the target pixels are + * completely overwritten when drawn on. + */ +public abstract void +setPaintMode(); + +/*************************************************************************/ + +/** + * Sets this context info "XOR" mode, where the targe pixles are + * XOR-ed when drawn on. + * + * @param color The color to XOR against. + */ +public abstract void +setXORMode(Color color); + +/*************************************************************************/ + +/** + * Returns the current font for this graphics context. + * + * @return The current font. + */ +public abstract Font +getFont(); + +/*************************************************************************/ + +/** + * Sets the font for this graphics context to the specified value. + * + * @param font The new font. + */ +public abstract void +setFont(Font font); + +/*************************************************************************/ + +/** + * Returns the font metrics for the current font. + * + * @return The font metrics for the current font. + */ +public FontMetrics +getFontMetrics() +{ + return(getFontMetrics(getFont())); +} + +/*************************************************************************/ + +/** + * Returns the font metrics for the specified font. + * + * @param font The font to return metrics for. + * + * @return The requested font metrics. + */ +public abstract FontMetrics +getFontMetrics(Font font); + +/*************************************************************************/ + +/** + * Returns the bounding rectangle of the clipping region for this + * graphics context. + * + * @return The bounding rectangle for the clipping region. + */ +public abstract Rectangle +getClipBounds(); + +/*************************************************************************/ + +/** + * Returns the bounding rectangle of the clipping region for this + * graphics context. + * + * @return The bounding rectangle for the clipping region. + * + * @deprecated This method is deprecated in favor of + * <code>getClipBounds()</code>. + */ +public Rectangle +getClipRect() +{ + return(getClipBounds()); +} + +/*************************************************************************/ + +/** + * Sets the clipping region to the intersection of the current clipping + * region and the rectangle determined by the specified parameters. + * + * @param x The X coordinate of the upper left corner of the intersect rect. + * @param y The Y coordinate of the upper left corner of the intersect rect. + * @param width The width of the intersect rect. + * @param height The height of the intersect rect. + */ +public abstract void +clipRect(int x, int y, int width, int height); + +/*************************************************************************/ + +/** + * Sets the clipping region to the rectangle determined by the specified + * parameters. + * + * @param x The X coordinate of the upper left corner of the rect. + * @param y The Y coordinate of the upper left corner of the rect. + * @param width The width of the rect. + * @param height The height of the rect. + */ +public abstract void +setClip(int x, int y, int width, int height); + +/*************************************************************************/ + +/** + * Returns the current clipping region as a <code>Shape</code> object. + * + * @return The clipping region as a <code>Shape</code>. + */ +public abstract Shape +getClip(); + +/*************************************************************************/ + +/** + * Sets the clipping region to the specified <code>Shape</code>. + * + * @param clip The new clipping region. + */ +public abstract void +setClip(Shape clip); + +/*************************************************************************/ + +/** + * Copies the specified rectangle to the specified offset location. + * + * @param x The X coordinate of the upper left corner of the copy rect. + * @param y The Y coordinate of the upper left corner of the copy rect. + * @param width The width of the copy rect. + * @param height The height of the copy rect. + * @param dx The offset from the X value to start drawing. + * @param dy The offset from the Y value to start drawing. + */ +public abstract void +copyArea(int x, int y, int width, int height, int dx, int dy); + +/*************************************************************************/ + +/** + * Draws a line between the two specified points. + * + * @param x1 The X coordinate of the first point. + * @param y1 The Y coordinate of the first point. + * @param x2 The X coordinate of the second point. + * @param y2 The Y coordinate of the second point. + */ +public abstract void +drawLine(int x1, int y1, int x2, int y2); + +/*************************************************************************/ + +/** + * Fills the area bounded by the specified rectangle. + * + * @param x The X coordinate of the upper left corner of the fill rect. + * @param y The Y coordinate of the upper left corner of the fill rect. + * @param width The width of the fill rect. + * @param height The height of the fill rect. + */ +public abstract void +fillRect(int x, int y, int width, int height); + +/*************************************************************************/ + +/** + * Draws the outline of the specified rectangle. + * + * @param x The X coordinate of the upper left corner of the draw rect. + * @param y The Y coordinate of the upper left corner of the draw rect. + * @param width The width of the draw rect. + * @param height The height of the draw rect. + */ +public void +drawRect(int x, int y, int width, int height) +{ + int x1 = x; + int y1 = y; + int x2 = x + width; + int y2 = y + height; + drawLine(x1, y1, x2, y1); + drawLine(x2, y1, x2, y2); + drawLine(x2, y2, x1, y2); + drawLine(x1, y2, x1, y1); +} + +/*************************************************************************/ + +/** + * Clears the specified rectangle. + * + * @param x The X coordinate of the upper left corner of the clear rect. + * @param y The Y coordinate of the upper left corner of the clear rect. + * @param width The width of the clear rect. + * @param height The height of the clear rect. + */ +public abstract void +clearRect(int x, int y, int width, int height); + +/*************************************************************************/ + +/** + * Draws the outline of the specified rectangle with rounded cornders. + * + * @param x The X coordinate of the upper left corner of the draw rect. + * @param y The Y coordinate of the upper left corner of the draw rect. + * @param width The width of the draw rect. + * @param height The height of the draw rect. + * @param arcWidth The width of the corner arcs. + * @param arcHeight The height of the corner arcs. + */ +public abstract void +drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight); + +/*************************************************************************/ + +/** + * Fills the specified rectangle with rounded cornders. + * + * @param x The X coordinate of the upper left corner of the fill rect. + * @param y The Y coordinate of the upper left corner of the fill rect. + * @param width The width of the fill rect. + * @param height The height of the fill rect. + * @param arcWidth The width of the corner arcs. + * @param arcHeight The height of the corner arcs. + */ +public abstract void +fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight); + +/*************************************************************************/ + +public void +draw3DRect(int x, int y, int width, int height, boolean raised) +{ + Color color = getColor(); + Color tl = color.brighter(); + Color br = color.darker(); + + if (!raised) + { + Color tmp = tl; + tl = br; + br = tmp; + } + + int x1 = x; + int y1 = y; + int x2 = x + width; + int y2 = y + height; + + setColor(tl); + drawLine(x1, y1, x2, y1); + drawLine(x1, y2, x1, y1); + setColor(br); + drawLine(x2, y1, x2, y2); + drawLine(x2, y2, x1, y2); + setColor(color); +} + +/** + * Fills the specified rectangle with a 3D effect + * + * @param x The X coordinate of the upper left corner of the fill rect. + * @param y The Y coordinate of the upper left corner of the fill rect. + * @param width The width of the fill rect. + * @param height The height of the fill rect. + * @param raised <code>true</code> if the rectangle appears raised, + * <code>false</code> if it should appear etched. + */ +public void +fill3DRect(int x, int y, int width, int height, boolean raised) +{ + fillRect(x, y, width, height); + draw3DRect(x, y, width-1, height-1, raised); +} + +/*************************************************************************/ + +/** + * Draws an oval that just fits within the specified rectangle. + * + * @param x The X coordinate of the upper left corner of the rect. + * @param y The Y coordinate of the upper left corner of the rect. + * @param width The width of the rect. + * @param height The height of the rect. + */ +public abstract void +drawOval(int x, int y, int width, int height); + +/*************************************************************************/ + +/** + * Fills an oval that just fits within the specified rectangle. + * + * @param x The X coordinate of the upper left corner of the rect. + * @param y The Y coordinate of the upper left corner of the rect. + * @param width The width of the rect. + * @param height The height of the rect. + */ +public abstract void +fillOval(int x, int y, int width, int height); + +/*************************************************************************/ + +/** + * Draws an arc using the specified bounding rectangle and the specified + * angle parameter. The arc is centered at the center of the rectangle. + * The arc starts at the arcAngle position and extend for arcAngle + * degrees. The degree origin is at the 3 o'clock position. + * + * @param x The X coordinate of the upper left corner of the rect. + * @param y The Y coordinate of the upper left corner of the rect. + * @param width The width of the rect. + * @param height The height of the rect. + * @param arcStart The beginning angle of the arc. + * @param arcAngle The extent of the arc. + */ +public abstract void +drawArc(int x, int y, int width, int height, int arcStart, int arcAngle); + +/*************************************************************************/ + +/** + * Fills the arc define by the specified bounding rectangle and the specified + * angle parameter. The arc is centered at the center of the rectangle. + * The arc starts at the arcAngle position and extend for arcAngle + * degrees. The degree origin is at the 3 o'clock position. + * + * @param x The X coordinate of the upper left corner of the rect. + * @param y The Y coordinate of the upper left corner of the rect. + * @param width The width of the rect. + * @param height The height of the rect. + * @param arcStart The beginning angle of the arc. + * @param arcAngle The extent of the arc. + */ +public abstract void +fillArc(int x, int y, int width, int height, int arcStart, int arcAngle); + +/*************************************************************************/ + +/** + * Draws a series of interconnected lines determined by the arrays + * of corresponding x and y coordinates. + * + * @param xPoints The X coordinate array. + * @param yPoints The Y coordinate array. + * @param npoints The number of points to draw. + */ +public abstract void +drawPolyline(int xPoints[], int yPoints[], int npoints); + +/*************************************************************************/ + +/** + * Draws a series of interconnected lines determined by the arrays + * of corresponding x and y coordinates. The figure is closed if necessary + * by connecting the first and last points. + * + * @param xPoints The X coordinate array. + * @param yPoints The Y coordinate array. + * @param npoints The number of points to draw. + */ +public abstract void +drawPolygon(int xPoints[], int yPoints[], int npoints); + +/*************************************************************************/ + +/** + * Draws the specified polygon. + * + * @param polygon The polygon to draw. + */ +public void +drawPolygon(Polygon polygon) +{ + drawPolygon(polygon.xpoints, polygon.ypoints, polygon.npoints); +} + +/*************************************************************************/ + +/** + * Fills the polygon determined by the arrays + * of corresponding x and y coordinates. + * + * @param xPoints The X coordinate array. + * @param yPoints The Y coordinate array. + * @param npoints The number of points to draw. + */ +public abstract void +fillPolygon(int xPoints[], int yPoints[], int npoints); + +/*************************************************************************/ + +/** + * Fills the specified polygon + * + * @param polygon The polygon to fill. + */ +public void +fillPolygon(Polygon polygon) +{ + fillPolygon(polygon.xpoints, polygon.ypoints, polygon.npoints); +} + +/*************************************************************************/ + +/** + * Draws the specified string starting at the specified point. + * + * @param string The string to draw. + * @param x The X coordinate of the point to draw at. + * @param y The Y coordinate of the point to draw at. + */ +public abstract void +drawString(String string, int x, int y); + +public abstract void drawString (AttributedCharacterIterator ci, int x, int y); + +/*************************************************************************/ + +/** + * Draws the specified characters starting at the specified point. + * + * @param data The array of characters to draw. + * @param offset The offset into the array to start drawing characters from. + * @param length The number of characters to draw. + * @param x The X coordinate of the point to draw at. + * @param y The Y coordinate of the point to draw at. + */ +public void +drawChars(char data[], int offset, int length, int x, int y) +{ + drawString(new String(data, offset, length), x, y); +} + +public void +drawBytes(byte[] data, int offset, int length, int x, int y) +{ + String str = new String(data, offset, length); + drawString(str, x, y); +} + +/*************************************************************************/ + +/** + * Draws all of the image that is available and returns. If the image + * is not completely loaded, <code>false</code> is returned and + * the specified iamge observer is notified as more data becomes + * available. + * + * @param image The image to draw. + * @param x The X coordinate of the point to draw at. + * @param y The Y coordinate of the point to draw at. + * @param observer The image observer to notify as data becomes available. + * + * @return <code>true</code> if all the image data is available, + * <code>false</code> otherwise. + */ +public abstract boolean +drawImage(Image image, int x, int y, ImageObserver observer); + +/*************************************************************************/ + +/** + * Draws all of the image that is available and returns. The image + * is scaled to fit in the specified rectangle. If the image + * is not completely loaded, <code>false</code> is returned and + * the specified iamge observer is notified as more data becomes + * available. + * + * @param image The image to draw. + * @param x The X coordinate of the point to draw at. + * @param y The Y coordinate of the point to draw at. + * @param width The width of the rectangle to draw in. + * @param height The height of the rectangle to draw in. + * @param observer The image observer to notify as data becomes available. + * + * @return <code>true</code> if all the image data is available, + * <code>false</code> otherwise. + */ +public abstract boolean +drawImage(Image image, int x, int y, int width, int height, + ImageObserver observer); + +/*************************************************************************/ + +/** + * Draws all of the image that is available and returns. If the image + * is not completely loaded, <code>false</code> is returned and + * the specified iamge observer is notified as more data becomes + * available. + * + * @param image The image to draw. + * @param x The X coordinate of the point to draw at. + * @param y The Y coordinate of the point to draw at. + * @param bgcolor The background color to use for the image. + * @param observer The image observer to notify as data becomes available. + * + * @return <code>true</code> if all the image data is available, + * <code>false</code> otherwise. + */ +public abstract boolean +drawImage(Image image, int x, int y, Color bgcolor, ImageObserver observer); + +/*************************************************************************/ + +/** + * Draws all of the image that is available and returns. The image + * is scaled to fit in the specified rectangle. If the image + * is not completely loaded, <code>false</code> is returned and + * the specified iamge observer is notified as more data becomes + * available. + * + * @param image The image to draw. + * @param x The X coordinate of the point to draw at. + * @param y The Y coordinate of the point to draw at. + * @param width The width of the rectangle to draw in. + * @param height The height of the rectangle to draw in. + * @param bgcolor The background color to use for the image. + * @param observer The image observer to notify as data becomes available. + * + * @return <code>true</code> if all the image data is available, + * <code>false</code> otherwise. + */ +public abstract boolean +drawImage(Image image, int x, int y, int width, int height, Color bgcolor, + ImageObserver observer); + +/*************************************************************************/ + +/** + * FIXME: Write Javadocs for this when you understand it. + */ +public abstract boolean +drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, + int sx2, int sy2, ImageObserver observer); + +/*************************************************************************/ + +/** + * FIXME: Write Javadocs for this when you understand it. + */ +public abstract boolean +drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, + int sx2, int sy2, Color bgcolor, ImageObserver observer); + +/*************************************************************************/ + +/** + * Free any resources held by this graphics context immediately instead + * of waiting for the object to be garbage collected and finalized. + */ +public abstract void +dispose(); + +/*************************************************************************/ + +/** + * Frees the resources held by this graphics context when it is + * garbage collected. + */ +public void +finalize() +{ + dispose(); +} + +/*************************************************************************/ + +/** + * Returns a string representation of this object. + * + * @return A string representation of this object. + */ +public String +toString() +{ + return getClass ().getName () + "[font=" + getFont () + ",color=" + getColor () + "]"; +} + +public boolean +hitClip(int x, int y, int width, int height) +{ + throw new UnsupportedOperationException("not implemented yet"); +} + +public Rectangle +getClipBounds(Rectangle r) +{ + Rectangle clipBounds = getClipBounds(); + + if (r == null) + return clipBounds; + + r.x = clipBounds.x; + r.y = clipBounds.y; + r.width = clipBounds.width; + r.height = clipBounds.height; + return r; +} + +} // class Graphics + diff --git a/libjava/classpath/java/awt/Graphics2D.java b/libjava/classpath/java/awt/Graphics2D.java new file mode 100644 index 0000000..3faa9dc --- /dev/null +++ b/libjava/classpath/java/awt/Graphics2D.java @@ -0,0 +1,158 @@ +/* Copyright (C) 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.renderable.RenderableImage; +import java.text.AttributedCharacterIterator; +import java.util.Map; + +/** + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public abstract class Graphics2D extends Graphics +{ + + protected Graphics2D() + { + } + + public void draw3DRect(int x, int y, int width, int height, + boolean raised) + { + super.draw3DRect(x, y, width, height, raised); + } + + public void fill3DRect(int x, int y, int width, int height, + boolean raised) + { + super.fill3DRect(x, y, width, height, raised); + } + + public abstract void draw(Shape shape); + + public abstract boolean drawImage(Image image, AffineTransform xform, + ImageObserver obs); + + public abstract void drawImage(BufferedImage image, + BufferedImageOp op, + int x, + int y); + + public abstract void drawRenderedImage(RenderedImage image, + AffineTransform xform); + + public abstract void drawRenderableImage(RenderableImage image, + AffineTransform xform); + + public abstract void drawString(String text, int x, int y); + + public abstract void drawString(String text, float x, float y); + + public abstract void drawString(AttributedCharacterIterator iterator, + int x, int y); + + public abstract void drawString(AttributedCharacterIterator iterator, + float x, float y); + + // public abstract void drawGlyphVector(GlyphVector g, float x, float y); + + public abstract void fill(Shape shape); + + public abstract boolean hit(Rectangle rect, Shape text, + boolean onStroke); + + public abstract GraphicsConfiguration getDeviceConfiguration(); + + public abstract void setComposite(Composite comp); + + public abstract void setPaint(Paint paint); + + public abstract void setStroke(Stroke stroke); + + public abstract void setRenderingHint(RenderingHints.Key hintKey, + Object hintValue); + + public abstract Object getRenderingHint(RenderingHints.Key hintKey); + + public abstract void setRenderingHints(Map hints); + + public abstract void addRenderingHints(Map hints); + + public abstract RenderingHints getRenderingHints(); + + public abstract void translate(int x, int y); + + public abstract void translate(double tx, double ty); + + public abstract void rotate(double theta); + + public abstract void rotate(double theta, double x, double y); + + public abstract void scale(double scaleX, double scaleY); + + public abstract void shear(double shearX, double shearY); + + public abstract void transform(AffineTransform Tx); + + public abstract void setTransform(AffineTransform Tx); + + public abstract AffineTransform getTransform(); + + public abstract Paint getPaint(); + + public abstract Composite getComposite(); + + public abstract void setBackground(Color color); + + public abstract Color getBackground(); + + public abstract Stroke getStroke(); + + public abstract void clip(Shape s); + + public abstract FontRenderContext getFontRenderContext (); + + public abstract void drawGlyphVector (GlyphVector g, float x, float y); +} diff --git a/libjava/classpath/java/awt/GraphicsConfigTemplate.java b/libjava/classpath/java/awt/GraphicsConfigTemplate.java new file mode 100644 index 0000000..e468883 --- /dev/null +++ b/libjava/classpath/java/awt/GraphicsConfigTemplate.java @@ -0,0 +1,106 @@ +/* GraphicsConfigTemplate.java -- a template for selecting configurations + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.io.Serializable; + +/** + * This allows filtering an array of GraphicsConfigurations for the best + * one based on various requirements. The resulting configuration has had + * all non-default attributes set as required to meet or exceed the request. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see GraphicsConfiguration + * @see GraphicsDevice + * @since 1.2 + * @status updated to 1.4 + */ +public abstract class GraphicsConfigTemplate implements Serializable +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = -8061369279557787079L; + + /** States that a feature is required to select a configuration. */ + public static final int REQUIRED = 1; + + /** + * States that a feature is preferred, but not required, to select a + * configuration. In the case of multiple valid configurations, the tie + * breaks in favor of the one with the feature. + */ + public static final int PREFERRED = 2; + + /** + * States that a feature is not necessary in the configuration. In the case + * of multiple valid configurations, the tie breaks in favor of the one + * without the feature, to reduce overhead. + */ + public static final int UNNECESSARY = 3; + + /** + * The default constructor. + */ + public GraphicsConfigTemplate() + { + } + + /** + * Returns the "best" match among the array of possible configurations, given + * the criteria of this template. + * + * @param array the array to choose from + * @return the best match + * @throws NullPointerException if array is null + */ + public abstract GraphicsConfiguration getBestConfiguration + (GraphicsConfiguration[] array); + + /** + * Returns true if the given configuration supports all the features required + * by this template. + * + * @param config the configuration to test + * @return true if it is a match + * @throws NullPointerException if config is null + */ + public abstract boolean isGraphicsConfigSupported + (GraphicsConfiguration config); +} // class GraphicsConfigTemplate diff --git a/libjava/classpath/java/awt/GraphicsConfiguration.java b/libjava/classpath/java/awt/GraphicsConfiguration.java new file mode 100644 index 0000000..6dc27793 --- /dev/null +++ b/libjava/classpath/java/awt/GraphicsConfiguration.java @@ -0,0 +1,218 @@ +/* GraphicsConfiguration.java -- describes characteristics of graphics + Copyright (C) 2000, 2001, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.VolatileImage; + +/** + * This class describes the configuration of various graphics devices, such + * as a monitor or printer. Different configurations may exist for the same + * device, according to the different native modes supported. + * + * <p>Virtual devices are supported (for example, in a multiple screen + * environment, a virtual device covers all screens simultaneously); the + * configuration will have a non-zero relative coordinate system in such + * a case. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see Window + * @see Frame + * @see GraphicsEnvironment + * @see GraphicsDevice + * @since 1.0 + * @status updated to 1.4 + */ +public abstract class GraphicsConfiguration +{ + /** + * The default constructor. + * + * @see GraphicsDevice#getConfigurations() + * @see GraphicsDevice#getDefaultConfiguration() + * @see GraphicsDevice#getBestConfiguration(GraphicsConfigTemplate) + * @see Graphics2D#getDeviceConfiguration() + */ + protected GraphicsConfiguration () + { + } + + /** + * Gets the associated device that this configuration describes. + * + * @return the device + */ + public abstract GraphicsDevice getDevice(); + + /** + * Returns a buffered image optimized to this device, so that blitting can + * be supported in the buffered image. + * + * @param w the width of the buffer + * @param h the height of the buffer + * @return the buffered image, or null if none is supported + */ + public abstract BufferedImage createCompatibleImage(int w, int h); + + /** + * Returns a buffered volatile image optimized to this device, so that + * blitting can be supported in the buffered image. Because the buffer is + * volatile, it can be optimized by native graphics accelerators. + * + * @param w the width of the buffer + * @param h the height of the buffer + * @return the buffered image, or null if none is supported + * @see Component#createVolatileImage(int, int) + * @since 1.4 + */ + public abstract VolatileImage createCompatibleVolatileImage(int w, int h); + + /** + * Returns a buffered volatile image optimized to this device, and with the + * given capabilities, so that blitting can be supported in the buffered + * image. Because the buffer is volatile, it can be optimized by native + * graphics accelerators. + * + * @param w the width of the buffer + * @param h the height of the buffer + * @param caps the desired capabilities of the image buffer + * @return the buffered image, or null if none is supported + * @throws AWTException if the capabilities cannot be met + * @since 1.4 + */ + public VolatileImage createCompatibleVolatileImage(int w, int h, + ImageCapabilities caps) + throws AWTException + { + throw new AWTException("not implemented"); + } + + /** + * Returns a buffered image optimized to this device, and with the specified + * transparency, so that blitting can be supported in the buffered image. + * + * @param w the width of the buffer + * @param h the height of the buffer + * @param transparency the transparency of the buffer + * @return the buffered image, or null if none is supported + * @see Transparency#OPAQUE + * @see Transparency#BITMASK + * @see Transparency#TRANSLUCENT + */ + public abstract BufferedImage createCompatibleImage(int w, int h, + int transparency); + + /** + * Gets the color model of the corresponding device. + * + * @return the color model + */ + public abstract ColorModel getColorModel(); + + /** + * Gets a color model for the corresponding device which supports the desired + * transparency level. + * + * @param transparency the transparency of the model + * @return the color model, with transparency + * @see Transparency#OPAQUE + * @see Transparency#BITMASK + * @see Transparency#TRANSLUCENT + */ + public abstract ColorModel getColorModel(int transparency); + + /** + * Returns a transform that maps user coordinates to device coordinates. The + * preferred mapping is about 72 user units to 1 inch (2.54 cm) of physical + * space. This is often the identity transform. The device coordinates have + * the origin at the upper left, with increasing x to the right, and + * increasing y to the bottom. + * + * @return the transformation from user space to device space + * @see #getNormalizingTransform() + */ + public abstract AffineTransform getDefaultTransform(); + + /** + * Returns a transform that maps user coordinates to device coordinates. The + * exact mapping is 72 user units to 1 inch (2.54 cm) of physical space. + * This is often the identity transform. The device coordinates have the + * origin at the upper left, with increasing x to the right, and increasing + * y to the bottom. Note that this is more accurate (and thus, sometimes more + * costly) than the default transform. + * + * @return the normalized transformation from user space to device space + * @see #getDefaultTransform() + */ + public abstract AffineTransform getNormalizingTransform(); + + /** + * Returns the bounds of the configuration, in device coordinates. If this + * is a virtual device (for example, encompassing several screens), the + * bounds may have a non-zero origin. + * + * @return the device bounds + * @since 1.3 + */ + public abstract Rectangle getBounds(); + + /** + * Returns the buffering capabilities of this configuration. + * + * @return the buffer capabilities + * @since 1.4 + */ + public BufferCapabilities getBufferCapabilities() + { + throw new Error("not implemented"); + } + + /** + * Returns the imaging capabilities of this configuration. + * + * @return the image capabilities + * @since 1.4 + */ + public ImageCapabilities getImageCapabilities() + { + throw new Error("not implemented"); + } +} // class GraphicsConfiguration diff --git a/libjava/classpath/java/awt/GraphicsDevice.java b/libjava/classpath/java/awt/GraphicsDevice.java new file mode 100644 index 0000000..95487a2 --- /dev/null +++ b/libjava/classpath/java/awt/GraphicsDevice.java @@ -0,0 +1,292 @@ +/* GraphicsDevice.java -- information about a graphics device + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.image.VolatileImage; + +/** + * This describes a graphics device available to the given environment. This + * includes screen and printer devices, and the different configurations for + * each device. Also, this allows you to create virtual devices which operate + * over a multi-screen environment. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see GraphicsEnvironment + * @see GraphicsConfiguration + * @since 1.3 + * @status updated to 1.4 + */ +public abstract class GraphicsDevice +{ + /** Device is a raster screen. */ + public static final int TYPE_RASTER_SCREEN = 0; + + /** Device is a printer. */ + public static final int TYPE_PRINTER = 1; + + /** Device is an image buffer not visible to the user. */ + public static final int TYPE_IMAGE_BUFFER = 2; + + /** The current full-screen window, or null if there is none. */ + private Window full_screen; + + /** + * The bounds of the fullscreen window before it has been switched to full + * screen. + */ + private Rectangle fullScreenOldBounds; + + /** The current display mode, or null if unknown. */ + private DisplayMode mode; + + /** + * The default constructor. + * + * @see GraphicsEnvironment#getScreenDevices() + * @see GraphicsEnvironment#getDefaultScreenDevice() + * @see GraphicsConfiguration#getDevice() + */ + protected GraphicsDevice() + { + } + + /** + * Returns the type of the device. + * + * @return the device type + * @see #TYPE_RASTER_SCREEN + * @see #TYPE_PRINTER + * @see #TYPE_IMAGE_BUFFER + */ + public abstract int getType(); + + /** + * Returns an identification string for the device. This can be + * vendor-specific, and may be useful for debugging. + * + * @return the identification + */ + public abstract String getIDstring(); + + /** + * Return all configurations valid for this device. + * + * @return an array of configurations + */ + public abstract GraphicsConfiguration[] getConfigurations(); + + /** + * Return the default configuration for this device. + * + * @return the default configuration + */ + public abstract GraphicsConfiguration getDefaultConfiguration(); + + /** + * Return the best configuration, according to the criteria in the given + * template. + * + * @param template the template to adjust by + * @return the best configuration + * @throws NullPointerException if template is null + */ + public GraphicsConfiguration getBestConfiguration + (GraphicsConfigTemplate template) + { + return template.getBestConfiguration(getConfigurations()); + } + + /** + * Returns true if the device supports full-screen exclusive mode. The + * default implementation returns true; subclass it if this is not the case. + * + * @return true if full screen support is available + * @since 1.4 + */ + public boolean isFullScreenSupported() + { + return true; + } + + /** + * Toggle the given window between full screen and normal mode. The previous + * full-screen window, if different, is restored; if the given window is + * null, no window will be full screen. If + * <code>isFullScreenSupported()</code> returns true, full screen mode is + * considered to be exclusive, which implies:<ul> + * <li>Windows cannot overlap the full-screen window. All other application + * windows will always appear beneath the full-screen window in the + * Z-order.</li> + * <li>Input method windows are disabled. It is advisable to call + * <code>Component.enableInputMethods(false)</code> to make a component + * a non-client of the input method framework.</li> + * </ul><br> + * If <code>isFullScreenSupported()</code> returns false, full-screen + * exclusive mode is simulated by resizing the window to the size of the + * screen and positioning it at (0,0). This is also what this method does. + * If a device supports real fullscreen mode then it should override this + * method as well as #isFullScreenSupported and #getFullScreenWindow. + * + * @param w the window to toggle + * @see #isFullScreenSupported() + * @see #getFullScreenWindow() + * @see #setDisplayMode(DisplayMode) + * @see Component#enableInputMethods(boolean) + * @since 1.4 + */ + public synchronized void setFullScreenWindow(Window w) + { + // Restore the previous window to normal mode and release the reference. + if (full_screen != null) + { + full_screen.setBounds(fullScreenOldBounds); + } + + full_screen = null; + + // If w != null, make it full-screen. + if (w != null) + { + fullScreenOldBounds = w.getBounds(); + full_screen = w; + DisplayMode dMode = getDisplayMode(); + full_screen.setBounds(0, 0, dMode.getWidth(), dMode.getHeight()); + full_screen.requestFocus(); + full_screen.setLocationRelativeTo(null); + } + } + + /** + * Returns the current full-screen window of the device, or null if no + * window is full-screen. + * + * @return the full-screen window + * @see #setFullScreenWindow(Window) + * @since 1.4 + */ + public Window getFullScreenWindow() + { + return full_screen; + } + + /** + * Returns whether this device supports low-level display changes. This may + * depend on whether full-screen exclusive mode is available. + * + * XXX The default implementation returns false for now. + * + * @return true if display changes are supported + * @see #setDisplayMode(DisplayMode) + * @since 1.4 + */ + public boolean isDisplayChangeSupported() + { + return false; + } + + /** + * Sets the display mode. This may be dependent on the availability of + * full-screen exclusive mode. + * + * @param mode the new mode + * @throws IllegalArgumentException if the new mode is not in getDisplayModes + * @throws UnsupportedOperationException if ! isDisplayChangeSupported() + * @see #getDisplayMode() + * @see #getDisplayModes() + * @see #isDisplayChangeSupported() + * @since 1.4 + */ + public void setDisplayMode(DisplayMode mode) + { + DisplayMode[] array = getDisplayModes(); + if (! isDisplayChangeSupported()) + throw new UnsupportedOperationException(); + int i = array == null ? 0 : array.length; + while (--i >= 0) + if (array[i].equals(mode)) + break; + if (i < 0) + throw new IllegalArgumentException(); + this.mode = mode; + } + + /** + * Returns the current display mode of this device, or null if unknown. + * + * @return the current display mode + * @see #setDisplayMode(DisplayMode) + * @see #getDisplayModes() + * @since 1.4 + */ + public DisplayMode getDisplayMode() + { + return mode; + } + + /** + * Return an array of all available display modes. This implementation + * returns a 0-length array, so subclasses must override this. + * + * @return the array of available modes + * @since 1.4 + */ + public DisplayMode[] getDisplayModes() + { + return new DisplayMode[0]; + } + + /** + * Return the number of bytes available in accelerated memory on this + * device. The device may support creation or caching on a first-come, + * first-served basis, depending on the operating system and driver. + * Memory may be a finite resource, and because of multi-threading, you + * are not guaranteed that the result of this method ensures your image + * will successfully be put in accelerated memory. A negative result means + * the memory is unlimited. The default implementation assumes no special + * memory is available, and returns 0. + * + * @return the size of accelerated memory available + * @see VolatileImage#flush() + * @see ImageCapabilities#isAccelerated() + */ + public int getAvailableAcceleratedMemory() + { + return 0; + } +} // class GraphicsDevice diff --git a/libjava/classpath/java/awt/GraphicsEnvironment.java b/libjava/classpath/java/awt/GraphicsEnvironment.java new file mode 100644 index 0000000..a82e7a3 --- /dev/null +++ b/libjava/classpath/java/awt/GraphicsEnvironment.java @@ -0,0 +1,244 @@ +/* GraphicsEnvironment.java -- information about the graphics environment + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import gnu.java.awt.ClasspathToolkit; +import gnu.classpath.SystemProperties; +import java.awt.image.BufferedImage; +import java.util.Locale; + +/** + * This descibes the collection of GraphicsDevice and Font objects available + * on a given platform. The resources might be local or remote, and specify + * the valid configurations for displaying graphics. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see GraphicsDevice + * @see GraphicsConfiguration + * @since 1.4 + * @status updated to 1.4 + */ +public abstract class GraphicsEnvironment +{ + private static GraphicsEnvironment localGraphicsEnvironment; + + /** + * The environment must be obtained from a factory or query method, hence + * this constructor is protected. + */ + protected GraphicsEnvironment() + { + } + + /** + * Returns the local graphics environment. If the java.awt.graphicsenv + * system property is set, it instantiates the specified class, + * otherwise it assume that the awt toolkit is a ClasspathToolkit + * and delegates to it to create the instance. + * + * @return the local environment + */ + public static GraphicsEnvironment getLocalGraphicsEnvironment() + { + if (localGraphicsEnvironment != null) + return localGraphicsEnvironment; + + String graphicsenv = SystemProperties.getProperty("java.awt.graphicsenv", + null); + if (graphicsenv != null) + { + try + { + // We intentionally use the bootstrap class loader. + localGraphicsEnvironment = (GraphicsEnvironment) + Class.forName(graphicsenv).newInstance(); + return localGraphicsEnvironment; + } + catch (Exception x) + { + throw (InternalError) + new InternalError("Unable to instantiate java.awt.graphicsenv") + .initCause(x); + } + } + else + { + ClasspathToolkit tk; + tk = ((ClasspathToolkit) Toolkit.getDefaultToolkit()); + localGraphicsEnvironment = tk.getLocalGraphicsEnvironment(); + return localGraphicsEnvironment; + } + } + + /** + * Check if the local environment is headless, meaning that it does not + * support a display, keyboard, or mouse. Many methods in the Abstract + * Windows Toolkit (java.awt) throw a {@link HeadlessException} if this + * returns true. + * + * This method returns true if the java.awt.headless property is set + * to "true". + * + * @return true if the environment is headless, meaning that graphics are + * unsupported + * @since 1.4 + */ + public static boolean isHeadless() + { + String headless = SystemProperties.getProperty("java.awt.headless", null); + return "true".equalsIgnoreCase(headless); + } + + /** + * Check if the given environment is headless, meaning that it does not + * support a display, keyboard, or mouse. Many methods in the Abstract + * Windows Toolkit (java.awt) throw a {@link HeadlessException} if this + * returns true. This default implementation returns isHeadless(), so + * subclasses need only override it if they differ. + * + * @return true if the environment is headless, meaning that graphics are + * unsupported + * @since 1.4 + */ + public boolean isHeadlessInstance() + { + return isHeadless(); + } + + /** + * Get an array of all the GraphicsDevice objects. + * + * @return the available graphics devices, may be 0 length + * @throws HeadlessException if the environment is headless + */ + public abstract GraphicsDevice[] getScreenDevices(); + + /** + * Get the default screen GraphicsDevice object. + * + * @return the default screen device + * @throws HeadlessException if the environment is headless + */ + public abstract GraphicsDevice getDefaultScreenDevice(); + + /** + * Return a Graphics2D object which will render into the specified image. + * + * @param image the image to render into + * @return the object that renders into the image + */ + public abstract Graphics2D createGraphics(BufferedImage image); + + /** + * Returns an array of the one-point size fonts available in this + * environment. From there, the user can select the font and derive the + * correct one of proper size and attributes, using <code>deriveFont</code>. + * Only one master version of each font appears in this array; if a font + * can be derived from another, it must be created in that way. + * + * @return the array of available fonts + * @see #getAvailableFontFamilyNames() + * @see Font#deriveFont(int, float) + * @since 1.2 + */ + public abstract Font[] getAllFonts(); + + /** + * Returns an array of the font family names available in this environment. + * This allows flexibility in choosing the style of font, while still letting + * the Font class decide its best match. + * + * @return the array of available font families + * @see #getAllFonts() + * @see Font#getFamily() + * @since 1.2 + */ + public abstract String[] getAvailableFontFamilyNames(); + + /** + * Returns an array of the font family names available in this environment, + * localized to the current Locale if l is non-null. This allows + * flexibility in choosing the style of font, while still letting the Font + * class decide its best match. + * + * @param l the locale to use + * @return the array of available font families, localized + * @see #getAllFonts() + * @see Font#getFamily() + * @since 1.2 + */ + public abstract String[] getAvailableFontFamilyNames(Locale l); + + /** + * Returns the point where a window should be centered. You should probably + * also check that the window fits within the screen bounds. The default + * simply returns the center of the maximum window bounds; subclasses should + * override this if native objects (like scrollbars) make that off-centered. + * + * @return the centering point + * @throws HeadlessException if the environment is headless + * @see #getMaximumWindowBounds() + * @since 1.4 + */ + public Point getCenterPoint() + { + Rectangle r = getMaximumWindowBounds(); + return new Point(r.x + r.width / 2, r.y + r.height / 2); + } + + /** + * Returns the maximum bounds for a centered window object. The default + * implementation simply returns the bounds of the default configuration + * of the default screen; subclasses should override this to if native + * objects (like scrollbars) reduce what is truly available. Also, + * subclasses should override this if the window should be centered across + * a multi-screen display. + * + * @return the maximum window bounds + * @throws HeadlessException if the environment is headless + * @see #getCenterPoint() + * @see GraphicsConfiguration#getBounds() + * @see Toolkit#getScreenInsets(GraphicsConfiguration) + * @since 1.4 + */ + public Rectangle getMaximumWindowBounds() + { + return getDefaultScreenDevice().getDefaultConfiguration().getBounds(); + } +} // class GraphicsEnvironment diff --git a/libjava/classpath/java/awt/GridBagConstraints.java b/libjava/classpath/java/awt/GridBagConstraints.java new file mode 100644 index 0000000..8d8b4fa --- /dev/null +++ b/libjava/classpath/java/awt/GridBagConstraints.java @@ -0,0 +1,195 @@ +/* GridBagConstraints.java -- Constraints for GridBag layout manager + Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.io.Serializable; + +/** + * This specifies the constraints for a component managed by the + * GridBagLayout layout manager. + */ +public class GridBagConstraints implements Cloneable, Serializable +{ + static final long serialVersionUID = -1000070633030801713L; + + /** Fill in both directions. */ + public static final int BOTH = 1; + /** Don't fill. */ + public static final int NONE = 0; + /** Fill horizontally. */ + public static final int HORIZONTAL = 2; + /** Fill vertically. */ + public static final int VERTICAL = 3; + + /** Position in the center. */ + public static final int CENTER = 10; + /** Position to the east. */ + public static final int EAST = 13; + /** Position to the north. */ + public static final int NORTH = 11; + /** Position to the northeast. */ + public static final int NORTHEAST = 12; + /** Position to the northwest. */ + public static final int NORTHWEST = 18; + /** Position to the south. */ + public static final int SOUTH = 15; + /** Position to the southeast. */ + public static final int SOUTHEAST = 14; + /** Position to the southwest. */ + public static final int SOUTHWEST = 16; + /** Position to the west. */ + public static final int WEST = 17; + + /** Occupy all remaining cells except last cell. */ + public static final int RELATIVE = -1; + /** Occupy all remaining cells. */ + public static final int REMAINDER = 0; + + /** + * Position to where the first text line would end. Equals to NORTHEAST for + * horizontal left-to-right orientations. + */ + public static final int FIRST_LINE_END = 24; + + /** + * Position to where the first text line would start. Equals to NORTHWEST for + * horizontal left-to-right orientations. + */ + public static final int FIRST_LINE_START = 23; + + /** + * Position to where the last text line would end. Equals to SOUTHEAST for + * horizontal left-to-right orientations. + */ + public static final int LAST_LINE_END = 26; + + /** + * Position to where the last text line would start. Equals to SOUTHWEST for + * horizontal left-to-right orientations. + */ + public static final int LAST_LINE_START = 25; + + /** + * Position to where a text line would end. Equals to EAST for + * left-to-right orientations. + */ + public static final int LINE_END = 22; + + /** + * Position to where a text line would start. Equals to WEST for + * left-to-right orientations. + */ + public static final int LINE_START = 21; + + /** + * Position to where a page ends. Equals SOUTH for horizontal orientations. + */ + public static final int PAGE_END = 20; + + /** + * Position to where a page starts. Equals NORTH for horizontal orientations. + */ + public static final int PAGE_START = 19; + + public int anchor; + public int fill; + public int gridheight; + public int gridwidth; + public int gridx; + public int gridy; + public Insets insets; + public int ipadx; + public int ipady; + public double weightx; + public double weighty; + + /** Create a copy of this object. */ + public Object clone () + { + try + { + GridBagConstraints g = (GridBagConstraints) super.clone (); + g.insets = (Insets) insets.clone (); + return g; + } + catch (CloneNotSupportedException _) + { + // Can't happen. + return null; + } + } + + /** Create a new GridBagConstraints object with the default + * parameters. */ + public GridBagConstraints () + { + this.anchor = CENTER; + this.fill = NONE; + this.gridx = RELATIVE; + this.gridy = RELATIVE; + this.gridwidth = 1; + this.gridheight = 1; + this.ipadx = 0; + this.ipady = 0; + this.insets = new Insets (0, 0, 0, 0); + this.weightx = 0; + this.weighty = 0; + } + + /** Create a new GridBagConstraints object with the indicated + * parameters. */ + public GridBagConstraints (int gridx, int gridy, + int gridwidth, int gridheight, + double weightx, double weighty, + int anchor, int fill, + Insets insets, int ipadx, int ipady) + { + this.anchor = anchor; + this.fill = fill; + this.gridx = gridx; + this.gridy = gridy; + this.gridwidth = gridwidth; + this.gridheight = gridheight; + this.ipadx = ipadx; + this.ipady = ipady; + this.insets = insets; + this.weightx = weightx; + this.weighty = weighty; + } +} diff --git a/libjava/classpath/java/awt/GridBagLayout.java b/libjava/classpath/java/awt/GridBagLayout.java new file mode 100644 index 0000000..767610c --- /dev/null +++ b/libjava/classpath/java/awt/GridBagLayout.java @@ -0,0 +1,1069 @@ +/* GridBagLayout - Layout manager for components according to GridBagConstraints + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; + +/** + * @author Michael Koch (konqueror@gmx.de) + * @author Jeroen Frijters (jeroen@frijters.net) + */ +public class GridBagLayout + implements Serializable, LayoutManager2 +{ + private static final long serialVersionUID = 8838754796412211005L; + + protected static final int MINSIZE = 1; + protected static final int PREFERREDSIZE = 2; + protected static final int MAXGRIDSIZE = 512; + + // comptable remembers the original contraints given to us. + // internalcomptable is used to keep track of modified constraint values + // that we calculate, particularly when we are given RELATIVE and + // REMAINDER constraints. + // Constraints kept in comptable are never modified, and constraints + // kept in internalcomptable can be modified internally only. + protected Hashtable comptable; + private Hashtable internalcomptable; + protected GridBagLayoutInfo layoutInfo; + protected GridBagConstraints defaultConstraints; + + public double[] columnWeights; + public int[] columnWidths; + public double[] rowWeights; + public int[] rowHeights; + + public GridBagLayout () + { + this.comptable = new Hashtable(); + this.internalcomptable = new Hashtable(); + this.defaultConstraints= new GridBagConstraints(); + } + + /** + * Helper method to calc the sum of a range of elements in an int array. + */ + private int sumIntArray (int[] array, int upto) + { + int result = 0; + + for (int i = 0; i < upto; i++) + result += array [i]; + + return result; + } + + /** + * Helper method to calc the sum of all elements in an int array. + */ + private int sumIntArray (int[] array) + { + return sumIntArray(array, array.length); + } + + /** + * Helper method to calc the sum of all elements in an double array. + */ + private double sumDoubleArray (double[] array) + { + double result = 0; + + for (int i = 0; i < array.length; i++) + result += array [i]; + + return result; + } + + public void addLayoutComponent (String name, Component component) + { + // do nothing here. + } + + public void removeLayoutComponent (Component component) + { + // do nothing here + } + + public void addLayoutComponent (Component component, Object constraints) + { + if (constraints == null) + return; + + if (!(constraints instanceof GridBagConstraints)) + throw new IllegalArgumentException("constraints " + + constraints + + " are not an instance of GridBagConstraints"); + + setConstraints (component, (GridBagConstraints) constraints); + } + + public Dimension preferredLayoutSize (Container parent) + { + if (parent == null) + return new Dimension (0, 0); + + GridBagLayoutInfo li = getLayoutInfo (parent, PREFERREDSIZE); + return getMinSize (parent, li); + } + + public Dimension minimumLayoutSize (Container parent) + { + if (parent == null) + return new Dimension (0, 0); + + GridBagLayoutInfo li = getLayoutInfo (parent, MINSIZE); + return getMinSize (parent, li); + } + + public Dimension maximumLayoutSize (Container target) + { + return new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + public void layoutContainer (Container parent) + { + arrangeGrid (parent); + } + + public float getLayoutAlignmentX (Container target) + { + return Component.CENTER_ALIGNMENT; + } + + public float getLayoutAlignmentY (Container target) + { + return Component.CENTER_ALIGNMENT; + } + + public void invalidateLayout (Container target) + { + this.layoutInfo = null; + } + + public void setConstraints (Component component, + GridBagConstraints constraints) + { + GridBagConstraints clone = (GridBagConstraints) constraints.clone(); + + if (clone.gridx < 0) + clone.gridx = GridBagConstraints.RELATIVE; + + if (clone.gridy < 0) + clone.gridy = GridBagConstraints.RELATIVE; + + if (clone.gridwidth == 0) + clone.gridwidth = GridBagConstraints.REMAINDER; + else if (clone.gridwidth < 0 + && clone.gridwidth != GridBagConstraints.REMAINDER + && clone.gridwidth != GridBagConstraints.RELATIVE) + clone.gridwidth = 1; + + if (clone.gridheight == 0) + clone.gridheight = GridBagConstraints.REMAINDER; + else if (clone.gridheight < 0 + && clone.gridheight != GridBagConstraints.REMAINDER + && clone.gridheight != GridBagConstraints.RELATIVE) + clone.gridheight = 1; + + comptable.put (component, clone); + } + + public GridBagConstraints getConstraints (Component component) + { + return (GridBagConstraints) (lookupConstraints (component).clone()); + } + + protected GridBagConstraints lookupConstraints (Component component) + { + GridBagConstraints result = (GridBagConstraints) comptable.get (component); + + if (result == null) + { + setConstraints (component, defaultConstraints); + result = (GridBagConstraints) comptable.get (component); + } + + return result; + } + + private GridBagConstraints lookupInternalConstraints (Component component) + { + GridBagConstraints result = + (GridBagConstraints) internalcomptable.get (component); + + if (result == null) + { + result = (GridBagConstraints) lookupConstraints(component).clone(); + internalcomptable.put (component, result); + } + + return result; + } + + /** + * @since 1.1 + */ + public Point getLayoutOrigin () + { + if (layoutInfo == null) + return new Point (0, 0); + + return new Point (layoutInfo.pos_x, layoutInfo.pos_y); + } + + /** + * @since 1.1 + */ + public int[][] getLayoutDimensions () + { + int[][] result = new int [2][]; + if (layoutInfo == null) + { + result[0] = new int[0]; + result[1] = new int[0]; + + return result; + } + + result [0] = new int [layoutInfo.cols]; + System.arraycopy (layoutInfo.colWidths, 0, result [0], 0, layoutInfo.cols); + result [1] = new int [layoutInfo.rows]; + System.arraycopy (layoutInfo.rowHeights, 0, result [1], 0, layoutInfo.rows); + return result; + } + + public double[][] getLayoutWeights () + { + double[][] result = new double [2][]; + if (layoutInfo == null) + { + result[0] = new double[0]; + result[1] = new double[0]; + + return result; + } + + result [0] = new double [layoutInfo.cols]; + System.arraycopy (layoutInfo.colWeights, 0, result [0], 0, layoutInfo.cols); + result [1] = new double [layoutInfo.rows]; + System.arraycopy (layoutInfo.rowWeights, 0, result [1], 0, layoutInfo.rows); + return result; + } + + /** + * @since 1.1 + */ + public Point location (int x, int y) + { + if (layoutInfo == null) + return new Point (0, 0); + + int col; + int row; + int pixel_x = layoutInfo.pos_x; + int pixel_y = layoutInfo.pos_y; + + for (col = 0; col < layoutInfo.cols; col++) + { + int w = layoutInfo.colWidths [col]; + if (x < pixel_x + w) + break; + + pixel_x += w; + } + + for (row = 0; row < layoutInfo.rows; row++) + { + int h = layoutInfo.rowHeights [row]; + if (y < pixel_y + h) + break; + + pixel_y += h; + } + + return new Point (col, row); + } + + /** + * Obsolete. + */ + protected void AdjustForGravity (GridBagConstraints gbc, Rectangle rect) + { + // FIXME + throw new Error ("Not implemented"); + } + + /** + * Obsolete. + */ + protected void ArrangeGrid (Container parent) + { + Component[] components = parent.getComponents(); + + if (components.length == 0) + return; + + GridBagLayoutInfo info = getLayoutInfo (parent, PREFERREDSIZE); + if (info.cols == 0 && info.rows == 0) + return; + layoutInfo = info; + + // DEBUG + //dumpLayoutInfo (layoutInfo); + + for(int i = 0; i < components.length; i++) + { + Component component = components [i]; + + // If component is not visible we dont have to care about it. + if (!component.isVisible()) + continue; + + GridBagConstraints constraints = + lookupInternalConstraints(component); + + int cellx = sumIntArray(layoutInfo.colWidths, constraints.gridx); + int celly = sumIntArray(layoutInfo.rowHeights, constraints.gridy); + int cellw = sumIntArray(layoutInfo.colWidths, + constraints.gridx + constraints.gridwidth) - cellx; + int cellh = sumIntArray(layoutInfo.rowHeights, + constraints.gridy + constraints.gridheight) - celly; + + Insets insets = constraints.insets; + if (insets != null) + { + cellx += insets.left; + celly += insets.top; + cellw -= insets.left + insets.right; + cellh -= insets.top + insets.bottom; + } + + Dimension dim = component.getPreferredSize(); + + // Note: Documentation says that padding is added on both sides, but + // visual inspection shows that the Sun implementation only adds it + // once, so we do the same. + dim.width += constraints.ipadx; + dim.height += constraints.ipady; + + switch(constraints.fill) + { + case GridBagConstraints.HORIZONTAL: + dim.width = cellw; + break; + case GridBagConstraints.VERTICAL: + dim.height = cellh; + break; + case GridBagConstraints.BOTH: + dim.width = cellw; + dim.height = cellh; + break; + } + + int x; + int y; + + switch(constraints.anchor) + { + case GridBagConstraints.NORTH: + x = cellx + (cellw - dim.width) / 2; + y = celly; + break; + case GridBagConstraints.SOUTH: + x = cellx + (cellw - dim.width) / 2; + y = celly + cellh - dim.height; + break; + case GridBagConstraints.WEST: + x = cellx; + y = celly + (cellh - dim.height) / 2; + break; + case GridBagConstraints.EAST: + x = cellx + cellw - dim.width; + y = celly + (cellh - dim.height) / 2; + break; + case GridBagConstraints.NORTHEAST: + x = cellx + cellw - dim.width; + y = celly; + break; + case GridBagConstraints.NORTHWEST: + x = cellx; + y = celly; + break; + case GridBagConstraints.SOUTHEAST: + x = cellx + cellw - dim.width; + y = celly + cellh - dim.height; + break; + case GridBagConstraints.SOUTHWEST: + x = cellx; + y = celly + cellh - dim.height; + break; + default: + x = cellx + (cellw - dim.width) / 2; + y = celly + (cellh - dim.height) / 2; + break; + } + + component.setBounds(layoutInfo.pos_x + x, layoutInfo.pos_y + y, dim.width, dim.height); + } + + // DEBUG + //dumpLayoutInfo (layoutInfo); + } + + /** + * Obsolete. + */ + protected GridBagLayoutInfo GetLayoutInfo (Container parent, int sizeflag) + { + if (sizeflag != MINSIZE && sizeflag != PREFERREDSIZE) + throw new IllegalArgumentException(); + + Dimension parentDim = parent.getSize (); + Insets parentInsets = parent.getInsets (); + parentDim.width -= parentInsets.left + parentInsets.right; + parentDim.height -= parentInsets.top + parentInsets.bottom; + + int current_y = 0; + int max_x = 0; + int max_y = 0; + + // Guaranteed to contain the last component added to the given row + // or column, whose gridwidth/height is not REMAINDER. + HashMap lastInRow = new HashMap(); + HashMap lastInCol = new HashMap(); + + Component[] components = parent.getComponents(); + + // Components sorted by gridwidths/heights, + // smallest to largest, with REMAINDER and RELATIVE at the end. + // These are useful when determining sizes and weights. + ArrayList sortedByWidth = new ArrayList(components.length); + ArrayList sortedByHeight = new ArrayList(components.length); + + // STEP 1: first we figure out how many rows/columns + for (int i = 0; i < components.length; i++) + { + Component component = components [i]; + + // If component is not visible we dont have to care about it. + if (!component.isVisible()) + continue; + + // When looking up the constraint for the first time, check the + // original unmodified constraint. After the first time, always + // refer to the internal modified constraint. + GridBagConstraints originalConstraints = lookupConstraints (component); + GridBagConstraints constraints = (GridBagConstraints) originalConstraints.clone(); + internalcomptable.put(component, constraints); + + // Cases: + // + // 1. gridy == RELATIVE, gridx == RELATIVE + // + // use y as the row number; check for the next + // available slot at row y + // + // 2. only gridx == RELATIVE + // + // check for the next available slot at row gridy + // + // 3. only gridy == RELATIVE + // + // check for the next available slot at column gridx + // + // 4. neither gridx or gridy == RELATIVE + // + // nothing to check; just add it + + + // cases 1 and 2 + if(constraints.gridx == GridBagConstraints.RELATIVE) + { + if (constraints.gridy == GridBagConstraints.RELATIVE) + constraints.gridy = current_y; + + int x; + + // Check the component that occupies the right-most spot in this + // row. We want to add this component after it. + // If this row is empty, add to the 0 position. + if (!lastInRow.containsKey(new Integer(constraints.gridy))) + x = 0; + else + { + Component lastComponent = (Component) lastInRow.get(new Integer(constraints.gridy)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + x = lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth); + } + + // Determine if this component will fit in the slot vertically. + // If not, bump it over to where it does fit. + for (int y = constraints.gridy + 1; y < constraints.gridy + Math.max(1, constraints.gridheight); y++) + { + if (lastInRow.containsKey(new Integer(y))) + { + Component lastComponent = (Component) lastInRow.get(new Integer(y)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + x = Math.max (x, + lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth)); + } + } + + constraints.gridx = x; + } + // case 3 + else if(constraints.gridy == GridBagConstraints.RELATIVE) + { + int y; + // Check the component that occupies the bottom-most spot in + // this column. We want to add this component below it. + // If this column is empty, add to the 0 position. + if (!lastInCol.containsKey(new Integer(constraints.gridx))) + y = 0; + else + { + Component lastComponent = (Component)lastInCol.get(new Integer(constraints.gridx)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + y = lastConstraints.gridy + Math.max(1, lastConstraints.gridheight); + } + + // Determine if this component will fit in the slot horizontally. + // If not, bump it down to where it does fit. + for (int x = constraints.gridx + 1; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++) + { + if (lastInCol.containsKey(new Integer(x))) + { + Component lastComponent = (Component) lastInCol.get(new Integer(x)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + y = Math.max (y, + lastConstraints.gridy + Math.max(1, lastConstraints.gridheight)); + } + } + + constraints.gridy = y; + } + // case 4: do nothing + + max_x = Math.max(max_x, + constraints.gridx + Math.max(1, constraints.gridwidth)); + max_y = Math.max(max_y, + constraints.gridy + Math.max(1, constraints.gridheight)); + + sortBySpan(component, constraints.gridwidth, sortedByWidth, true); + sortBySpan(component, constraints.gridheight, sortedByHeight, false); + + // Update our reference points for RELATIVE gridx and gridy. + if(constraints.gridwidth == GridBagConstraints.REMAINDER) + { + current_y = constraints.gridy + Math.max(1, constraints.gridheight); + } + else if (constraints.gridwidth != GridBagConstraints.REMAINDER) + { + for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++) + { + if(lastInRow.containsKey(new Integer(y))) + { + Component lastComponent = (Component) lastInRow.get(new Integer(y)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + if (constraints.gridx > lastConstraints.gridx) + { + lastInRow.put(new Integer(y), component); + } + } + else + { + lastInRow.put(new Integer(y), component); + } + } + + for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++) + { + if(lastInCol.containsKey(new Integer(x))) + { + Component lastComponent = (Component) lastInCol.get(new Integer(x)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + if (constraints.gridy > lastConstraints.gridy) + { + lastInCol.put(new Integer(x), component); + } + } + else + { + lastInCol.put(new Integer(x), component); + } + } + } + } // end of STEP 1 + + GridBagLayoutInfo info = new GridBagLayoutInfo(max_x, max_y); + + // Check if column widths and row heights are overridden. + + for (int x = 0; x < max_x; x++) + { + if(columnWidths != null && columnWidths.length > x) + info.colWidths[x] = columnWidths[x]; + if(columnWeights != null && columnWeights.length > x) + info.colWeights[x] = columnWeights[x]; + } + + for (int y = 0; y < max_y; y++) + { + if(rowHeights != null && rowHeights.length > y) + info.rowHeights[y] = rowHeights[y]; + if(rowWeights != null && rowWeights.length > y) + info.rowWeights[y] = rowWeights[y]; + } + + // STEP 2: Fix up any cells with width/height as REMAINDER/RELATIVE. + for (int i = 0; i < components.length; i++) + { + Component component = components [i]; + + // If component is not visible we dont have to care about it. + if (!component.isVisible()) + continue; + + GridBagConstraints constraints = lookupInternalConstraints (component); + + if(constraints.gridwidth == GridBagConstraints.REMAINDER || constraints.gridwidth == GridBagConstraints.RELATIVE) + { + if(constraints.gridwidth == GridBagConstraints.REMAINDER) + { + for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++) + { + if (lastInRow.containsKey(new Integer(y))) + { + Component lastComponent = (Component) lastInRow.get(new Integer(y)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + + if (lastConstraints.gridwidth == GridBagConstraints.RELATIVE) + { + constraints.gridx = max_x - 1; + break; + } + else + { + constraints.gridx = Math.max (constraints.gridx, + lastConstraints.gridx + Math.max (1, lastConstraints.gridwidth)); + } + } + } + constraints.gridwidth = max_x - constraints.gridx; + } + else if (constraints.gridwidth == GridBagConstraints.RELATIVE) + { + constraints.gridwidth = max_x - constraints.gridx - 1; + } + + // Re-sort + sortedByWidth.remove(sortedByWidth.indexOf(component)); + sortBySpan(component, constraints.gridwidth, sortedByWidth, true); + } + + if(constraints.gridheight == GridBagConstraints.REMAINDER || constraints.gridheight == GridBagConstraints.RELATIVE) + { + if(constraints.gridheight == GridBagConstraints.REMAINDER) + { + for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++) + { + if (lastInCol.containsKey(new Integer(x))) + { + Component lastComponent = (Component) lastInRow.get(new Integer(x)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + + if (lastConstraints.gridheight == GridBagConstraints.RELATIVE) + { + constraints.gridy = max_y - 1; + break; + } + else + { + constraints.gridy = Math.max (constraints.gridy, + lastConstraints.gridy + Math.max (1, lastConstraints.gridheight)); + } + } + } + constraints.gridheight = max_y - constraints.gridy; + } + else if (constraints.gridheight == GridBagConstraints.RELATIVE) + { + constraints.gridheight = max_y - constraints.gridy - 1; + } + + // Re-sort + sortedByHeight.remove(sortedByHeight.indexOf(component)); + sortBySpan(component, constraints.gridheight, sortedByHeight, false); + } + } // end of STEP 2 + + // STEP 3: Determine sizes and weights for columns. + for (int i = 0; i < sortedByWidth.size(); i++) + { + Component component = (Component) sortedByWidth.get(i); + + // If component is not visible we dont have to care about it. + if (!component.isVisible()) + continue; + + GridBagConstraints constraints = lookupInternalConstraints (component); + + int width = (sizeflag == PREFERREDSIZE) ? + component.getPreferredSize().width : + component.getMinimumSize().width; + + if(constraints.insets != null) + width += constraints.insets.left + constraints.insets.right; + + width += constraints.ipadx; + + distributeSizeAndWeight(width, + constraints.weightx, + constraints.gridx, + constraints.gridwidth, + info.colWidths, + info.colWeights); + } // end of STEP 3 + + // STEP 4: Determine sizes and weights for rows. + for (int i = 0; i < sortedByHeight.size(); i++) + { + Component component = (Component) sortedByHeight.get(i); + + // If component is not visible we dont have to care about it. + if (!component.isVisible()) + continue; + + GridBagConstraints constraints = lookupInternalConstraints (component); + + int height = (sizeflag == PREFERREDSIZE) ? + component.getPreferredSize().height : + component.getMinimumSize().height; + + if(constraints.insets != null) + height += constraints.insets.top + constraints.insets.bottom; + + height += constraints.ipady; + + distributeSizeAndWeight(height, + constraints.weighty, + constraints.gridy, + constraints.gridheight, + info.rowHeights, + info.rowWeights); + } // end of STEP 4 + + // Adjust cell sizes iff parent size not zero. + if (parentDim.width > 0 && parentDim.height > 0) + { + calcCellSizes (info.colWidths, info.colWeights, parentDim.width); + calcCellSizes (info.rowHeights, info.rowWeights, parentDim.height); + } + + int totalWidth = sumIntArray(info.colWidths); + int totalHeight = sumIntArray(info.rowHeights); + + // Make sure pos_x and pos_y are never negative. + if (totalWidth >= parentDim.width) + info.pos_x = parentInsets.left; + else + info.pos_x = parentInsets.left + (parentDim.width - totalWidth) / 2; + + if (totalHeight >= parentDim.height) + info.pos_y = parentInsets.top; + else + info.pos_y = parentInsets.top + (parentDim.height - totalHeight) / 2; + + // DEBUG + //dumpLayoutInfo (info); + + return info; + } + + /** + * Obsolete. + */ + protected Dimension GetMinSize (Container parent, GridBagLayoutInfo info) + { + if (parent == null || info == null) + return new Dimension (0, 0); + + Insets insets = parent.getInsets(); + int width = sumIntArray (info.colWidths) + insets.left + insets.right; + int height = sumIntArray (info.rowHeights) + insets.top + insets.bottom; + return new Dimension (width, height); + } + + /** + * @since 1.4 + */ + protected Dimension getMinSize (Container parent, GridBagLayoutInfo info) + { + return GetMinSize (parent, info); + } + + /** + * Helper method used by GetLayoutInfo to keep components sorted, either + * by gridwidth or gridheight. + * + * @param component Component to add to the sorted list. + * @param span Either the component's gridwidth or gridheight. + * @param list <code>ArrayList</code> of components, sorted by + * their span. + * @param sortByWidth Flag indicating sorting index. If true, sort by + * width. Otherwise, sort by height. + * FIXME: Use a better sorting algorithm. + */ + private void sortBySpan (Component component, int span, ArrayList list, boolean sortByWidth) + { + if (span == GridBagConstraints.REMAINDER + || span == GridBagConstraints.RELATIVE) + { + // Put all RELATIVE and REMAINDER components at the end. + list.add(component); + } + else + { + int i = 0; + if (list.size() > 0) + { + GridBagConstraints gbc = lookupInternalConstraints((Component) list.get(i)); + int otherspan = sortByWidth ? + gbc.gridwidth : + gbc.gridheight; + while (otherspan != GridBagConstraints.REMAINDER + && otherspan != GridBagConstraints.RELATIVE + && span >= otherspan) + { + i++; + if (i < list.size()) + { + gbc = lookupInternalConstraints((Component) list.get(i)); + otherspan = sortByWidth ? + gbc.gridwidth : + gbc.gridheight; + } + else + break; + } + } + list.add(i, component); + } + } + + /** + * Helper method used by GetLayoutInfo to distribute a component's size + * and weight. + * + * @param size Preferred size of component, with inset and padding + * already added. + * @param weight Weight of component. + * @param start Starting position of component. Either + * constraints.gridx or gridy. + * @param span Span of component. either contraints.gridwidth or + * gridheight. + * @param sizes Sizes of rows or columns. + * @param weights Weights of rows or columns. + */ + private void distributeSizeAndWeight (int size, double weight, + int start, int span, + int[] sizes, double[] weights) + { + if (span == 1) + { + sizes[start] = Math.max(sizes[start], size); + weights[start] = Math.max(weights[start], weight); + } + else + { + int numOccupied = span; + int lastOccupied = -1; + + for(int i = start; i < start + span; i++) + { + if (sizes[i] == 0.0) + numOccupied--; + else + { + size -= sizes[i]; + lastOccupied = i; + } + } + + // A component needs to occupy at least one row. + if(numOccupied == 0) + sizes[start + span - 1] = size; + else if (size > 0) + sizes[lastOccupied] += size; + + calcCellWeights(weight, weights, start, span); + } + } + + /** + * Helper method used by GetLayoutInfo to calculate weight distribution. + * @param weight Weight of component. + * @param weights Weights of rows/columns. + * @param start Starting position of component in grid (gridx/gridy). + * @param span Span of component (gridwidth/gridheight). + */ + private void calcCellWeights (double weight, double[] weights, int start, int span) + { + double totalWeight = 0.0; + for(int k = start; k < start + span; k++) + totalWeight += weights[k]; + + if(weight > totalWeight) + { + if (totalWeight == 0.0) + { + weights[start + span - 1] += weight; + } + else + { + double diff = weight - totalWeight ; + double remaining = diff; + + for(int k = start; k < start + span; k++) + { + double extraWeight = diff * weights[k] / totalWeight; + weights[k] += extraWeight; + remaining -= extraWeight; + } + + if (remaining > 0.0 && weights[start + span - 1] != 0.0) + { + weights[start + span - 1] += remaining; + } + } + } + } + + /** + * Helper method used by GetLayoutInfo to distribute extra space + * based on weight distribution. + * + * @param sizes Sizes of rows/columns. + * @param weights Weights of rows/columns. + * @param range Dimension of container. + */ + private void calcCellSizes (int[] sizes, double[] weights, int range) + { + int totalSize = sumIntArray (sizes); + double totalWeight = sumDoubleArray (weights); + + int diff = range - totalSize; + + if (diff == 0) + return; + + for (int i = 0; i < sizes.length; i++) + { + int newsize = (int) (sizes[i] + (((double) diff) * weights [i] / totalWeight )); + + if (newsize > 0) + sizes[i] = newsize; + } + } + + private void dumpLayoutInfo (GridBagLayoutInfo info) + { + System.out.println ("GridBagLayoutInfo:"); + System.out.println ("cols: " + info.cols + ", rows: " + info.rows); + System.out.print ("colWidths: "); + dumpArray(info.colWidths); + System.out.print ("rowHeights: "); + dumpArray(info.rowHeights); + System.out.print ("colWeights: "); + dumpArray(info.colWeights); + System.out.print ("rowWeights: "); + dumpArray(info.rowWeights); + } + + private void dumpArray(int[] array) + { + String sep = ""; + for(int i = 0; i < array.length; i++) + { + System.out.print(sep); + System.out.print(array[i]); + sep = ", "; + } + System.out.println(); + } + + private void dumpArray(double[] array) + { + String sep = ""; + for(int i = 0; i < array.length; i++) + { + System.out.print(sep); + System.out.print(array[i]); + sep = ", "; + } + System.out.println(); + } + + /** + * @since 1.4 + */ + protected void arrangeGrid (Container parent) + { + ArrangeGrid (parent); + } + + /** + * @since 1.4 + */ + protected GridBagLayoutInfo getLayoutInfo (Container parent, int sizeflag) + { + return GetLayoutInfo (parent, sizeflag); + } + + /** + * @since 1.4 + */ + protected void adjustForGravity (GridBagConstraints gbc, Rectangle rect) + { + AdjustForGravity (gbc, rect); + } +} diff --git a/libjava/classpath/java/awt/GridBagLayoutInfo.java b/libjava/classpath/java/awt/GridBagLayoutInfo.java new file mode 100644 index 0000000..43ba09d --- /dev/null +++ b/libjava/classpath/java/awt/GridBagLayoutInfo.java @@ -0,0 +1,70 @@ +/* GridBagLayoutInfo - + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.io.Serializable; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +class GridBagLayoutInfo implements Serializable +{ + private static final long serialVersionUID = -4899416460737170217L; + + int pos_x; + int pos_y; + int cols; + int rows; + int colWidths[]; + int rowHeights[]; + double colWeights[]; + double rowWeights[]; + + GridBagLayoutInfo (int cols, int rows) + { + this.pos_x = 0; + this.pos_y = 0; + this.cols = cols; + this.rows = rows; + this.colWidths = new int [cols]; + this.rowHeights = new int [rows]; + this.colWeights = new double [cols]; + this.rowWeights = new double [rows]; + } +} diff --git a/libjava/classpath/java/awt/GridLayout.java b/libjava/classpath/java/awt/GridLayout.java new file mode 100644 index 0000000..80d9641 --- /dev/null +++ b/libjava/classpath/java/awt/GridLayout.java @@ -0,0 +1,360 @@ +/* GridLayout.java -- Grid-based layout engine + Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.io.Serializable; + +/** This class implements a grid-based layout scheme. Components are + * all given the same size and are laid out from left to right and top + * to bottom. A GridLayout is configured with a number of rows and a + * number of columns. If both are specified, then the number of + * columns is ignored and is derived from the number of rows and the + * total number of components. If either is zero then that dimension + * is computed based on the actual size of the container. An + * exception is thrown if an attempt is made to set both the number of + * rows and the number of columns to 0. This class also supports + * horizontal and vertical gaps; these are used as spacing between + * cells. + * + * @author Tom Tromey (tromey@redhat.com) + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class GridLayout implements LayoutManager, Serializable +{ + static final long serialVersionUID = -7411804673224730901L; + + /** Add a new component to the layout. This particular implementation + * does nothing. + * @param name The name of the component to add. + * @param comp The component to add. + */ + public void addLayoutComponent (String name, Component comp) + { + // Nothing. + } + + /** Return the number of columns in this layout. */ + public int getColumns () + { + return cols; + } + + /** Return the horizontal gap. */ + public int getHgap () + { + return hgap; + } + + /** Return the number of rows in this layout. */ + public int getRows () + { + return rows; + } + + /** Return the vertical gap. */ + public int getVgap () + { + return vgap; + } + + /** Create a new <code>GridLayout</code> with one row and any number + * of columns. Both gaps are set to 0. + */ + public GridLayout () + { + this (1, 0, 0, 0); + } + + /** Create a new <code>GridLayout</code> with the specified number + * of rows and columns. Both gaps are set to 0. Note that the row + * and column settings cannot both be zero. If both the row and + * column values are non-zero, the rows value takes precedence. + * @param rows Number of rows + * @param cols Number of columns + * @exception IllegalArgumentException If rows and columns are both + * 0, or if either are negative + */ + public GridLayout (int rows, int cols) + { + this (rows, cols, 0, 0); + } + + /** Create a new GridLayout with the specified number of rows and + * columns and the specified gaps. + * Note that the row and column settings cannot both be + * zero. If both the row and column values are non-zero, the rows value + * takes precedence. + * @param rows Number of rows + * @param cols Number of columns + * @param hgap The horizontal gap + * @param vgap The vertical gap + * @exception IllegalArgumentException If rows and columns are both + * 0, if either are negative, or if either gap is negative + */ + public GridLayout (int rows, int cols, int hgap, int vgap) + { + if (rows < 0) + throw new IllegalArgumentException ("number of rows cannot be negative"); + if (cols < 0) + throw new IllegalArgumentException ("number of columns cannot be negative"); + if (rows == 0 && cols == 0) + throw new IllegalArgumentException ("both rows and columns cannot be 0"); + if (hgap < 0) + throw new IllegalArgumentException ("horizontal gap must be nonnegative"); + if (vgap < 0) + throw new IllegalArgumentException ("vertical gap must be nonnegative"); + this.rows = rows; + this.cols = cols; + this.hgap = hgap; + this.vgap = vgap; + } + + /** Lay out the container's components based on current settings. + * The free space in the container is divided evenly into the specified + * number of rows and columns in this object. + * @param parent The container to lay out + */ + public void layoutContainer (Container parent) + { + synchronized (parent.getTreeLock ()) + { + int num = parent.ncomponents; + + // There's no point, and handling this would mean adding special + // cases. + if (num == 0) + return; + + // This is more efficient than calling getComponents(). + Component[] comps = parent.component; + + int real_rows = rows; + int real_cols = cols; + if (real_rows == 0) + real_rows = (num + real_cols - 1) / real_cols; + else + real_cols = (num + real_rows - 1) / real_rows; + + // We might have less than a single row. In this case we expand + // to fill. + if (num < real_cols) + real_cols = num; + + Dimension d = parent.getSize (); + Insets ins = parent.getInsets (); + + // Compute width and height of each cell in the grid. + int tw = d.width - ins.left - ins.right; + tw = (tw - (real_cols - 1) * hgap) / real_cols; + int th = d.height - ins.top - ins.bottom; + th = (th - (real_rows - 1) * vgap) / real_rows; + + // If the cells are too small, still try to do something. + if (tw < 0) + tw = 1; + if (th < 0) + th = 1; + + int x = ins.left; + int y = ins.top; + int i = 0; + int recount = 0; + + while (i < num) + { + comps[i].setBounds (x, y, tw, th); + + ++i; + ++recount; + if (recount == real_cols) + { + recount = 0; + y += vgap + th; + x = ins.left; + } + else + x += hgap + tw; + } + } + } + + /** Get the minimum layout size of the container. + * @param cont The parent container + */ + public Dimension minimumLayoutSize (Container cont) + { + return getSize (cont, true); + } + + /** Get the preferred layout size of the container. + * @param cont The parent container + */ + public Dimension preferredLayoutSize (Container cont) + { + return getSize (cont, false); + } + + /** Remove the indicated component from this layout manager. + * This particular implementation does nothing. + * @param comp The component to remove + */ + public void removeLayoutComponent (Component comp) + { + // Nothing. + } + + /** Set the number of columns. + * @param newCols + * @exception IllegalArgumentException If the number of columns is + * negative, or if the number of columns is zero and the number + * of rows is already 0. + */ + public void setColumns (int newCols) + { + if (newCols < 0) + throw new IllegalArgumentException ("number of columns cannot be negative"); + if (newCols == 0 && rows == 0) + throw new IllegalArgumentException ("number of rows is already 0"); + this.cols = newCols; + } + + /** Set the horizontal gap + * @param hgap The horizontal gap + * @exception IllegalArgumentException If the hgap value is less than zero. + */ + public void setHgap (int hgap) + { + if (hgap < 0) + throw new IllegalArgumentException ("horizontal gap must be nonnegative"); + this.hgap = hgap; + } + + /** Set the number of rows + * @param newRows + * @exception IllegalArgumentException If the number of rows is + * negative, or if the number of rows is zero and the number + * of columns is already 0. + */ + public void setRows (int newRows) + { + if (newRows < 0) + throw new IllegalArgumentException ("number of rows cannot be negative"); + if (newRows == 0 && cols == 0) + throw new IllegalArgumentException ("number of columns is already 0"); + this.rows = newRows; + } + + /** Set the vertical gap. + * @param vgap The vertical gap + * @exception IllegalArgumentException If the vgap value is less than zero. + */ + public void setVgap (int vgap) + { + if (vgap < 0) + throw new IllegalArgumentException ("vertical gap must be nonnegative"); + this.vgap = vgap; + } + + /** Return String description of this object. */ + public String toString () + { + return ("[" + getClass ().getName () + + ",hgap=" + hgap + ",vgap=" + vgap + + ",rows=" + rows + ",cols=" + cols + + "]"); + } + + // This method is used to compute the various sizes. + private Dimension getSize (Container parent, boolean is_min) + { + synchronized (parent.getTreeLock ()) + { + int w = 0, h = 0, num = parent.ncomponents; + // This is more efficient than calling getComponents(). + Component[] comps = parent.component; + + for (int i = 0; i < num; ++i) + { + Dimension d; + + if (is_min) + d = comps[i].getMinimumSize (); + else + d = comps[i].getPreferredSize (); + + w = Math.max (d.width, w); + h = Math.max (d.height, h); + } + + int real_rows = rows; + int real_cols = cols; + if (real_rows == 0) + real_rows = (num + real_cols - 1) / real_cols; + else + real_cols = (num + real_rows - 1) / real_rows; + + Insets ins = parent.getInsets (); + // We subtract out an extra gap here because the gaps are only + // between cells. + w = ins.left + ins.right + real_cols * (w + hgap) - hgap; + h = ins.top + ins.bottom + real_rows * (h + vgap) - vgap; + return new Dimension (w, h); + } + } + + /** + * @serial The number of columns in the grid. + */ + private int cols; + + /** + * @serial The number of rows in the grid. + */ + private int rows; + + /** + * @serial The horizontal gap between columns + */ + private int hgap; + + /** + * @serial The vertical gap between rows + */ + private int vgap; +} diff --git a/libjava/classpath/java/awt/HeadlessException.java b/libjava/classpath/java/awt/HeadlessException.java new file mode 100644 index 0000000..b180b1d --- /dev/null +++ b/libjava/classpath/java/awt/HeadlessException.java @@ -0,0 +1,72 @@ +/* HeadlessException.java -- operation not possible in headless environment + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This exception is thrown when code dependent on a keyboard, mouse, or + * display is executed in a headless environment. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.4 + * @status updated to 1.4 + */ +public class HeadlessException extends UnsupportedOperationException +{ + /** + * Compatible with JDK 1.4+. + */ + private static final long serialVersionUID = 167183644944358563L; + + /** + * Create a new instance with no detailed error message. + */ + public HeadlessException() + { + } + + /** + * Create a new instance with the specified detailed error message. + * + * @param message the detailed error message + */ + public HeadlessException(String message) + { + super(message); + } +} // class HeadlessException diff --git a/libjava/classpath/java/awt/IllegalComponentStateException.java b/libjava/classpath/java/awt/IllegalComponentStateException.java new file mode 100644 index 0000000..4a47f1d --- /dev/null +++ b/libjava/classpath/java/awt/IllegalComponentStateException.java @@ -0,0 +1,71 @@ +/* IllegalComponentStateException.java -- bad component state + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This exception is thrown when the requested operation failed because + * a component was not in the proper state. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @status updated to 1.4 + */ +public class IllegalComponentStateException extends IllegalStateException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -1889339587208144238L; + + /** + * Create a new instance with no detailed error message. + */ + public IllegalComponentStateException() + { + } + + /** + * Create a new instance with the specified detailed error message. + * + * @param message the detailed error message + */ + public IllegalComponentStateException(String message) + { + super(message); + } +} // class IllegalComponentStateException diff --git a/libjava/classpath/java/awt/Image.java b/libjava/classpath/java/awt/Image.java new file mode 100644 index 0000000..b657ad0 --- /dev/null +++ b/libjava/classpath/java/awt/Image.java @@ -0,0 +1,203 @@ +/* Image.java -- superclass for images + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.image.FilteredImageSource; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.awt.image.ReplicateScaleFilter; + +/** + * This is the abstract superclass of all image objects in Java. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @since 1.0 + * @status updated to 1.4 + */ +public abstract class Image +{ + /** + * This variable is returned whenever a property that is not defined + * is requested. + */ + // For debug purposes, this might as well be a unique string. + public static final Object UndefinedProperty + = new String("undefined property"); + + /** + * Constant indicating that the default scaling algorithm should be used. + * + * @since 1.1 + */ + public static final int SCALE_DEFAULT = 1; + + /** + * Constant indicating that a fast scaling algorithm should be used. + * + * @since 1.1 + */ + public static final int SCALE_FAST = 2; + + /** + * Constant indicating that a smooth scaling algorithm should be used. + * + * @since 1.1 + */ + public static final int SCALE_SMOOTH = 4; + + /** + * Constant indicating that the <code>ReplicateScaleFilter</code> class + * algorithm should be used for scaling. + * + * @see ReplicateScaleFilter + * @since 1.1 + */ + public static final int SCALE_REPLICATE = 8; + + /** + * Constant indicating that the area averaging scaling algorithm should be + * used. + * + * @see java.awt.image.AreaAveragingScaleFilter + * @since 1.1 + */ + public static final int SCALE_AREA_AVERAGING = 16; + + /** + * A default constructor for subclasses. + */ + public Image() + { + } + + /** + * Returns the width of the image, or -1 if it is unknown. If the + * image width is unknown, the observer object will be notified when + * the value is known. + * + * @param observer the image observer for this object + * @return the width in pixels + * @see #getHeight(ImageObserver) + */ + public abstract int getWidth(ImageObserver observer); + + /** + * Returns the height of the image, or -1 if it is unknown. If the + * image height is unknown, the observer object will be notified when + * the value is known. + * + * @param observer the image observer for this object + * @return the height in pixels + * @see #getWidth(ImageObserver) + */ + public abstract int getHeight(ImageObserver observer); + + /** + * Returns the image producer object for this object. The producer is the + * object which generates pixels for this image. + * + * @return the image producer for this object + */ + public abstract ImageProducer getSource(); + + /** + * Returns a graphics context object for drawing an off-screen object. + * This method is only valid for off-screen objects. + * + * @return a graphics context object for an off-screen object + * @see Graphics#getcreateImage(int, int) + */ + public abstract Graphics getGraphics(); + + /** + * This method requests a named property for an object. The value of the + * property is returned. The value <code>UndefinedProperty</code> is + * returned if there is no property with the specified name. The value + * <code>null</code> is returned if the properties for the object are + * not yet known. In this case, the specified image observer is notified + * when the properties are known. + * + * @param name the requested property name + * @param observer the image observer for this object + * @return the named property, if available + * @see #UndefinedProperty + */ + public abstract Object getProperty(String name, ImageObserver observer); + + /** + * Scales the image to the requested dimension. A new Image with asynchronous + * loading will be produced according to the hints of the algorithm + * requested. If either the width or height is non-positive, it is adjusted + * to preserve the original aspect ratio. + * + * @param width the width of the scaled image + * @param height the height of the scaled image + * @param flags a value indicating the algorithm to use + * @return the scaled <code>Image</code> object + * @see #SCALE_DEFAULT + * @see #SCALE_FAST + * @see #SCALE_SMOOTH + * @see #SCALE_REPLICATE + * @see #SCALE_AREA_AVERAGING + * @since 1.1 + */ + public Image getScaledInstance(int width, int height, int flags) + { + switch (flags) + { + case SCALE_DEFAULT: + case SCALE_FAST: + case SCALE_REPLICATE: + ImageProducer producer = + new FilteredImageSource(this.getSource(), + new ReplicateScaleFilter(width, height)); + return Toolkit.getDefaultToolkit().createImage(producer); + case SCALE_SMOOTH: + case SCALE_AREA_AVERAGING: + default: + throw new Error("not implemented"); + } + } + + /** + * Flushes (that is, destroys) any resources used for this image. This + * includes the actual image data. + */ + public abstract void flush(); +} // class Image diff --git a/libjava/classpath/java/awt/ImageCapabilities.java b/libjava/classpath/java/awt/ImageCapabilities.java new file mode 100644 index 0000000..2fe71d1 --- /dev/null +++ b/libjava/classpath/java/awt/ImageCapabilities.java @@ -0,0 +1,107 @@ +/* ImageCapabilities.java -- the capabilities of an image buffer + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This class represents the capabilities of an image buffer. An + * image buffer may be backed by accelerated graphics resources. + * Those resources may or may not be volatile. This class is used to + * describe these image buffer characteristics. + */ +public class ImageCapabilities implements Cloneable +{ + /** + * Whether or not this the image buffer uses accelerated graphics + * resources. + */ + private final boolean accelerated; + + /** + * Create a new image capability descriptor. + * + * @param accelerated true if the image buffer uses accelerated + * graphics resources + */ + public ImageCapabilities(boolean accelerated) + { + this.accelerated = accelerated; + } + + /** + * Returns whether or not the image buffer uses accelerated graphics + * resources. + * + * @return true if the image buffer uses accelerated graphics + * resources; false otherwise + */ + public boolean isAccelerated() + { + return accelerated; + } + + /** + * Returns whether or not the image buffer's resources are volatile, + * meaning that they can be reclaimed by the graphics system at any + * time. + * + * @return true if the image buffer's resources are volatile; false + * otherwise + */ + public boolean isTrueVolatile() + { + return true; + } + + /** + * Clone this image capability descriptor. + * + * @return a clone of this image capability descriptor + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); + } + } +} diff --git a/libjava/classpath/java/awt/Insets.java b/libjava/classpath/java/awt/Insets.java new file mode 100644 index 0000000..7238a34 --- /dev/null +++ b/libjava/classpath/java/awt/Insets.java @@ -0,0 +1,158 @@ +/* Insets.java -- information about a container border + Copyright (C) 1999, 2000, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.io.Serializable; + +/** + * This class represents the "margin" or space around a container. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @status + */ +public class Insets implements Cloneable, Serializable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -2272572637695466749L; + + /** + * The gap from the top. + * + * @serial the top inset + */ + public int top; + + /** + * The gap from the left. + * + * @serial the left inset + */ + public int left; + + /** + * The gap from the bottom. + * + * @serial the bottom inset + */ + public int bottom; + + /** + * The gap from the right. + * + * @serial the right inset + */ + public int right; + + /** + * Initializes a new instance of <code>Inset</code> with the specified + * inset values. + * + * @param top the top inset + * @param left the left inset + * @param bottom the bottom inset + * @param right the right inset + */ + public Insets(int top, int left, int bottom, int right) + { + this.top = top; + this.left = left; + this.bottom = bottom; + this.right = right; + } + + /** + * Tests whether this object is equal to the specified object. The other + * object must be an instance of Insets with identical field values. + * + * @param obj the object to test against + * @return true if the specified object is equal to this one + */ + public boolean equals(Object obj) + { + if (! (obj instanceof Insets)) + return false; + Insets i = (Insets) obj; + return top == i.top && bottom == i.bottom + && left == i.left && right == i.right; + } + + /** + * Returns a hashcode for this instance. The formula is unspecified, but + * appears to be <code>XXX what is it? </code>. + * + * @return the hashcode + */ + public int hashCode() + { + // This can't be right... + return top + bottom + left + right; + } + + /** + * Returns a string representation of this object, which will be non-null. + * The format is unspecified, but appears to be <code>XXX what is it?</code>. + * + * @return a string representation of this object + */ + public String toString() + { + return getClass().getName() + "(top=" + top + ",bottom=" + bottom + + ",left=" + left + ",right=" + right + ')'; + } + + /** + * Returns a copy of this object. + * + * @return a copy of this object + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // Impossible + } + } +} // class Insets diff --git a/libjava/classpath/java/awt/ItemSelectable.java b/libjava/classpath/java/awt/ItemSelectable.java new file mode 100644 index 0000000..f155f72 --- /dev/null +++ b/libjava/classpath/java/awt/ItemSelectable.java @@ -0,0 +1,75 @@ +/* ItemSelectable.java -- items that can be selected + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ItemListener; + +/** + * This interface is for objects that can have one or more items selected. + * For example, radio buttons. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @since 1.0 + * @status updated to 1.4 + */ +public interface ItemSelectable +{ + /** + * Returns the list of objects that are selected in this component. + * + * @return the list of selected objects, or null + */ + Object[] getSelectedObjects(); + + /** + * Adds an item listener to this object. It will receive selection events + * for this object by the user (but not programatically). If listener is + * null, it is ignored. + * + * @param listener the item listener to add + */ + void addItemListener(ItemListener listener); + + /** + * Removes an item listener from this object. + * + * @param listener the item listener to remove + */ + void removeItemListener(ItemListener listener); +} // interface ItemSelectable diff --git a/libjava/classpath/java/awt/JobAttributes.java b/libjava/classpath/java/awt/JobAttributes.java new file mode 100644 index 0000000..2acb3a0 --- /dev/null +++ b/libjava/classpath/java/awt/JobAttributes.java @@ -0,0 +1,500 @@ +/* JobAttributes.java -- + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * Needs documentation... + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + * @status updated to 1.4, lacks documentation + */ +public final class JobAttributes implements Cloneable +{ + public static final class DefaultSelectionType extends AttributeValue + { + private static final String[] NAMES = { "all", "range", "selection" }; + public static final DefaultSelectionType ALL + = new DefaultSelectionType(0); + public static final DefaultSelectionType RANGE + = new DefaultSelectionType(1); + public static final DefaultSelectionType SELECTION + = new DefaultSelectionType(2); + private DefaultSelectionType(int value) + { + super(value, NAMES); + } + } // class DefaultSelectionType + + public static final class DestinationType extends AttributeValue + { + private static final String[] NAMES = { "file", "printer" }; + public static final DestinationType FILE = new DestinationType(0); + public static final DestinationType PRINTER = new DestinationType(1); + private DestinationType(int value) + { + super(value, NAMES); + } + } // class DestinationType + + public static final class DialogType extends AttributeValue + { + private static final String[] NAMES = { "common", "native", "none" }; + public static final DialogType COMMON = new DialogType(0); + public static final DialogType NATIVE = new DialogType(1); + public static final DialogType NONE = new DialogType(2); + private DialogType(int value) + { + super(value, NAMES); + } + } // class DialogType + + public static final class MultipleDocumentHandlingType + extends AttributeValue + { + private static final String[] NAMES = { + "separate-documents-collated-copies", + "separate-documents-uncollated-copies" + }; + public static final MultipleDocumentHandlingType + SEPARATE_DOCUMENTS_COLLATED_COPIES + = new MultipleDocumentHandlingType(0); + public static final MultipleDocumentHandlingType + SEPARATE_DOCUMENTS_UNCOLLATED_COPIES + = new MultipleDocumentHandlingType(1); + private MultipleDocumentHandlingType(int value) + { + super(value, NAMES); + } + } // class MultipleDocumentHandlingType + + public static final class SidesType extends AttributeValue + { + private static final String[] NAMES + = { "one-sided", "two-sided-long-edge", "two-sided-short-edge" }; + public static final SidesType ONE_SIDED = new SidesType(0); + public static final SidesType TWO_SIDED_LONG_EDGE = new SidesType(1); + public static final SidesType TWO_SIDED_SHORT_EDGE = new SidesType(2); + private SidesType(int value) + { + super(value, NAMES); + } + } // class SidesType + + private int copies; + private DefaultSelectionType selection; + private DestinationType destination; + private DialogType dialog; + private String filename; + private int maxPage; + private int minPage; + private MultipleDocumentHandlingType multiple; + private int[][] pageRanges; // null for default value + private int fromPage; // 0 for default value + private int toPage; // 0 for default value + private String printer; + private SidesType sides; + + public JobAttributes() + { + copies = 1; + selection = DefaultSelectionType.ALL; + destination = DestinationType.PRINTER; + dialog = DialogType.NATIVE; + maxPage = Integer.MAX_VALUE; + minPage = 1; + multiple + = MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_UNCOLLATED_COPIES; + sides = SidesType.ONE_SIDED; + } + + public JobAttributes(JobAttributes attr) + { + set(attr); + } + + public JobAttributes(int copies, DefaultSelectionType selection, + DestinationType destination, DialogType dialog, + String filename, int max, int min, + MultipleDocumentHandlingType multiple, + int[][] pageRanges, String printer, SidesType sides) + { + if (copies <= 0 || selection == null || destination == null + || dialog == null || max < min || min <= 0 || multiple == null + || sides == null) + throw new IllegalArgumentException(); + this.copies = copies; + this.selection = selection; + this.destination = destination; + this.dialog = dialog; + this.filename = filename; + maxPage = max; + minPage = min; + this.multiple = multiple; + setPageRanges(pageRanges); + this.printer = printer; + this.sides = sides; + } + + public Object clone() + { + return new JobAttributes(this); + } + + public void set(JobAttributes attr) + { + copies = attr.copies; + selection = attr.selection; + destination = attr.destination; + dialog = attr.dialog; + filename = attr.filename; + maxPage = attr.maxPage; + minPage = attr.minPage; + multiple = attr.multiple; + pageRanges = (int[][]) attr.pageRanges.clone(); + printer = attr.printer; + sides = attr.sides; + fromPage = attr.fromPage; + toPage = attr.toPage; + } + + public int getCopies() + { + return copies; + } + + public void setCopies(int copies) + { + if (copies <= 0) + throw new IllegalArgumentException(); + this.copies = copies; + } + + public void setCopiesToDefault() + { + copies = 1; + } + + public DefaultSelectionType getDefaultSelection() + { + return selection; + } + + public void setDefaultSelection(DefaultSelectionType selection) + { + if (selection == null) + throw new IllegalArgumentException(); + this.selection = selection; + } + + public DestinationType getDestination() + { + return destination; + } + + public void setDestination(DestinationType destination) + { + if (destination == null) + throw new IllegalArgumentException(); + this.destination = destination; + } + + public DialogType getDialog() + { + return dialog; + } + + public void setDialog(DialogType dialog) + { + if (dialog == null) + throw new IllegalArgumentException(); + this.dialog = dialog; + } + + public String getFileName() + { + return filename; + } + + public void setFileName(String filename) + { + this.filename = filename; + } + + public int getFromPage() + { + return fromPage != 0 ? fromPage + : pageRanges != null ? pageRanges[0][0] + : toPage != 0 ? toPage : minPage; + } + + public void setFromPage(int fromPage) + { + if (fromPage < minPage || (fromPage > toPage && toPage != 0) + || fromPage > maxPage) + throw new IllegalArgumentException(); + if (pageRanges == null) + this.fromPage = fromPage; + } + + public int getMaxPage() + { + return maxPage; + } + + public void setMaxPage(int maxPage) + { + if (maxPage < minPage) + throw new IllegalArgumentException(); + this.maxPage = maxPage; + if (maxPage < fromPage) + fromPage = maxPage; + if (maxPage < toPage) + toPage = maxPage; + if (pageRanges != null) + { + int i = pageRanges.length - 1; + while (i >= 0 && maxPage < pageRanges[i][1]) + i--; + if (maxPage >= pageRanges[++i][0]) + pageRanges[i++][1] = maxPage; + if (i == 0) + pageRanges = null; + else if (i < pageRanges.length) + { + int[][] tmp = new int[i][]; + System.arraycopy(pageRanges, 0, tmp, 0, i); + pageRanges = tmp; + } + } + } + + public int getMinPage() + { + return minPage; + } + + public void setMinPage(int minPage) + { + if (minPage <= 0 || minPage > maxPage) + throw new IllegalArgumentException(); + this.minPage = minPage; + if (minPage > toPage) + toPage = minPage; + if (minPage > fromPage) + fromPage = minPage; + if (pageRanges != null) + { + int size = pageRanges.length; + int i = 0; + while (i < size && minPage > pageRanges[i][0]) + i++; + if (minPage <= pageRanges[i - 1][1]) + pageRanges[--i][0] = minPage; + if (i == size) + pageRanges = null; + else if (i > 0) + { + int[][] tmp = new int[size - i][]; + System.arraycopy(pageRanges, i, tmp, 0, size - i); + pageRanges = tmp; + } + } + } + + public MultipleDocumentHandlingType getMultipleDocumentHandling() + { + return multiple; + } + + public void setMultipleDocumentHandling + (MultipleDocumentHandlingType multiple) + { + if (multiple == null) + throw new IllegalArgumentException(); + this.multiple = multiple; + } + + public void setMultipleDocumentHandlingToDefault() + { + multiple + = MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_UNCOLLATED_COPIES; + } + + public int[][] getPageRanges() + { + if (pageRanges == null) + return new int[][] { { getFromPage(), getToPage() } }; + // Perform a deep clone, so user code cannot affect original arrays. + int i = pageRanges.length; + int[][] result = new int[i][]; + while (--i >= 0) + result[i] = (int[]) pageRanges[i].clone(); + return result; + } + + public void setPageRanges(int[][] pageRanges) + { + int size = pageRanges == null ? 0 : pageRanges.length; + if (size == 0) + throw new IllegalArgumentException(); + while (--size >= 0) + { + int[] range = pageRanges[size]; + if (range == null || range.length != 2 + || range[0] < minPage || range[1] < range[0] || range[1] > maxPage + || (size != 0 && range[0] <= pageRanges[size - 1][1])) + throw new IllegalArgumentException(); + } + size = pageRanges.length; + if (fromPage > 0 && pageRanges[0][0] > fromPage) + fromPage = pageRanges[0][0]; + if (toPage > 0 && pageRanges[size - 1][1] < toPage) + toPage = pageRanges[size - 1][1]; + this.pageRanges = new int[size][]; + while (--size >= 0) + this.pageRanges[size] = (int[]) pageRanges[size].clone(); + } + + public String getPrinter() + { + return printer; + } + + public void setPrinter(String printer) + { + this.printer = printer; + } + + public SidesType getSides() + { + return sides; + } + + public void setSides(SidesType sides) + { + if (sides == null) + throw new IllegalArgumentException(); + this.sides = sides; + } + + public void setSidesToDefault() + { + sides = SidesType.ONE_SIDED; + } + + public int getToPage() + { + return toPage != 0 ? toPage + : pageRanges != null ? pageRanges[pageRanges.length - 1][1] + : fromPage != 0 ? fromPage : maxPage; + } + + public void setToPage(int toPage) + { + if (toPage < minPage || (fromPage > toPage && fromPage != 0) + || toPage > maxPage) + throw new IllegalArgumentException(); + if (pageRanges == null) + this.toPage = toPage; + } + + public boolean equals(Object o) + { + if (this == o) + return true; + if (! (o instanceof JobAttributes)) + return false; + JobAttributes ja = (JobAttributes) o; + if (copies != ja.copies || selection != ja.selection + || destination != ja.destination || dialog != ja.dialog + || ! filename.equals(ja.filename) || maxPage != ja.maxPage + || minPage != ja.minPage || multiple != ja.multiple + || fromPage != ja.fromPage || toPage != ja.toPage + || ! printer.equals(ja.printer) || sides != ja.sides + || (pageRanges == null) != (ja.pageRanges == null)) + return false; + if (pageRanges != ja.pageRanges) + for (int i = pageRanges.length; --i >= 0; ) + if (pageRanges[i][0] != ja.pageRanges[i][0] + || pageRanges[i][1] != ja.pageRanges[i][1]) + return false; + return true; + } + + public int hashCode() + { + int hash = (selection.value << 6) ^ (destination.value << 5) + ^ (dialog.value << 3) ^ (multiple.value << 2) ^ sides.value + ^ (filename == null ? 0 : filename.hashCode()) + ^ (printer == null ? 0 : printer.hashCode()); + // The effect of the above fields on the hashcode match the JDK. However, + // I am unable to reverse engineer the effect of the fields listed below, + // so I am using my own implementation. Note that this still satisfies + // the general contract of hashcode, it just doesn't match the JDK. + hash ^= (copies << 27) ^ (maxPage << 22) ^ (minPage << 17); + if (pageRanges == null) + hash ^= (getFromPage() << 13) ^ (getToPage() << 8); + else + for (int i = pageRanges.length; --i >= 0; ) + hash ^= (pageRanges[i][0] << 13) ^ (pageRanges[i][1] << 8); + return hash; + } + + public String toString() + { + StringBuffer s = new StringBuffer("copies=").append(copies) + .append(",defaultSelection=").append(selection).append(",destination=") + .append(destination).append(",dialog=").append(dialog) + .append(",fileName=").append(filename).append(",fromPage=") + .append(getFromPage()).append(",maxPage=").append(maxPage) + .append(",minPage=").append(minPage) + .append(",multiple-document-handling=").append(multiple) + .append(",page-ranges=["); + if (pageRanges == null) + s.append(minPage).append(':').append(minPage).append(']'); + else + for (int i = 0; i < pageRanges.length; i++) + s.append(pageRanges[i][0]).append(':').append(pageRanges[i][1]) + .append(','); + s.setLength(s.length() - 1); + return s.append("],printer=").append(printer).append(",sides=") + .append(sides).append(",toPage=").append(getToPage()).toString(); + } +} // class JobAttributes diff --git a/libjava/classpath/java/awt/KeyEventDispatcher.java b/libjava/classpath/java/awt/KeyEventDispatcher.java new file mode 100644 index 0000000..3099727 --- /dev/null +++ b/libjava/classpath/java/awt/KeyEventDispatcher.java @@ -0,0 +1,82 @@ +/* KeyEventDispatcher.java -- dispatches key events + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.KeyEvent; + +/** + * An instance of this interface coordinates with a KeyboardFocusManager to + * target and dispatch all key events. This allows retargeting, consuming, + * changing, or otherwise manipulating the key event before sending it on to + * a target. + * + * <p>By default, the KeyboardFocusManager is the sink for all key events not + * dispatched by other dispatchers. Therefore, it is unnecessary for the user + * to register the focus manager as a dispatcher. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see KeyboardFocusManager#addKeyEventDispatcher(KeyEventDispatcher) + * @see KeyboardFocusManager#removeKeyEventDispatcher(KeyEventDispatcher) + * @since 1.4 + * @status updated to 1.4 + */ +public interface KeyEventDispatcher +{ + /** + * Called by the KeyboardFocusManager to request that a key event be + * dispatched. The dispatcher is free to retarget the event, consume it, + * dispatch it, or make other changes. This is usually done to allow + * delivery of key events to objects other than the window in focus, such + * as for navigating non-focusable components. If this dispatcher chooses + * to dispatch the event itself, it should call <code>redispatchEvent</code> + * to avoid infinite recursion. + * + * <p>If the return value is false, the KeyEvent is passed to the next + * dispatcher in the chain, ending with the KeyboardFocusManager. If the + * return value is true, the event has been consumed (although it might + * have been ignored), and no further action will be taken on the event. Be + * sure to check whether the event was consumed before dispatching it + * further. + * + * @param e the key event + * @return true if the event has been consumed + * @see KeyboardFocusManager#redispatchEvent(Component, AWTEvent) + */ + boolean dispatchKeyEvent(KeyEvent e); +} // interface KeyEventDispatcher diff --git a/libjava/classpath/java/awt/KeyEventPostProcessor.java b/libjava/classpath/java/awt/KeyEventPostProcessor.java new file mode 100644 index 0000000..0b39dc2 --- /dev/null +++ b/libjava/classpath/java/awt/KeyEventPostProcessor.java @@ -0,0 +1,81 @@ +/* KeyEventPostProcessor.java -- performs actions after a key event dispatch + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.KeyEvent; + +/** + * An instance of this interface coordinates with a KeyboardFocusManager to + * target and dispatch all key events that are otherwise unconsumed. This + * allows events which take place when nothing has focus to still operate, + * such as menu keyboard shortcuts. + * + * <p>By default, the KeyboardFocusManager is the sink for all key events not + * post-processed elsewhere. Therefore, it is unnecessary for the user + * to register the focus manager as a dispatcher. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see KeyboardFocusManager#addKeyEventPostProcessor(KeyEventPostProcessor) + * @see KeyboardFocusManager#removeKeyEventPostProcessor(KeyEventPostProcessor) + * @since 1.4 + * @status updated to 1.4 + */ +public interface KeyEventPostProcessor +{ + /** + * Called by the KeyboardFocusManager to request that a key event be + * post-processed. Typically, the event has already been dispatched and + * handled, unless no object has focus. Thus, this allows global event + * handling for things like menu shortcuts. If this post-processor chooses + * to dispatch the event, it should call <code>redispatchEvent</code> + * to avoid infinite recursion. + * + * <p>If the return value is false, the KeyEvent is passed to the next + * dispatcher in the chain, ending with the KeyboardFocusManager. If the + * return value is true, the event has been consumed (although it might + * have been ignored), and no further action will be taken on the event. Be + * sure to check whether the event was consumed before dispatching it + * further. + * + * @param e the key event + * @return true if the event has been consumed + * @see KeyboardFocusManager#redispatchEvent(Component, AWTEvent) + */ + boolean postProcessKeyEvent(KeyEvent e); +} // interface KeyEventPostProcessor diff --git a/libjava/classpath/java/awt/KeyboardFocusManager.java b/libjava/classpath/java/awt/KeyboardFocusManager.java new file mode 100644 index 0000000..f646184 --- /dev/null +++ b/libjava/classpath/java/awt/KeyboardFocusManager.java @@ -0,0 +1,1478 @@ +/* KeyboardFocusManager.java -- manage component focusing via the keyboard + Copyright (C) 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.applet.Applet; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.beans.PropertyVetoException; +import java.beans.VetoableChangeListener; +import java.beans.VetoableChangeSupport; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * The <code>KeyboardFocusManager</code> handles the focusing of + * windows for receiving keyboard events. The manager handles + * the dispatch of all <code>FocusEvent</code>s and + * <code>KeyEvent</code>s, along with <code>WindowEvent</code>s + * relating to the focused window. Users can use the manager + * to ascertain the current focus owner and fire events. + * <br /> + * <br /> + * The focus owner is the <code>Component</code> that receives + * key events. The focus owner is either the currently focused + * window or a component within this window. + * <br /> + * <br /> + * The underlying native windowing system may denote the active + * window or its children with special decorations (e.g. a highlighted + * title bar). The active window is always either a <code>Frame</code> + * or <code>Dialog</code>, and is either the currently focused + * window or its owner. + * <br /> + * <br /> + * Applets may be partitioned into different applet contexts, according + * to their code base. In this case, each context has its own + * <code>KeyboardFocusManager</code>, as opposed to the global + * manager maintained by applets which share the same context. + * Each context is insulated from the others, and they don't interact. + * The resulting behaviour, as with context division, depends on the browser + * supporting the applets. Regardless, there can only ever be + * one focused window, one active window and one focus owner + * per <code>ClassLoader</code>. + * <br /> + * <br /> + * To support this separation of focus managers, the manager instances + * and the internal state information is grouped by the + * <code>ThreadGroup</code> to which it pertains. With respect to + * applets, each code base has its own <code>ThreadGroup</code>, so the + * isolation of each context is enforced within the manager. + * <br /> + * <br /> + * By default, the manager defines TAB and Ctrl+TAB as the + * forward focus traversal keys and Shift+TAB and Ctrl+Shift+TAB + * as the backward focus traversal keys. No up or down cycle + * traversal keys are defined by default. Traversal takes effect + * on the firing of a relevant <code>KEY_PRESSED</code> event. + * However, all other key events related to the use of the + * defined focus traversal key sequence are consumed and not + * dispatched. + * <br /> + * <br /> + * These default traversal keys come into effect on all windows + * for which no alternative set of keys is defined. This also + * applies recursively to any child components of such a window, + * which define no traversal keys of their own. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @author Thomas Fitzsimmons (fitzsim@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.4 + */ +public abstract class KeyboardFocusManager + implements KeyEventDispatcher, KeyEventPostProcessor +{ + /** Identifies {@link AWTKeyStroke}s that move the focus forward in + the focus cycle. */ + public static final int FORWARD_TRAVERSAL_KEYS = 0; + + /** Identifies {@link AWTKeyStroke}s that move the focus backward in + the focus cycle. */ + public static final int BACKWARD_TRAVERSAL_KEYS = 1; + + /** Identifies {@link AWTKeyStroke}s that move the focus up to the + parent focus cycle root. */ + public static final int UP_CYCLE_TRAVERSAL_KEYS = 2; + + /** Identifies {@link AWTKeyStroke}s that move the focus down to the + child focus cycle root. */ + public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3; + + /** The set of {@link AWTKeyStroke}s that cause focus to be moved to + the next focusable Component in the focus cycle. */ + private static final Set DEFAULT_FORWARD_KEYS; + + /** The set of {@link AWTKeyStroke}s that cause focus to be moved to + the previous focusable Component in the focus cycle. */ + private static final Set DEFAULT_BACKWARD_KEYS; + + /** Populate the DEFAULT_FORWARD_KEYS and DEFAULT_BACKWARD_KEYS + {@link java.util.Set}s. */ + static + { + Set s = new HashSet(); + s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0)); + s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, + KeyEvent.CTRL_DOWN_MASK)); + DEFAULT_FORWARD_KEYS = Collections.unmodifiableSet(s); + s = new HashSet(); + s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, + KeyEvent.SHIFT_DOWN_MASK)); + s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, + KeyEvent.SHIFT_DOWN_MASK + | KeyEvent.CTRL_DOWN_MASK)); + DEFAULT_BACKWARD_KEYS = Collections.unmodifiableSet(s); + } + + /** The global object {@link java.util.Map}s. */ + + /** For security reasons, {@link java.applet.Applet}s in different + codebases must be insulated from one another. Since {@link + KeyboardFocusManager}s have the ability to return {@link + Component}s from a given {@link java.applet.Applet}, each + codebase must have an independent {@link KeyboardFocusManager}. + Since each codebase has its own {@link ThreadGroup} in which its + {@link Applet}s run, it makes sense to partition {@link + KeyboardFocusManager}s according to {@link + java.lang.ThreadGroup}. Thus, currentKeyboardFocusManagers is a + {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}. */ + private static Map currentKeyboardFocusManagers = new HashMap (); + + /** {@link java.applet.Applet}s in one codebase must not be allowed + to access {@link Component}s in {@link java.applet.Applet}s in + other codebases. To enforce this restriction, we key the + following {@link java.util.Map}s on {@link java.lang.ThreadGroup}s (which + are per-codebase). For example, if {@link + java.lang.ThreadGroup} A calls {@link #setGlobalFocusOwner}, + passing {@link Component} C, currentFocusOwners[A] is assigned + C, and all other currentFocusOwners values are nullified. Then + if {@link java.lang.ThreadGroup} A subsequently calls {@link + #getGlobalFocusOwner}, it will return currentFocusOwners[A], + that is, {@link Component} C. If another {@link + java.lang.ThreadGroup} K calls {@link #getGlobalFocusOwner}, it + will return currentFocusOwners[K], that is, null. + + Since this is a static field, we ensure that there is only one + focused {@link Component} per class loader. */ + private static Map currentFocusOwners = new HashMap (); + + /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s + that stores the {@link Component} that owns the permanent + keyboard focus. @see currentFocusOwners */ + private static Map currentPermanentFocusOwners = new HashMap (); + + /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s + that stores the focused {@link Window}. @see + currentFocusOwners */ + private static Map currentFocusedWindows = new HashMap (); + + /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s + that stores the active {@link Window}. @see + currentFocusOwners */ + private static Map currentActiveWindows = new HashMap (); + + /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s + that stores the focus cycle root {@link Container}. @see + currentFocusOwners */ + private static Map currentFocusCycleRoots = new HashMap (); + + /** The default {@link FocusTraveralPolicy} that focus-managing + {@link Container}s will use to define their initial focus + traversal policy. */ + private FocusTraversalPolicy defaultPolicy; + + /** An array that stores the {@link #FORWARD_TRAVERSAL_KEYS}, {@link + #BACKWARD_TRAVERSAL_KEYS}, {@link #UP_CYCLE_TRAVERSAL_KEYS} and + {@link #DOWN_CYCLE_TRAVERSAL_KEYS} {@link AWTKeyStroke}s {@link + java.util.Set}s. */ + private Set[] defaultFocusKeys = new Set[] + { + DEFAULT_FORWARD_KEYS, DEFAULT_BACKWARD_KEYS, + Collections.EMPTY_SET, Collections.EMPTY_SET + }; + + /** + * A utility class to support the handling of events relating to property changes. + */ + private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport (this); + + /** + * A utility class to support the handling of events relating to vetoable changes. + */ + private final VetoableChangeSupport vetoableChangeSupport = new VetoableChangeSupport (this); + + /** A list of {@link KeyEventDispatcher}s that process {@link + KeyEvent}s before they are processed the default keyboard focus + manager. */ + private final ArrayList keyEventDispatchers = new ArrayList(); + + /** A list of {@link KeyEventPostProcessor}s that process unconsumed + {@link KeyEvent}s. */ + private final ArrayList keyEventPostProcessors = new ArrayList(); + + /** + * Construct a KeyboardFocusManager. + */ + public KeyboardFocusManager () + { + } + + /** + * Retrieve the keyboard focus manager associated with the {@link + * java.lang.ThreadGroup} to which the calling thread belongs. + * + * @return the keyboard focus manager associated with the current + * thread group + */ + public static KeyboardFocusManager getCurrentKeyboardFocusManager () + { + ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup (); + + if (currentKeyboardFocusManagers.get (currentGroup) == null) + setCurrentKeyboardFocusManager (null); + + return (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup); + } + + /** + * Set the keyboard focus manager associated with the {@link + * java.lang.ThreadGroup} to which the calling thread belongs. + * + * @param m the keyboard focus manager for the current thread group + */ + public static void setCurrentKeyboardFocusManager (KeyboardFocusManager m) + { + SecurityManager sm = System.getSecurityManager (); + if (sm != null) + sm.checkPermission (new AWTPermission ("replaceKeyboardFocusManager")); + + ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup (); + KeyboardFocusManager manager; + + if (m == null) + manager = createFocusManager(); + else + manager = m; + + currentKeyboardFocusManagers.put (currentGroup, manager); + } + + /** + * Creates a KeyboardFocusManager. The exact class is determined by the + * system property 'gnu.java.awt.FocusManager'. If this is not set, + * we default to DefaultKeyboardFocusManager. + */ + private static KeyboardFocusManager createFocusManager() + { + String fmClassName = System.getProperty("gnu.java.awt.FocusManager", + "java.awt.DefaultKeyboardFocusManager"); + try + { + Class fmClass = Class.forName(fmClassName); + KeyboardFocusManager fm = (KeyboardFocusManager) fmClass.newInstance(); + return fm; + } + catch (ClassNotFoundException ex) + { + System.err.println("The class " + fmClassName + " cannot be found."); + System.err.println("Check the setting of the system property"); + System.err.println("gnu.java.awt.FocusManager"); + return null; + } + catch (InstantiationException ex) + { + System.err.println("The class " + fmClassName + " cannot be"); + System.err.println("instantiated."); + System.err.println("Check the setting of the system property"); + System.err.println("gnu.java.awt.FocusManager"); + return null; + } + catch (IllegalAccessException ex) + { + System.err.println("The class " + fmClassName + " cannot be"); + System.err.println("accessed."); + System.err.println("Check the setting of the system property"); + System.err.println("gnu.java.awt.FocusManager"); + return null; + } + } + + /** + * Retrieve the {@link Component} that has the keyboard focus, or + * null if the focus owner was not set by a thread in the current + * {@link java.lang.ThreadGroup}. + * + * @return the keyboard focus owner or null + */ + public Component getFocusOwner () + { + Component owner = (Component) getObject (currentFocusOwners); + if (owner == null) + owner = (Component) getObject (currentPermanentFocusOwners); + return owner; + } + + /** + * Retrieve the {@link Component} that has the keyboard focus, + * regardless of whether or not it was set by a thread in the + * current {@link java.lang.ThreadGroup}. If there is no temporary + * focus owner in effect then this method will return the same value + * as {@link #getGlobalPermanentFocusOwner}. + * + * @return the keyboard focus owner + * @throws SecurityException if this is not the keyboard focus + * manager associated with the current {@link java.lang.ThreadGroup} + */ + protected Component getGlobalFocusOwner () + { + // Check if there is a temporary focus owner. + Component focusOwner = (Component) getGlobalObject (currentFocusOwners); + + return (focusOwner == null) ? getGlobalPermanentFocusOwner () : focusOwner; + } + + /** + * Set the {@link Component} that will be returned by {@link + * #getFocusOwner} (when it is called from the current {@link + * java.lang.ThreadGroup}) and {@link #getGlobalFocusOwner}. This + * method does not actually transfer the keyboard focus. + * + * @param owner the Component to return from getFocusOwner and + * getGlobalFocusOwner + * + * @see Component#requestFocus() + * @see Component#requestFocusInWindow() + */ + protected void setGlobalFocusOwner (Component owner) + { + if (owner == null || owner.focusable) + setGlobalObject (currentFocusOwners, owner, "focusOwner"); + } + + /** + * Clear the global focus owner and deliver a FOCUS_LOST event to + * the previously-focused {@link Component}. Until another {@link + * Component} becomes the keyboard focus owner, key events will be + * discarded by top-level windows. + */ + public void clearGlobalFocusOwner () + { + synchronized (currentFocusOwners) + { + Component focusOwner = getGlobalFocusOwner (); + Component permanentFocusOwner = getGlobalPermanentFocusOwner (); + + setGlobalFocusOwner (null); + setGlobalPermanentFocusOwner (null); + + // Inform the old focus owner that it has lost permanent + // focus. + if (focusOwner != null) + { + // We can't cache the event queue, because of + // bootstrapping issues. We need to set the default + // KeyboardFocusManager in EventQueue before the event + // queue is started. + EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue (); + if (focusOwner != permanentFocusOwner) + q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, true)); + else + q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, false)); + } + + if (focusOwner != permanentFocusOwner) + { + EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue (); + q.postEvent (new FocusEvent (permanentFocusOwner, FocusEvent.FOCUS_LOST, false)); + } + } + } + + /** + * Retrieve the {@link Component} that has the permanent keyboard + * focus, or null if the focus owner was not set by a thread in the + * current {@link java.lang.ThreadGroup}. + * + * @return the keyboard focus owner or null + */ + public Component getPermanentFocusOwner () + { + return (Component) getObject (currentPermanentFocusOwners); + } + + /** + * Retrieve the {@link Component} that has the permanent keyboard + * focus, regardless of whether or not it was set by a thread in the + * current {@link java.lang.ThreadGroup}. + * + * @return the keyboard focus owner + * @throws SecurityException if this is not the keyboard focus + * manager associated with the current {@link java.lang.ThreadGroup} + */ + protected Component getGlobalPermanentFocusOwner () + { + return (Component) getGlobalObject (currentPermanentFocusOwners); + } + + /** + * Set the {@link Component} that will be returned by {@link + * #getPermanentFocusOwner} (when it is called from the current + * {@link java.lang.ThreadGroup}) and {@link + * #getGlobalPermanentFocusOwner}. This method does not actually + * transfer the keyboard focus. + * + * @param focusOwner the Component to return from + * getPermanentFocusOwner and getGlobalPermanentFocusOwner + * + * @see Component#requestFocus() + * @see Component#requestFocusInWindow() + */ + protected void setGlobalPermanentFocusOwner (Component focusOwner) + { + if (focusOwner == null || focusOwner.focusable) + setGlobalObject (currentPermanentFocusOwners, focusOwner, + "permanentFocusOwner"); + } + + /** + * Retrieve the {@link Window} that is or contains the keyboard + * focus owner, or null if the focused window was not set by a + * thread in the current {@link java.lang.ThreadGroup}. + * + * @return the focused window or null + */ + public Window getFocusedWindow () + { + return (Window) getObject (currentFocusedWindows); + } + + /** + * Retrieve the {@link Window} that is or contains the focus owner, + * regardless of whether or not the {@link Window} was set focused + * by a thread in the current {@link java.lang.ThreadGroup}. + * + * @return the focused window + * @throws SecurityException if this is not the keyboard focus + * manager associated with the current {@link java.lang.ThreadGroup} + */ + protected Window getGlobalFocusedWindow () + { + return (Window) getGlobalObject (currentFocusedWindows); + } + + /** + * Set the {@link Window} that will be returned by {@link + * #getFocusedWindow} (when it is called from the current {@link + * java.lang.ThreadGroup}) and {@link #getGlobalFocusedWindow}. + * This method does not actually cause <code>window</code> to become + * the focused {@link Window}. + * + * @param window the Window to return from getFocusedWindow and + * getGlobalFocusedWindow + */ + protected void setGlobalFocusedWindow (Window window) + { + if (window == null || window.focusable) + setGlobalObject (currentFocusedWindows, window, "focusedWindow"); + } + + /** + * Retrieve the active {@link Window}, or null if the active window + * was not set by a thread in the current {@link + * java.lang.ThreadGroup}. + * + * @return the active window or null + */ + public Window getActiveWindow() + { + return (Window) getObject (currentActiveWindows); + } + + /** + * Retrieve the active {@link Window}, regardless of whether or not + * the {@link Window} was made active by a thread in the current + * {@link java.lang.ThreadGroup}. + * + * @return the active window + * @throws SecurityException if this is not the keyboard focus + * manager associated with the current {@link java.lang.ThreadGroup} + */ + protected Window getGlobalActiveWindow() + { + return (Window) getGlobalObject (currentActiveWindows); + } + + /** + * Set the {@link Window} that will be returned by {@link + * #getActiveWindow} (when it is called from the current {@link + * java.lang.ThreadGroup}) and {@link #getGlobalActiveWindow}. This + * method does not actually cause <code>window</code> to be made + * active. + * + * @param window the Window to return from getActiveWindow and + * getGlobalActiveWindow + */ + protected void setGlobalActiveWindow(Window window) + { + setGlobalObject (currentActiveWindows, window, "activeWindow"); + } + + /** + * Retrieve the default {@link FocusTraversalPolicy}. + * Focus-managing {@link Container}s use the returned object to + * define their initial focus traversal policy. + * + * @return a non-null default FocusTraversalPolicy object + */ + public FocusTraversalPolicy getDefaultFocusTraversalPolicy () + { + if (defaultPolicy == null) + defaultPolicy = new DefaultFocusTraversalPolicy (); + return defaultPolicy; + } + + /** + * Set the {@link FocusTraversalPolicy} returned by {@link + * #getDefaultFocusTraversalPolicy}. Focus-managing {@link + * Container}s created after this call will use policy as their + * initial focus traversal policy. Existing {@link Container}s' + * focus traversal policies will not be affected by calls to this + * method. + * + * @param policy the FocusTraversalPolicy that will be returned by + * subsequent calls to getDefaultFocusTraversalPolicy + * @throws IllegalArgumentException if policy is null + */ + public void setDefaultFocusTraversalPolicy (FocusTraversalPolicy policy) + { + if (policy == null) + throw new IllegalArgumentException (); + firePropertyChange ("defaultFocusTraversalPolicy", defaultPolicy, policy); + defaultPolicy = policy; + } + + /** + * Set the default {@link java.util.Set} of focus traversal keys for + * one of the focus traversal directions. + * + * @param id focus traversal direction identifier + * @param keystrokes set of AWTKeyStrokes + * + * @see #FORWARD_TRAVERSAL_KEYS + * @see #BACKWARD_TRAVERSAL_KEYS + * @see #UP_CYCLE_TRAVERSAL_KEYS + * @see #DOWN_CYCLE_TRAVERSAL_KEYS + */ + public void setDefaultFocusTraversalKeys (int id, Set keystrokes) + { + if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && + id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && + id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) + throw new IllegalArgumentException (); + + if (keystrokes == null) + throw new IllegalArgumentException (); + + Set sa; + Set sb; + Set sc; + String type; + switch (id) + { + case FORWARD_TRAVERSAL_KEYS: + sa = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS]; + sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS]; + sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS]; + type = "forwardDefaultFocusTraversalKeys"; + break; + case BACKWARD_TRAVERSAL_KEYS: + sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS]; + sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS]; + sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS]; + type = "backwardDefaultFocusTraversalKeys"; + break; + case UP_CYCLE_TRAVERSAL_KEYS: + sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS]; + sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS]; + sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS]; + type = "upCycleDefaultFocusTraversalKeys"; + break; + case DOWN_CYCLE_TRAVERSAL_KEYS: + sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS]; + sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS]; + sc = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS]; + type = "downCycleDefaultFocusTraversalKeys"; + break; + default: + throw new IllegalArgumentException (); + } + int i = keystrokes.size (); + Iterator iter = keystrokes.iterator (); + while (--i >= 0) + { + Object o = iter.next (); + if (!(o instanceof AWTKeyStroke) + || sa.contains (o) || sb.contains (o) || sc.contains (o) + || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED) + throw new IllegalArgumentException (); + } + keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes)); + firePropertyChange (type, defaultFocusKeys[id], keystrokes); + defaultFocusKeys[id] = keystrokes; + } + + /** + * Retrieve the default {@link java.util.Set} of focus traversal + * keys for one of the focus traversal directions. + * + * @param id focus traversal direction identifier + * + * @return the default set of AWTKeyStrokes + * + * @see #FORWARD_TRAVERSAL_KEYS + * @see #BACKWARD_TRAVERSAL_KEYS + * @see #UP_CYCLE_TRAVERSAL_KEYS + * @see #DOWN_CYCLE_TRAVERSAL_KEYS + */ + public Set getDefaultFocusTraversalKeys (int id) + { + if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS) + throw new IllegalArgumentException (); + return defaultFocusKeys[id]; + } + + /** + * Retrieve the current focus cycle root, or null if the focus owner + * was not set by a thread in the current {@link + * java.lang.ThreadGroup}. + * + * @return the current focus cycle root or null + */ + public Container getCurrentFocusCycleRoot () + { + return (Container) getObject (currentFocusCycleRoots); + } + + /** + * Retrieve the current focus cycle root, regardless of whether or + * not it was made set by a thread in the current {@link + * java.lang.ThreadGroup}. + * + * @return the current focus cycle root + * @throws SecurityException if this is not the keyboard focus + * manager associated with the current {@link java.lang.ThreadGroup} + */ + protected Container getGlobalCurrentFocusCycleRoot () + { + return (Container) getGlobalObject (currentFocusCycleRoots); + } + + /** + * Set the {@link Container} that will be returned by {@link + * #getCurrentFocusCycleRoot} (when it is called from the current + * {@link java.lang.ThreadGroup}) and {@link + * #getGlobalCurrentFocusCycleRoot}. This method does not actually + * make <code>cycleRoot</code> the current focus cycle root. + * + * @param cycleRoot the focus cycle root to return from + * getCurrentFocusCycleRoot and getGlobalCurrentFocusCycleRoot + */ + public void setGlobalCurrentFocusCycleRoot (Container cycleRoot) + { + setGlobalObject (currentFocusCycleRoots, cycleRoot, "currentFocusCycleRoot"); + } + + /** + * Registers the supplied property change listener for receiving + * events caused by the following property changes: + * + * <ul> + * <li>the current focus owner ("focusOwner")</li> + * <li>the permanent focus owner ("permanentFocusOwner")</li> + * <li>the focused window ("focusedWindow")</li> + * <li>the active window ("activeWindow")</li> + * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li> + * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li> + * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li> + * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li> + * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li> + * <li>the current focus cycle root ("currentFocusCycleRoot")</li> + * </ul> + * + * If the supplied listener is null, nothing occurs. + * + * @param l the new listener to register. + * @see KeyboardFocusManager#addPropertyChangeListener(String, java.beans.PropertyChangeListener) + */ + public void addPropertyChangeListener(PropertyChangeListener l) + { + if (l != null) + propertyChangeSupport.addPropertyChangeListener(l); + } + + /** + * Removes the supplied property change listener from the list + * of registered listeners. If the supplied listener is null, + * nothing occurs. + * + * @param l the listener to remove. + */ + public void removePropertyChangeListener(PropertyChangeListener l) + { + if (l != null) + propertyChangeSupport.removePropertyChangeListener(l); + } + + /** + * Returns the currently registered property change listeners + * in array form. The returned array is empty if no listeners are + * currently registered. + * + * @return an array of registered property change listeners. + */ + public PropertyChangeListener[] getPropertyChangeListeners() + { + return propertyChangeSupport.getPropertyChangeListeners(); + } + + /** + * Registers a property change listener for receiving events relating + * to a change to a specified property. The supplied property name can be + * either user-defined or one from the following list of properties + * relevant to this class: + * + * <ul> + * <li>the current focus owner ("focusOwner")</li> + * <li>the permanent focus owner ("permanentFocusOwner")</li> + * <li>the focused window ("focusedWindow")</li> + * <li>the active window ("activeWindow")</li> + * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li> + * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li> + * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li> + * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li> + * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li> + * <li>the current focus cycle root ("currentFocusCycleRoot")</li> + * </ul> + * + * Nothing occurs if a null listener is supplied. null is regarded as a valid property name. + * + * @param name the name of the property to handle change events for. + * @param l the listener to register for changes to the specified property. + * @see KeyboardFocusManager#addPropertyChangeListener(java.beans.PropertyChangeListener) + */ + public void addPropertyChangeListener(String name, PropertyChangeListener l) + { + if (l != null) + propertyChangeSupport.addPropertyChangeListener(name, l); + } + + /** + * Removes the supplied property change listener registered for the + * specified property from the list of registered listeners. If the + * supplied listener is null, nothing occurs. + * + * @param name the name of the property the listener is + * monitoring changes to. + * @param l the listener to remove. + */ + public void removePropertyChangeListener(String name, + PropertyChangeListener l) + { + if (l != null) + propertyChangeSupport.removePropertyChangeListener(name, l); + } + + /** + * Returns the currently registered property change listeners + * in array form, which listen for changes to the supplied property. + * The returned array is empty, if no listeners are currently registered + * for events pertaining to the supplied property. + * + * @param name The property the returned listeners monitor for changes. + * @return an array of registered property change listeners which + * listen for changes to the supplied property. + */ + public PropertyChangeListener[] getPropertyChangeListeners(String name) + { + return propertyChangeSupport.getPropertyChangeListeners(name); + } + + /** + * Fires a property change event as a response to a change to + * to the specified property. The event is only fired if a + * change has actually occurred (i.e. o and n are different). + * + * @param name The name of the property to which a change occurred. + * @param o The old value of the property. + * @param n The new value of the property. + */ + protected void firePropertyChange(String name, Object o, Object n) + { + propertyChangeSupport.firePropertyChange(name, o, n); + } + + /** + * Registers a vetoable property change listener for receiving events + * relating to the following properties: + * + * <ul> + * <li>the current focus owner ("focusOwner")</li> + * <li>the permanent focus owner ("permanentFocusOwner")</li> + * <li>the focused window ("focusedWindow")</li> + * <li>the active window ("activeWindow")</li> + * </ul> + * + * Nothing occurs if a null listener is supplied. + * + * @param l the listener to register. + * @see KeyboardFocusManager#addVetoableChangeListener(String, java.beans.VetoableChangeListener) + */ + public void addVetoableChangeListener(VetoableChangeListener l) + { + if (l != null) + vetoableChangeSupport.addVetoableChangeListener(l); + } + + /** + * Removes the supplied vetoable property change listener from + * the list of registered listeners. If the supplied listener + * is null, nothing occurs. + * + * @param l the listener to remove. + */ + public void removeVetoableChangeListener(VetoableChangeListener l) + { + if (l != null) + vetoableChangeSupport.removeVetoableChangeListener(l); + } + + /** + * Returns the currently registered vetoable property change listeners + * in array form. The returned array is empty if no listeners are + * currently registered. + * + * @return an array of registered vetoable property change listeners. + * @since 1.4 + */ + public VetoableChangeListener[] getVetoableChangeListeners() + { + return vetoableChangeSupport.getVetoableChangeListeners(); + } + + /** + * Registers a vetoable property change listener for receiving events relating + * to a vetoable change to a specified property. The supplied property name can be + * either user-defined or one from the following list of properties + * relevant to this class: + * + * <ul> + * <li>the current focus owner ("focusOwner")</li> + * <li>the permanent focus owner ("permanentFocusOwner")</li> + * <li>the focused window ("focusedWindow")</li> + * <li>the active window ("activeWindow")</li> + * </ul> + * + * Nothing occurs if a null listener is supplied. null is regarded as a valid property name. + * + * @param name the name of the property to handle change events for. + * @param l the listener to register for changes to the specified property. + * @see KeyboardFocusManager#addVetoableChangeListener(java.beans.VetoableChangeListener) + */ + public void addVetoableChangeListener(String name, VetoableChangeListener l) + { + if (l != null) + vetoableChangeSupport.addVetoableChangeListener(name, l); + } + + /** + * Removes the supplied vetoable property change listener registered + * for the specified property from the list of registered listeners. + * If the supplied listener is null, nothing occurs. + * + * @param name the name of the vetoable property the listener is + * monitoring changes to. + * @param l the listener to remove. + */ + public void removeVetoableChangeListener(String name, + VetoableChangeListener l) + { + if (l != null) + vetoableChangeSupport.removeVetoableChangeListener(name, l); + } + + /** + * Returns the currently registered vetoable property change listeners + * in array form, which listen for changes to the supplied property. + * The returned array is empty, if no listeners are currently registered + * for events pertaining to the supplied property. + * + * @param name The property the returned listeners monitor for changes. + * @return an array of registered property change listeners which + * listen for changes to the supplied property. + * @since 1.4 + */ + public VetoableChangeListener[] getVetoableChangeListeners(String name) + { + return vetoableChangeSupport.getVetoableChangeListeners(name); + } + + /** + * Fires a property change event as a response to a vetoable change to + * to the specified property. The event is only fired if a + * change has actually occurred (i.e. o and n are different). + * In the event that the property change is vetoed, the following + * occurs: + * + * <ol> + * <li> + * This method throws a <code>PropertyVetoException</code> to + * the proposed change. + * </li> + * <li> + * A new event is fired to reverse the previous change. + * </li> + * <li> + * This method again throws a <code>PropertyVetoException</code> + * in response to the reversion. + * </li> + * </ol> + * + * @param name The name of the property to which a change occurred. + * @param o The old value of the property. + * @param n The new value of the property. + * @throws PropertyVetoException if one of the listeners vetos + * the change by throwing this exception. + */ + protected void fireVetoableChange(String name, Object o, Object n) + throws PropertyVetoException + { + vetoableChangeSupport.fireVetoableChange(name, o, n); + } + + /** + * Adds a key event dispatcher to the list of registered dispatchers. + * When a key event is fired, each dispatcher's <code>dispatchKeyEvent</code> + * method is called in the order that they were added, prior to the manager + * dispatching the event itself. Notifications halt when one of the + * dispatchers returns true. + * <br /> + * <br /> + * The same dispatcher can exist multiple times within the list + * of registered dispatchers, and there is no limit on the length + * of this list. A null dispatcher is simply ignored. + * + * @param dispatcher The dispatcher to register. + */ + public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) + { + if (dispatcher != null) + keyEventDispatchers.add(dispatcher); + } + + /** + * Removes the specified key event dispatcher from the list of + * registered dispatchers. The manager always dispatches events, + * regardless of its existence within the list. The manager + * can be added and removed from the list, as with any other + * dispatcher, but this does not affect its ability to dispatch + * key events. Non-existent and null dispatchers are simply ignored + * by this method. + * + * @param dispatcher The dispatcher to remove. + */ + public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) + { + keyEventDispatchers.remove(dispatcher); + } + + /** + * Returns the currently registered key event dispatchers in <code>List</code> + * form. At present, this only includes dispatchers explicitly registered + * via the <code>addKeyEventDispatcher()</code> method, but this behaviour + * is subject to change and should not be depended on. The manager itself + * may be a member of the list, but only if explicitly registered. If no + * dispatchers have been registered, the list will be empty. + * + * @return A list of explicitly registered key event dispatchers. + * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher) + */ + protected List getKeyEventDispatchers () + { + return (List) keyEventDispatchers.clone (); + } + + /** + * Adds a key event post processor to the list of registered post processors. + * Post processors work in the same way as key event dispatchers, except + * that they are invoked after the manager has dispatched the key event, + * and not prior to this. Each post processor's <code>postProcessKeyEvent</code> + * method is called to see if any post processing needs to be performed. THe + * processors are called in the order in which they were added to the list, + * and notifications continue until one returns true. As with key event + * dispatchers, the manager is implicitly called following this process, + * regardless of whether or not it is present within the list. + * <br /> + * <br /> + * The same post processor can exist multiple times within the list + * of registered post processors, and there is no limit on the length + * of this list. A null post processor is simply ignored. + * + * @param postProcessor the post processor to register. + * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher) + */ + public void addKeyEventPostProcessor (KeyEventPostProcessor postProcessor) + { + if (postProcessor != null) + keyEventPostProcessors.add (postProcessor); + } + + /** + * Removes the specified key event post processor from the list of + * registered post processors. The manager always post processes events, + * regardless of its existence within the list. The manager + * can be added and removed from the list, as with any other + * post processor, but this does not affect its ability to post process + * key events. Non-existent and null post processors are simply ignored + * by this method. + * + * @param postProcessor the post processor to remove. + */ + public void removeKeyEventPostProcessor (KeyEventPostProcessor postProcessor) + { + keyEventPostProcessors.remove (postProcessor); + } + + /** + * Returns the currently registered key event post processors in <code>List</code> + * form. At present, this only includes post processors explicitly registered + * via the <code>addKeyEventPostProcessor()</code> method, but this behaviour + * is subject to change and should not be depended on. The manager itself + * may be a member of the list, but only if explicitly registered. If no + * post processors have been registered, the list will be empty. + * + * @return A list of explicitly registered key event post processors. + * @see KeyboardFocusManager#addKeyEventPostProcessor(java.awt.KeyEventPostProcessor) + */ + protected List getKeyEventPostProcessors () + { + return (List) keyEventPostProcessors.clone (); + } + + /** + * The AWT event dispatcher uses this method to request that the manager + * handle a particular event. If the manager fails or refuses to + * dispatch the supplied event (this method returns false), the + * AWT event dispatcher will try to dispatch the event itself. + * <br /> + * <br /> + * The manager is expected to handle all <code>FocusEvent</code>s + * and <code>KeyEvent</code>s, and <code>WindowEvent</code>s + * relating to the focus. Dispatch is done with regard to the + * the focus owner and the currently focused and active windows. + * In handling the event, the source of the event may be overridden. + * <br /> + * <br /> + * The actual dispatching is performed by calling + * <code>redispatchEvent()</code>. This avoids the infinite recursion + * of dispatch requests which may occur if this method is called on + * the target component. + * + * @param e the event to dispatch. + * @return true if the event was dispatched. + * @see KeyboardFocusManager#redispatchEvent(java.awt.Component, java.awt.AWTEvent) + * @see KeyEvent + * @see FocusEvent + * @see WindowEvent + */ + public abstract boolean dispatchEvent (AWTEvent e); + + /** + * Handles redispatching of an event so that recursion of + * dispatch requests does not occur. Event dispatch methods + * within this manager (<code>dispatchEvent()</code>) and + * the key event dispatchers should use this method to handle + * dispatching rather than the dispatch method of the target + * component. + * <br /> + * <br /> + * <strong> + * This method is not intended for general consumption, and is + * only for the use of the aforementioned classes. + * </strong> + * + * @param target the target component to which the event is + * dispatched. + * @param e the event to dispatch. + */ + public final void redispatchEvent (Component target, AWTEvent e) + { + synchronized (e) + { + e.setSource (target); + target.dispatchEvent (e); + } + } + + /** + * Attempts to dispatch key events for which no key event dispatcher + * has so far succeeded. This method is usually called by + * <code>dispatchEvent()</code> following the sending of the key + * event to any registered key event dispatchers. If the key + * event reaches this stage, none of the dispatchers returned + * true. This is, of course, always the case if there are no + * registered dispatchers. + * <br /> + * <br /> + * If this method also fails to handle the key event, then + * false is returned to the caller. In the case of + * <code>dispatchEvent()</code>, the calling method may try + * to handle the event itself or simply forward on the + * false result to its caller. When the event is dispatched + * by this method, a true result is propogated through the + * calling methods. + * + * @param e the key event to dispatch. + * @return true if the event was dispatched successfully. + */ + public abstract boolean dispatchKeyEvent (KeyEvent e); + + /** + * Handles the post processing of key events. By default, + * this method will map unhandled key events to appropriate + * <code>MenuShortcut</code>s. The event is consumed + * in the process and the shortcut is activated. This + * method is usually called by <code>dispatchKeyEvent</code>. + * + * @param e the key event to post process. + * @return true by default, as the event was handled. + */ + public abstract boolean postProcessKeyEvent (KeyEvent e); + + /** + * Handles focus traversal operations for key events which + * represent focus traversal keys in relation to the supplied + * component. The supplied component is assumed to have the + * focus, whether it does so or not, and the operation is + * carried out as appropriate, with this in mind. + * + * @param focused the component on which to perform focus traversal, + * on the assumption that this component has the focus. + * @param e the possible focus traversal key event. + */ + public abstract void processKeyEvent (Component focused, KeyEvent e); + + /** + * Delays all key events following the specified timestamp until the + * supplied component has focus. The AWT calls this method when it is + * determined that a focus change may occur within the native windowing + * system. Any key events which occur following the time specified by + * after are delayed until a <code>FOCUS_GAINED</code> event is received + * for the untilFocused component. The manager is responsible for ensuring + * this takes place. + * + * @param after the timestamp beyond which all key events are delayed until + * the supplied component gains focus. + * @param untilFocused the component to wait on gaining focus. + */ + protected abstract void enqueueKeyEvents (long after, Component untilFocused); + + /** + * Removes the key event block specified by the supplied timestamp and component. + * All delayed key events are released for normal dispatching following its + * removal and subsequent key events that would have been blocked are now + * immediately dispatched. If the specified timestamp is below 0, then + * the request with the oldest timestamp is removed. + * + * @param after the timestamp of the key event block to be removed, or a + * value smaller than 0 if the oldest is to be removed. + * @param untilFocused the component of the key event block to be removed. + */ + protected abstract void dequeueKeyEvents (long after, Component untilFocused); + + /** + * Discards all key event blocks relating to focus requirements for + * the supplied component, regardless of timestamp. + * + * @param comp the component of the key event block(s) to be removed. + */ + protected abstract void discardKeyEvents (Component comp); + + /** + * Moves the current focus to the next component following + * comp, based on the current focus traversal policy. By + * default, only visible, displayable, accepted components + * can receive focus. <code>Canvas</code>es, <code>Panel</code>s, + * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s, + * <code>Window</code>s and lightweight components are judged + * to be unacceptable by default. See the + * <code>DefaultFocusTraversalPolicy</code> for more details. + * + * @param comp the component prior to the one which will + * become the focus, following execution of this method. + * @see DefaultFocusTraversalPolicy + */ + public abstract void focusNextComponent(Component comp); + + /** + * Moves the current focus to the previous component, prior to + * comp, based on the current focus traversal policy. By + * default, only visible, displayable, accepted components + * can receive focus. <code>Canvas</code>es, <code>Panel</code>s, + * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s, + * <code>Window</code>s and lightweight components are judged + * to be unacceptable by default. See the + * <code>DefaultFocusTraversalPolicy</code> for more details. + * + * @param comp the component following the one which will + * become the focus, following execution of this method. + * @see DefaultFocusTraversalPolicy + */ + public abstract void focusPreviousComponent(Component comp); + + /** + * Moves the current focus upwards by one focus cycle. + * Both the current focus owner and current focus cycle root + * become the focus cycle root of the supplied component. + * However, in the case of a <code>Window</code>, the default + * focus component becomes the focus owner and the focus cycle + * root is not changed. + * + * @param comp the component used as part of the focus traversal. + */ + public abstract void upFocusCycle(Component comp); + + /** + * Moves the current focus downwards by one focus cycle. + * If the supplied container is a focus cycle root, then this + * becomes the current focus cycle root and the focus goes + * to the default component of the specified container. + * Nothing happens for non-focus cycle root containers. + * + * @param cont the container used as part of the focus traversal. + */ + public abstract void downFocusCycle(Container cont); + + /** + * Moves the current focus to the next component, based on the + * current focus traversal policy. By default, only visible, + * displayable, accepted component can receive focus. + * <code>Canvas</code>es, <code>Panel</code>s, + * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s, + * <code>Window</code>s and lightweight components are judged + * to be unacceptable by default. See the + * <code>DefaultFocusTraversalPolicy</code> for more details. + * + * @see DefaultFocusTraversalPolicy + */ + public final void focusNextComponent() + { + focusNextComponent (null); + } + + /** + * Moves the current focus to the previous component, based on the + * current focus traversal policy. By default, only visible, + * displayable, accepted component can receive focus. + * <code>Canvas</code>es, <code>Panel</code>s, + * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s, + * <code>Window</code>s and lightweight components are judged + * to be unacceptable by default. See the + * <code>DefaultFocusTraversalPolicy</code> for more details. + * + * @see DefaultFocusTraversalPolicy + */ + public final void focusPreviousComponent() + { + focusPreviousComponent (null); + } + + /** + * Moves the current focus upwards by one focus cycle, + * so that the new focus owner is the focus cycle root + * of the current owner. The current focus cycle root then + * becomes the focus cycle root of the new focus owner. + * However, in the case of the focus cycle root of the + * current focus owner being a <code>Window</code>, the default + * component of this window becomes the focus owner and the + * focus cycle root is not changed. + */ + public final void upFocusCycle() + { + upFocusCycle (null); + } + + /** + * Moves the current focus downwards by one focus cycle, + * iff the current focus cycle root is a <code>Container</code>. + * Usually, the new focus owner is set to the default component + * of the container and the current focus cycle root is set + * to the current focus owner. Nothing occurs if the current + * focus cycle root is not a container. + */ + public final void downFocusCycle() + { + Component focusOwner = getGlobalFocusOwner (); + if (focusOwner instanceof Container + && ((Container) focusOwner).isFocusCycleRoot ()) + downFocusCycle ((Container) focusOwner); + } + + /** + * Retrieve an object from one of the global object {@link + * java.util.Map}s, if the object was set by the a thread in the + * current {@link java.lang.ThreadGroup}. Otherwise, return null. + * + * @param globalMap one of the global object Maps + * + * @return a global object set by the current ThreadGroup, or null + * + * @see getFocusOwner + * @see getPermanentFocusOwner + * @see getFocusedWindow + * @see getActiveWindow + * @see getCurrentFocusCycleRoot + */ + private Object getObject (Map globalMap) + { + ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup (); + return globalMap.get (currentGroup); + } + + /** + * Retrieve an object from one of the global object {@link + * java.util.Map}s, regardless of whether or not the object was set + * by a thread in the current {@link java.lang.ThreadGroup}. + * + * @param globalMap one of the global object Maps + * + * @return a global object set by the current ThreadGroup, or null + * + * @throws SecurityException if this is not the keyboard focus + * manager associated with the current {@link java.lang.ThreadGroup} + * + * @see getGlobalFocusOwner + * @see getGlobalPermanentFocusOwner + * @see getGlobalFocusedWindow + * @see getGlobalActiveWindow + * @see getGlobalCurrentFocusCycleRoot + */ + private Object getGlobalObject (Map globalMap) + { + ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup (); + KeyboardFocusManager managerForCallingThread + = (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup); + + if (this != managerForCallingThread) + throw new SecurityException ("Attempted to retrieve an object from a " + + "keyboard focus manager that isn't " + + "associated with the current thread group."); + + synchronized (globalMap) + { + Collection globalObjects = globalMap.values (); + Iterator i = globalObjects.iterator (); + Component globalObject; + + while (i.hasNext ()) + { + globalObject = (Component) i.next (); + if (globalObject != null) + return globalObject; + } + } + + // No Object was found. + return null; + } + + /** + * Set an object in one of the global object {@link java.util.Map}s, + * that will be returned by subsequent calls to getGlobalObject on + * the same {@link java.util.Map}. + * + * @param globalMap one of the global object Maps + * @param newObject the object to set + * @param property the property that will change + * + * @see setGlobalFocusOwner + * @see setGlobalPermanentFocusOwner + * @see setGlobalFocusedWindow + * @see setGlobalActiveWindow + * @see setGlobalCurrentFocusCycleRoot + */ + private void setGlobalObject (Map globalMap, + Object newObject, + String property) + { + synchronized (globalMap) + { + // Save old object. + Object oldObject = getGlobalObject (globalMap); + + // Nullify old object. + Collection threadGroups = globalMap.keySet (); + Iterator i = threadGroups.iterator (); + while (i.hasNext ()) + { + ThreadGroup oldThreadGroup = (ThreadGroup) i.next (); + if (globalMap.get (oldThreadGroup) != null) + { + globalMap.put (oldThreadGroup, null); + // There should only be one object set at a time, so + // we can short circuit. + break; + } + } + + ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup (); + firePropertyChange (property, oldObject, newObject); + try + { + fireVetoableChange (property, oldObject, newObject); + // Set new object. + globalMap.put (currentGroup, newObject); + } + catch (PropertyVetoException e) + { + } + } + } +} diff --git a/libjava/classpath/java/awt/Label.java b/libjava/classpath/java/awt/Label.java new file mode 100644 index 0000000..8867fa1 --- /dev/null +++ b/libjava/classpath/java/awt/Label.java @@ -0,0 +1,314 @@ +/* Label.java -- Java label widget + Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.peer.LabelPeer; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * This component is used for displaying simple text strings that cannot + * be edited by the user. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Tom Tromey (tromey@cygnus.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ +public class Label extends Component implements Accessible +{ + +/* + * Static Variables + */ + +/** + * Alignment constant aligning the text to the left of its window. + */ +public static final int LEFT = 0; + +/** + * Alignment constant aligning the text in the center of its window. + */ +public static final int CENTER = 1; + +/** + * Alignment constant aligning the text to the right of its window. + */ +public static final int RIGHT = 2; + +// Serialization version constant: +private static final long serialVersionUID = 3094126758329070636L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial Indicates the alignment of the text within this label's window. + * This is one of the constants in this class. The default value is + * <code>LEFT</code>. + */ +private int alignment; + +/** + * @serial The text displayed in the label + */ +private String text; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>Label</code> with no text. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +Label() +{ + this("", LEFT); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Label</code> with the specified + * text that is aligned to the left. + * + * @param text The text of the label. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +Label(String text) +{ + this(text, LEFT); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Label</code> with the specified + * text and alignment. + * + * @param text The text of the label. + * @param alignment The desired alignment for the text in this label, + * which must be one of <code>LEFT</code>, <code>CENTER</code>, or + * <code>RIGHT</code>. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +Label(String text, int alignment) +{ + setAlignment (alignment); + setText (text); + + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException (); +} + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * Returns the constant indicating the alignment of the text in this + * label. The value returned will be one of the alignment constants + * from this class. + * + * @return The alignment of the text in the label. + */ +public int +getAlignment() +{ + return(alignment); +} + +/*************************************************************************/ + +/** + * Sets the text alignment of this label to the specified value. + * + * @param alignment The desired alignment for the text in this label, + * which must be one of <code>LEFT</code>, <code>CENTER</code>, or + * <code>RIGHT</code>. + */ +public synchronized void +setAlignment(int alignment) +{ + if (alignment != CENTER && alignment != LEFT && alignment != RIGHT) + throw new IllegalArgumentException ("invalid alignment: " + alignment); + this.alignment = alignment; + if (peer != null) + { + LabelPeer lp = (LabelPeer) peer; + lp.setAlignment (alignment); + } +} + +/*************************************************************************/ + +/** + * Returns the text displayed in this label. + * + * @return The text for this label. + */ +public String +getText() +{ + return(text); +} + +/*************************************************************************/ + +/** + * Sets the text in this label to the specified value. + * + * @param text The new text for this label. + */ +public synchronized void +setText(String text) +{ + this.text = text; + + if (peer != null) + { + LabelPeer lp = (LabelPeer) peer; + lp.setText (text); + } +} + +/*************************************************************************/ + +/** + * Notifies this label that it has been added to a container, causing + * the peer to be created. This method is called internally by the AWT + * system. + */ +public void +addNotify() +{ + if (peer == null) + peer = getToolkit ().createLabel (this); + super.addNotify (); +} + +/*************************************************************************/ + +/** + * Returns a parameter string useful for debugging. + * + * @return A debugging string. + */ +protected String +paramString() +{ + return ("text=" + getText() + ",alignment=" + + getAlignment() + "," + super.paramString()); +} + +/** + * This class provides accessibility support for the label. + */ +protected class AccessibleAWTLabel + extends AccessibleAWTComponent +{ + /** + * For compatability with Sun's JDK 1.4.2 rev. 5 + */ + private static final long serialVersionUID = -3568967560160480438L; + + /** + * Constructor for the accessible label. + */ + public AccessibleAWTLabel() + { + } + + /** + * Returns the accessible name for the label. This is + * the text used in the label. + * + * @return a <code>String</code> containing the accessible + * name for this label. + */ + public String getAccessibleName() + { + return getText(); + } + + /** + * Returns the accessible role for the label. + * + * @return an instance of <code>AccessibleRole</code>, describing + * the role of the label. + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.LABEL; + } + +} + +/** + * Gets the AccessibleContext associated with this <code>Label</code>. + * The context is created, if necessary. + * + * @return the associated context + */ +public AccessibleContext getAccessibleContext() +{ + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTLabel(); + return accessibleContext; +} + +} // class Label + diff --git a/libjava/classpath/java/awt/LayoutManager.java b/libjava/classpath/java/awt/LayoutManager.java new file mode 100644 index 0000000..62ff808 --- /dev/null +++ b/libjava/classpath/java/awt/LayoutManager.java @@ -0,0 +1,92 @@ +/* LayoutManager.java -- lay out elements in a Container + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This interface is for laying out containers in a particular sequence. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see Container + * @since 1.0 + * @status updated to 1.4 + */ +public interface LayoutManager +{ + /** + * Adds the specified component to the layout group. + * + * @param name the name of the component to add + * @param component the component to add + */ + void addLayoutComponent(String name, Component component); + + /** + * Removes the specified component from the layout group. + * + * @param component the component to remove + */ + void removeLayoutComponent(Component component); + + /** + * Calculates the preferred size for this container, taking into account + * the components it contains. + * + * @param parent the parent container to lay out + * @return the preferred dimensions of this container + * @see #minimumLayoutSize(Container) + */ + Dimension preferredLayoutSize(Container parent); + + /** + * Calculates the minimum size for this container, taking into account + * the components it contains. + * + * @param parent the parent container to lay out + * @return the minimum dimensions of this container + * @see #preferredLayoutSize(Container) + */ + Dimension minimumLayoutSize(Container parent); + + /** + * Lays out the components in the given container. + * + * @param parent the container to lay out + */ + void layoutContainer(Container parent); +} // interface LayoutManager diff --git a/libjava/classpath/java/awt/LayoutManager2.java b/libjava/classpath/java/awt/LayoutManager2.java new file mode 100644 index 0000000..45fc543 --- /dev/null +++ b/libjava/classpath/java/awt/LayoutManager2.java @@ -0,0 +1,100 @@ +/* LayoutManager2.java -- enhanced layout manager + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * Layout manager for laying out containers based on contraints. The + * constraints control how the layout will proceed. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see LayoutManager + * @see Container + * @since 1.0 + * @status updated to 1.4 + */ +public interface LayoutManager2 extends LayoutManager +{ + /** + * Adds the specified component to the layout, with the specified + * constraints object. + * + * @param component the component to add + * @param constraints the constraints to satisfy + */ + void addLayoutComponent(Component component, Object constraints); + + /** + * Determines the maximum size of the specified target container. + * + * @param target the container to lay out + * @return the maximum size of the container + * @see Component#getMaximumSize() + */ + Dimension maximumLayoutSize(Container target); + + /** + * Returns the preferred X axis alignment for the specified target + * container. This value will range from 0 to 1 where 0 is alignment + * closest to the origin, 0.5 is centered, and 1 is aligned furthest + * from the origin. + * + * @param target the target container + * @return the x-axis alignment preference + */ + float getLayoutAlignmentX(Container target); + + /** + * Returns the preferred Y axis alignment for the specified target + * container. This value will range from 0 to 1 where 0 is alignment + * closest to the origin, 0.5 is centered, and 1 is aligned furthest + * from the origin. + * + * @param target the target container + * @return the y-axis alignment preference + */ + float getLayoutAlignmentY(Container target); + + /** + * Forces the layout manager to purge any cached information about the + * layout of the target container. This will force it to be recalculated. + * + * @param target the target container + */ + void invalidateLayout(Container target); +} // interface LayoutManager2 diff --git a/libjava/classpath/java/awt/List.java b/libjava/classpath/java/awt/List.java new file mode 100644 index 0000000..5fcc79b --- /dev/null +++ b/libjava/classpath/java/awt/List.java @@ -0,0 +1,1263 @@ +/* List.java -- A listbox widget + Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.peer.ListPeer; +import java.util.EventListener; +import java.util.Vector; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleSelection; +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +/** + * Class that implements a listbox widget + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class List extends Component + implements ItemSelectable, Accessible +{ + +/* + * Static Variables + */ + +// Serialization constant +private static final long serialVersionUID = -3304312411574666869L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +// FIXME: Need read/writeObject + +/** + * @serial The items in the list. + */ +private Vector items = new Vector(); + +/** + * @serial Indicates whether or not multiple items can be selected + * simultaneously. + */ +private boolean multipleMode; + +/** + * @serial The number of rows in the list. This is set on creation + * only and cannot be modified. + */ +private int rows; + +/** + * @serial An array of the item indices that are selected. + */ +private int[] selected; + +/** + * @serial An index value used by <code>makeVisible()</code> and + * <code>getVisibleIndex</code>. + */ +private int visibleIndex; + +// The list of ItemListeners for this object. +private ItemListener item_listeners; + +// The list of ActionListeners for this object. +private ActionListener action_listeners; + + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>List</code> with no visible lines + * and multi-select disabled. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +List() +{ + this(4, false); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>List</code> with the specified + * number of visible lines and multi-select disabled. + * + * @param rows The number of visible rows in the list. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +List(int rows) +{ + this(rows, false); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>List</code> with the specified + * number of lines and the specified multi-select setting. + * + * @param rows The number of visible rows in the list. + * @param multipleMode <code>true</code> if multiple lines can be selected + * simultaneously, <code>false</code> otherwise. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +List(int rows, boolean multipleMode) +{ + this.rows = rows; + this.multipleMode = multipleMode; + + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException (); +} + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * Returns the number of items in this list. + * + * @return The number of items in this list. + */ +public int +getItemCount() +{ + return countItems (); +} + +/*************************************************************************/ + +/** + * Returns the number of items in this list. + * + * @return The number of items in this list. + * + * @deprecated This method is deprecated in favor of + * <code>getItemCount()</code> + */ +public int +countItems() +{ + return items.size (); +} + +/*************************************************************************/ + +/** + * Returns the complete list of items. + * + * @return The complete list of items in the list. + */ +public synchronized String[] +getItems() +{ + String[] l_items = new String[getItemCount()]; + + items.copyInto(l_items); + return(l_items); +} + +/*************************************************************************/ + +/** + * Returns the item at the specified index. + * + * @param index The index of the item to retrieve. + * + * @exception IndexOutOfBoundsException If the index value is not valid. + */ +public String +getItem(int index) +{ + return((String)items.elementAt(index)); +} + +/*************************************************************************/ + +/** + * Returns the number of visible rows in the list. + * + * @return The number of visible rows in the list. + */ +public int +getRows() +{ + return(rows); +} + +/*************************************************************************/ + +/** + * Tests whether or not multi-select mode is enabled. + * + * @return <code>true</code> if multi-select mode is enabled, + * <code>false</code> otherwise. + */ +public boolean +isMultipleMode() +{ + return allowsMultipleSelections (); +} + +/*************************************************************************/ + +/** + * Tests whether or not multi-select mode is enabled. + * + * @return <code>true</code> if multi-select mode is enabled, + * <code>false</code> otherwise. + * + * @deprecated This method is deprecated in favor of + * <code>isMultipleMode()</code>. + */ +public boolean +allowsMultipleSelections() +{ + return multipleMode; +} + +/*************************************************************************/ + +/** + * This method enables or disables multiple selection mode for this + * list. + * + * @param multipleMode <code>true</code> to enable multiple mode, + * <code>false</code> otherwise. + */ +public void +setMultipleMode(boolean multipleMode) +{ + setMultipleSelections (multipleMode); +} + +/*************************************************************************/ + +/** + * This method enables or disables multiple selection mode for this + * list. + * + * @param multipleMode <code>true</code> to enable multiple mode, + * <code>false</code> otherwise. + * + * @deprecated + */ +public void +setMultipleSelections(boolean multipleMode) +{ + this.multipleMode = multipleMode; + + ListPeer peer = (ListPeer) getPeer (); + if (peer != null) + peer.setMultipleMode (multipleMode); +} + +/*************************************************************************/ + +/** + * Returns the minimum size of this component. + * + * @return The minimum size of this component. + */ +public Dimension +getMinimumSize() +{ + return getMinimumSize (getRows ()); +} + +/*************************************************************************/ + +/** + * Returns the minimum size of this component. + * + * @return The minimum size of this component. + * + * @deprecated This method is deprecated in favor of + * <code>getMinimumSize</code>. + */ +public Dimension +minimumSize() +{ + return minimumSize (getRows ()); +} + +/*************************************************************************/ + +/** + * Returns the minimum size of this component assuming it had the specified + * number of rows. + * + * @param rows The number of rows to size for. + * + * @return The minimum size of this component. + */ +public Dimension +getMinimumSize(int rows) +{ + return minimumSize (rows); +} + +/*************************************************************************/ + +/** + * Returns the minimum size of this component assuming it had the specified + * number of rows. + * + * @param rows The number of rows to size for. + * + * @return The minimum size of this component. + * + * @deprecated This method is deprecated in favor of + * <code>getMinimumSize(int)</code>> + */ +public Dimension +minimumSize(int rows) +{ + ListPeer peer = (ListPeer) getPeer (); + if (peer != null) + return peer.minimumSize (rows); + else + return new Dimension (0, 0); +} + +/*************************************************************************/ + +/** + * Returns the preferred size of this component. + * + * @return The preferred size of this component. + */ +public Dimension +getPreferredSize() +{ + return getPreferredSize (getRows ()); +} + +/*************************************************************************/ + +/** + * Returns the preferred size of this component. + * + * @return The preferred size of this component. + * + * @deprecated This method is deprecated in favor of + * <code>getPreferredSize</code>. + */ +public Dimension +preferredSize() +{ + return preferredSize (getRows ()); +} + +/*************************************************************************/ + +/** + * Returns the preferred size of this component assuming it had the specified + * number of rows. + * + * @param rows The number of rows to size for. + * + * @return The preferred size of this component. + */ +public Dimension +getPreferredSize(int rows) +{ + return preferredSize (rows); +} + +/*************************************************************************/ + +/** + * Returns the preferred size of this component assuming it had the specified + * number of rows. + * + * @param rows The number of rows to size for. + * + * @return The preferred size of this component. + * + * @deprecated This method is deprecated in favor of + * <code>getPreferredSize(int)</code>> + */ +public Dimension +preferredSize(int rows) +{ + ListPeer peer = (ListPeer) getPeer (); + if (peer != null) + return peer.preferredSize (rows); + else + return new Dimension (0, 0); +} + +/*************************************************************************/ + +/** + * This method adds the specified item to the end of the list. + * + * @param item The item to add to the list. + */ +public void +add(String item) +{ + add (item, -1); +} + +/*************************************************************************/ + +/** + * This method adds the specified item to the end of the list. + * + * @param item The item to add to the list. + * + * @deprecated Use add() instead. + */ +public void +addItem(String item) +{ + addItem (item, -1); +} + +/*************************************************************************/ + +/** + * Adds the specified item to the specified location in the list. + * If the desired index is -1 or greater than the number of rows + * in the list, then the item is added to the end. + * + * @param item The item to add to the list. + * @param index The location in the list to add the item, or -1 to add + * to the end. + */ +public void +add(String item, int index) +{ + addItem (item, index); +} + +/*************************************************************************/ + +/** + * Adds the specified item to the specified location in the list. + * If the desired index is -1 or greater than the number of rows + * in the list, then the item is added to the end. + * + * @param item The item to add to the list. + * @param index The location in the list to add the item, or -1 to add + * to the end. + * + * @deprecated Use add() instead. + */ +public void +addItem(String item, int index) +{ + if ((index == -1) || (index >= items.size ())) + items.addElement (item); + else + items.insertElementAt (item, index); + + ListPeer peer = (ListPeer) getPeer (); + if (peer != null) + peer.add (item, index); +} + +/*************************************************************************/ + +/** + * Deletes the item at the specified index. + * + * @param index The index of the item to delete. + * + * @exception IllegalArgumentException If the index is not valid + * + * @deprecated + */ +public void +delItem(int index) throws IllegalArgumentException +{ + items.removeElementAt (index); + + ListPeer peer = (ListPeer) getPeer (); + if (peer != null) + peer.delItems (index, index); +} + +/*************************************************************************/ + +/** + * Deletes the item at the specified index. + * + * @param index The index of the item to delete. + * + * @exception IllegalArgumentException If the index is not valid + */ +public void +remove(int index) throws IllegalArgumentException +{ + delItem (index); +} + +/*************************************************************************/ + +/** + * Deletes all items in the specified index range. + * + * @param start The beginning index of the range to delete. + * @param end The ending index of the range to delete. + * + * @exception IllegalArgumentException If the indexes are not valid + * + * @deprecated This method is deprecated for some unknown reason. + */ +public synchronized void +delItems(int start, int end) throws IllegalArgumentException +{ + if ((start < 0) || (start >= items.size())) + throw new IllegalArgumentException("Bad list start index value: " + start); + + if ((start < 0) || (start >= items.size())) + throw new IllegalArgumentException("Bad list start index value: " + start); + + if (start > end) + throw new IllegalArgumentException("Start is greater than end!"); + + // We must run the loop in reverse direction. + for (int i = end; i >= start; --i) + items.removeElementAt (i); + if (peer != null) + { + ListPeer l = (ListPeer) peer; + l.delItems (start, end); + } +} + +/*************************************************************************/ + +/** + * Deletes the first occurrence of the specified item from the list. + * + * @param item The item to delete. + * + * @exception IllegalArgumentException If the specified item does not exist. + */ +public synchronized void +remove(String item) throws IllegalArgumentException +{ + int index = items.indexOf(item); + if (index == -1) + throw new IllegalArgumentException("List element to delete not found"); + + remove(index); +} + +/*************************************************************************/ + +/** + * Deletes all of the items from the list. + */ +public synchronized void +removeAll() +{ + clear (); +} + +/*************************************************************************/ + +/** + * Deletes all of the items from the list. + * + * @deprecated This method is deprecated in favor of <code>removeAll()</code>. + */ +public void +clear() +{ + items.clear(); + + ListPeer peer = (ListPeer) getPeer (); + if (peer != null) + peer.removeAll (); +} + +/*************************************************************************/ + +/** + * Replaces the item at the specified index with the specified item. + * + * @param item The new item value. + * @param index The index of the item to replace. + * + * @exception IllegalArgumentException If the index is not valid. + */ +public synchronized void +replaceItem(String item, int index) throws IllegalArgumentException +{ + if ((index < 0) || (index >= items.size())) + throw new IllegalArgumentException("Bad list index: " + index); + + items.insertElementAt(item, index + 1); + items.removeElementAt (index); + + if (peer != null) + { + ListPeer l = (ListPeer) peer; + + /* We add first and then remove so that the selected + item remains the same */ + l.add (item, index + 1); + l.delItems (index, index); + } +} + +/*************************************************************************/ + +/** + * Returns the index of the currently selected item. -1 will be returned + * if there are no selected rows or if there are multiple selected rows. + * + * @return The index of the selected row. + */ +public synchronized int +getSelectedIndex() +{ + if (peer != null) + { + ListPeer l = (ListPeer) peer; + selected = l.getSelectedIndexes (); + } + + if (selected == null || selected.length != 1) + return -1; + return selected[0]; +} + +/*************************************************************************/ + +/** + * Returns an array containing the indexes of the rows that are + * currently selected. + * + * @return A list of indexes of selected rows. + */ +public synchronized int[] +getSelectedIndexes() +{ + if (peer != null) + { + ListPeer l = (ListPeer) peer; + selected = l.getSelectedIndexes (); + } + return selected; +} + +/*************************************************************************/ + +/** + * Returns the item that is currently selected, or <code>null</code> if there + * is no item selected. FIXME: What happens if multiple items selected? + * + * @return The selected item, or <code>null</code> if there is no + * selected item. + */ +public synchronized String +getSelectedItem() +{ + int index = getSelectedIndex(); + if (index == -1) + return(null); + + return((String)items.elementAt(index)); +} + +/*************************************************************************/ + +/** + * Returns the list of items that are currently selected in this list. + * + * @return The list of currently selected items. + */ +public synchronized String[] +getSelectedItems() +{ + int[] indexes = getSelectedIndexes(); + if (indexes == null) + return(new String[0]); + + String[] retvals = new String[indexes.length]; + if (retvals.length > 0) + for (int i = 0 ; i < retvals.length; i++) + retvals[i] = (String)items.elementAt(indexes[i]); + + return(retvals); +} + +/*************************************************************************/ + +/** + * Returns the list of items that are currently selected in this list as + * an array of type <code>Object[]</code> instead of <code>String[]</code>. + * + * @return The list of currently selected items. + */ +public synchronized Object[] +getSelectedObjects() +{ + int[] indexes = getSelectedIndexes(); + if (indexes == null) + return(new Object[0]); + + Object[] retvals = new Object[indexes.length]; + if (retvals.length > 0) + for (int i = 0 ; i < retvals.length; i++) + retvals[i] = items.elementAt(indexes[i]); + + return(retvals); +} + +/*************************************************************************/ + +/** + * Tests whether or not the specified index is selected. + * + * @param index The index to test. + * + * @return <code>true</code> if the index is selected, <code>false</code> + * otherwise. + */ +public boolean +isIndexSelected(int index) +{ + return isSelected (index); +} + +/*************************************************************************/ + +/** + * Tests whether or not the specified index is selected. + * + * @param index The index to test. + * + * @return <code>true</code> if the index is selected, <code>false</code> + * otherwise. + * + * @deprecated This method is deprecated in favor of + * <code>isIndexSelected(int)</code>. + */ +public boolean +isSelected(int index) +{ + int[] indexes = getSelectedIndexes (); + + for (int i = 0; i < indexes.length; i++) + if (indexes[i] == index) + return true; + + return false; +} + +/*************************************************************************/ + +/** + * This method ensures that the item at the specified index is visible. + * + * @exception IllegalArgumentException If the specified index is out of + * range. + */ +public synchronized void +makeVisible(int index) throws IllegalArgumentException +{ + if ((index < 0) || (index >= items.size())) + throw new IllegalArgumentException("Bad list index: " + index); + + visibleIndex = index; + if (peer != null) + { + ListPeer l = (ListPeer) peer; + l.makeVisible (index); + } +} + +/*************************************************************************/ + +/** + * Returns the index of the last item that was made visible via the + * <code>makeVisible()</code> method. + * + * @return The index of the last item made visible via the + * <code>makeVisible()</code> method. + */ +public int +getVisibleIndex() +{ + return(visibleIndex); +} + +/*************************************************************************/ + +/** + * Makes the item at the specified index selected. + * + * @param index The index of the item to select. + */ +public synchronized void +select(int index) +{ + ListPeer lp = (ListPeer)getPeer(); + if (lp != null) + lp.select(index); +} + +/*************************************************************************/ + +/** + * Makes the item at the specified index not selected. + * + * @param index The index of the item to unselect. + */ +public synchronized void +deselect(int index) +{ + ListPeer lp = (ListPeer)getPeer(); + if (lp != null) + lp.deselect(index); +} + +/*************************************************************************/ + +/** + * Notifies this object to create its native peer. + */ +public void +addNotify() +{ + if (peer == null) + peer = getToolkit ().createList (this); + super.addNotify (); +} + +/*************************************************************************/ + +/** + * Notifies this object to destroy its native peer. + */ +public void +removeNotify() +{ + super.removeNotify(); +} + +/*************************************************************************/ + +/** + * Adds the specified <code>ActionListener</code> to the list of + * registered listeners for this object. + * + * @param listener The listener to add. + */ +public synchronized void +addActionListener(ActionListener listener) +{ + action_listeners = AWTEventMulticaster.add(action_listeners, listener); +} + +/*************************************************************************/ + +/** + * Removes the specified <code>ActionListener</code> from the list of + * registers listeners for this object. + * + * @param listener The listener to remove. + */ +public synchronized void +removeActionListener(ActionListener listener) +{ + action_listeners = AWTEventMulticaster.remove(action_listeners, listener); +} + +/*************************************************************************/ + +/** + * Adds the specified <code>ItemListener</code> to the list of + * registered listeners for this object. + * + * @param listener The listener to add. + */ +public synchronized void +addItemListener(ItemListener listener) +{ + item_listeners = AWTEventMulticaster.add(item_listeners, listener); +} + +/*************************************************************************/ + +/** + * Removes the specified <code>ItemListener</code> from the list of + * registers listeners for this object. + * + * @param listener The listener to remove. + */ +public synchronized void +removeItemListener(ItemListener listener) +{ + item_listeners = AWTEventMulticaster.remove(item_listeners, listener); +} + +/*************************************************************************/ + +/** + * Processes the specified event for this object. If the event is an + * instance of <code>ActionEvent</code> then the + * <code>processActionEvent()</code> method is called. Similarly, if the + * even is an instance of <code>ItemEvent</code> then the + * <code>processItemEvent()</code> method is called. Otherwise the + * superclass method is called to process this event. + * + * @param event The event to process. + */ +protected void +processEvent(AWTEvent event) +{ + if (event instanceof ActionEvent) + processActionEvent((ActionEvent)event); + else if (event instanceof ItemEvent) + processItemEvent((ItemEvent)event); + else + super.processEvent(event); +} + +/*************************************************************************/ + +/** + * This method processes the specified event by dispatching it to any + * registered listeners. Note that this method will only get called if + * action events are enabled. This will happen automatically if any + * listeners are added, or it can be done "manually" by calling + * the <code>enableEvents()</code> method. + * + * @param event The event to process. + */ +protected void +processActionEvent(ActionEvent event) +{ + if (action_listeners != null) + action_listeners.actionPerformed(event); +} + +/*************************************************************************/ + +/** + * This method processes the specified event by dispatching it to any + * registered listeners. Note that this method will only get called if + * item events are enabled. This will happen automatically if any + * listeners are added, or it can be done "manually" by calling + * the <code>enableEvents()</code> method. + * + * @param event The event to process. + */ +protected void +processItemEvent(ItemEvent event) +{ + if (item_listeners != null) + item_listeners.itemStateChanged(event); +} + +void +dispatchEventImpl(AWTEvent e) +{ + if (e.id <= ItemEvent.ITEM_LAST + && e.id >= ItemEvent.ITEM_FIRST + && (item_listeners != null + || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0)) + processEvent(e); + else if (e.id <= ActionEvent.ACTION_LAST + && e.id >= ActionEvent.ACTION_FIRST + && (action_listeners != null + || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0)) + processEvent(e); + else + super.dispatchEventImpl(e); +} + +/*************************************************************************/ + +/** + * Returns a debugging string for this object. + * + * @return A debugging string for this object. + */ +protected String +paramString() +{ + return "multiple=" + multipleMode + ",rows=" + rows + super.paramString(); +} + + /** + * Returns an array of all the objects currently registered as FooListeners + * upon this <code>List</code>. FooListeners are registered using the + * addFooListener method. + * + * @exception ClassCastException If listenerType doesn't specify a class or + * interface that implements java.util.EventListener. + */ + public EventListener[] getListeners (Class listenerType) + { + if (listenerType == ActionListener.class) + return AWTEventMulticaster.getListeners (action_listeners, listenerType); + + if (listenerType == ItemListener.class) + return AWTEventMulticaster.getListeners (item_listeners, listenerType); + + return super.getListeners (listenerType); + } + + /** + * Returns all action listeners registered to this object. + */ + public ActionListener[] getActionListeners () + { + return (ActionListener[]) getListeners (ActionListener.class); + } + + /** + * Returns all action listeners registered to this object. + */ + public ItemListener[] getItemListeners () + { + return (ItemListener[]) getListeners (ItemListener.class); + } + + // Accessibility internal class + protected class AccessibleAWTList extends AccessibleAWTComponent + implements AccessibleSelection, ItemListener, ActionListener + { + protected class AccessibleAWTListChild extends AccessibleAWTComponent + implements Accessible + { + private int index; + private List parent; + + public AccessibleAWTListChild(List parent, int indexInParent) + { + this.parent = parent; + index = indexInParent; + if (parent == null) + index = -1; + } + + /* (non-Javadoc) + * @see javax.accessibility.Accessible#getAccessibleContext() + */ + public AccessibleContext getAccessibleContext() + { + return this; + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.LIST_ITEM; + } + + public AccessibleStateSet getAccessibleStateSet() + { + AccessibleStateSet states = super.getAccessibleStateSet(); + if (parent.isIndexSelected(index)) + states.add(AccessibleState.SELECTED); + return states; + } + + public int getAccessibleIndexInParent() + { + return index; + } + + } + + public AccessibleAWTList() + { + addItemListener(this); + addActionListener(this); + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.LIST; + } + + public AccessibleStateSet getAccessibleStateSet() + { + AccessibleStateSet states = super.getAccessibleStateSet(); + states.add(AccessibleState.SELECTABLE); + if (isMultipleMode()) + states.add(AccessibleState.MULTISELECTABLE); + return states; + } + + public int getAccessibleChildrenCount() + { + return getItemCount(); + } + + public Accessible getAccessibleChild(int i) + { + if (i >= getItemCount()) + return null; + return new AccessibleAWTListChild(List.this, i); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleSelection#getAccessibleSelectionCount() + */ + public int getAccessibleSelectionCount() + { + return getSelectedIndexes().length; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleSelection#getAccessibleSelection() + */ + public AccessibleSelection getAccessibleSelection() + { + return this; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleSelection#getAccessibleSelection(int) + */ + public Accessible getAccessibleSelection(int i) + { + int[] items = getSelectedIndexes(); + if (i >= items.length) + return null; + return new AccessibleAWTListChild(List.this, items[i]); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleSelection#isAccessibleChildSelected(int) + */ + public boolean isAccessibleChildSelected(int i) + { + return isIndexSelected(i); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleSelection#addAccessibleSelection(int) + */ + public void addAccessibleSelection(int i) + { + select(i); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleSelection#removeAccessibleSelection(int) + */ + public void removeAccessibleSelection(int i) + { + deselect(i); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleSelection#clearAccessibleSelection() + */ + public void clearAccessibleSelection() + { + for (int i = 0; i < getItemCount(); i++) + deselect(i); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleSelection#selectAllAccessibleSelection() + */ + public void selectAllAccessibleSelection() + { + if (isMultipleMode()) + for (int i = 0; i < getItemCount(); i++) + select(i); + } + + /* (non-Javadoc) + * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent) + */ + public void itemStateChanged(ItemEvent event) + { + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ + public void actionPerformed(ActionEvent event) + { + } + + } + + /** + * Gets the AccessibleContext associated with this <code>List</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTList(); + return accessibleContext; + } +} // class List diff --git a/libjava/classpath/java/awt/MediaTracker.java b/libjava/classpath/java/awt/MediaTracker.java new file mode 100644 index 0000000..9abfde6 --- /dev/null +++ b/libjava/classpath/java/awt/MediaTracker.java @@ -0,0 +1,697 @@ +/* MediaTracker.java -- Class used for keeping track of images + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.image.ImageObserver; +import java.util.ArrayList; + +/** + * This class is used for keeping track of the status of various media + * objects. + * + * Media objects are tracked by assigning them an ID. It is possible + * to assign the same ID to mutliple objects, effectivly grouping them + * together. In this case the status flags ({@link #statusID}) and error flag + * (@link #isErrorID} and {@link #getErrorsID}) are ORed together. This + * means that you cannot say exactly which media object has which status, + * at most you can say that there <em>are</em> certain media objects with + * some certain status. + * + * At the moment only images are supported by this class. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Bryce McKinlay + */ +public class MediaTracker implements java.io.Serializable +{ + /** Indicates that the media is still loading. */ + public static final int LOADING = 1 << 0; + + /** Indicates that the loading operation has been aborted. */ + public static final int ABORTED = 1 << 1; + + /** Indicates that an error has occured during loading of the media. */ + public static final int ERRORED = 1 << 2; + + /** Indicates that the media has been successfully and completely loaded. */ + public static final int COMPLETE = 1 << 3; + + /** The component on which the media is eventually been drawn. */ + Component target; + + /** The head of the linked list of tracked media objects. */ + MediaEntry head; + + /** Our serialVersionUID for serialization. */ + static final long serialVersionUID = -483174189758638095L; + + /** + * This represents a media object that is tracked by a MediaTracker. + * It also implements a simple linked list. + */ + // FIXME: The serialized form documentation says MediaEntry is a + // serializable field, but the serialized form of MediaEntry itself + // doesn't appear to be documented. + class MediaEntry implements ImageObserver + { + /** The ID of the media object. */ + int id; + + /** The media object. (only images are supported ATM). */ + Image image; + + /** The link to the next entry in the list. */ + MediaEntry next; + + /** The tracking status. */ + int status; + + /** The width of the image. */ + int width; + + /** The height of the image. */ + int height; + + /** + * Receives notification from an {@link java.awt.image.ImageProducer} + * that more data of the image is available. + * + * @param img the image that is updated + * @param flags flags from the ImageProducer that indicate the status + * of the loading process + * @param x the X coordinate of the upper left corner of the image + * @param y the Y coordinate of the upper left corner of the image + * @param width the width of the image + * @param height the height of the image + * + * @return <code>true</code> if more data is needed, <code>false</code> + * otherwise + * + * @see java.awt.image.ImageObserver + */ + public boolean imageUpdate(Image img, int flags, int x, int y, + int width, int height) + { + if ((flags & ABORT) != 0) + status = ABORTED; + else if ((flags & ERROR) != 0) + status = ERRORED; + else if ((flags & ALLBITS) != 0) + status = COMPLETE; + else + status = 0; + + synchronized (MediaTracker.this) + { + MediaTracker.this.notifyAll(); + } + + // If status is not COMPLETE then we need more updates. + return ((status & (COMPLETE | ERRORED | ABORTED)) == 0); + } + } + + /** + * Constructs a new MediaTracker for the component <code>c</code>. The + * component should be the component that uses the media (i.e. draws it). + * + * @param c the Component that wants to use the media + */ + public MediaTracker(Component c) + { + target = c; + } + + /** + * Adds an image to the tracker with the specified <code>ID</code>. + * + * @param image the image to be added + * @param id the ID of the tracker list to which the image is added + */ + public void addImage(Image image, int id) + { + MediaEntry e = new MediaEntry(); + e.id = id; + e.image = image; + synchronized(this) + { + e.next = head; + head = e; + } + } + + /** + * Adds an image to the tracker with the specified <code>ID</code>. + * The image is expected to be rendered with the specified width and + * height. + * + * @param image the image to be added + * @param id the ID of the tracker list to which the image is added + * @param width the width of the image + * @param height the height of the image + */ + public void addImage(Image image, int id, int width, int height) + { + MediaEntry e = new MediaEntry(); + e.id = id; + e.image = image; + e.width = width; + e.height = height; + synchronized(this) + { + e.next = head; + head = e; + } + } + + /** + * Checks if all media objects have finished loading, i.e. are + * {@link #COMPLETE}, {@link #ABORTED} or {@link #ERRORED}. + * + * If the media objects are not already loading, a call to this + * method does <em>not</em> start loading. This is equivalent to + * a call to <code>checkAll(false)</code>. + * + * @return if all media objects have finished loading either by beeing + * complete, have been aborted or errored. + */ + public boolean checkAll() + { + return checkAll(false); + } + + /** + * Checks if all media objects have finished loading, i.e. are + * {@link #COMPLETE}, {@link #ABORTED} or {@link #ERRORED}. + * + * If the media objects are not already loading, and <code>load</code> + * is <code>true</code> then a call to this + * method starts loading the media objects. + * + * @param load if <code>true</code> this method starts loading objects + * that are not already loading + * + * @return if all media objects have finished loading either by beeing + * complete, have been aborted or errored. + */ + public boolean checkAll(boolean load) + { + MediaEntry e = head; + boolean result = true; + + while (e != null) + { + if ((e.status & (COMPLETE | ERRORED | ABORTED)) == 0) + { + if (load && ((e.status & LOADING) == 0)) + { + if (target.prepareImage(e.image, e)) + e.status = COMPLETE; + else + { + e.status = LOADING; + int flags = target.checkImage(e.image, e); + if ((flags & ImageObserver.ABORT) != 0) + e.status = ABORTED; + else if ((flags & ImageObserver.ERROR) != 0) + e.status = ERRORED; + else if ((flags & ImageObserver.ALLBITS) != 0) + e.status = COMPLETE; + } + boolean complete = (e.status + & (COMPLETE | ABORTED | ERRORED)) != 0; + if (!complete) + result = false; + } + else + result = false; + } + e = e.next; + } + return result; + } + + /** + * Checks if any of the registered media objects has encountered an error + * during loading. + * + * @return <code>true</code> if at least one media object has encountered + * an error during loading, <code>false</code> otherwise + * + */ + public boolean isErrorAny() + { + MediaEntry e = head; + while (e != null) + { + if ((e.status & ERRORED) != 0) + return true; + e = e.next; + } + return false; + } + + /** + * Returns all media objects that have encountered errors during loading. + * + * @return an array of all media objects that have encountered errors + * or <code>null</code> if there were no errors at all + */ + public Object[] getErrorsAny() + { + MediaEntry e = head; + ArrayList result = null; + while (e != null) + { + if ((e.status & ERRORED) != 0) + { + if (result == null) + result = new ArrayList(); + result.add(e.image); + } + e = e.next; + } + if (result == null) + return null; + else + return result.toArray(); + } + + /** + * Waits for all media objects to finish loading, either by completing + * successfully or by aborting or encountering an error. + * + * @throws InterruptedException if another thread interrupted the + * current thread while waiting + */ + public void waitForAll() throws InterruptedException + { + synchronized (this) + { + while (checkAll(true) == false) + wait(); + } + } + + /** + * Waits for all media objects to finish loading, either by completing + * successfully or by aborting or encountering an error. + * + * This method waits at most <code>ms</code> milliseconds. If the + * media objects have not completed loading within this timeframe, this + * method returns <code>false</code>, otherwise <code>true</code>. + * + * @param ms timeframe in milliseconds to wait for the media objects to + * finish + * + * @return <code>true</code> if all media objects have successfully loaded + * within the timeframe, <code>false</code> otherwise + * + * @throws InterruptedException if another thread interrupted the + * current thread while waiting + */ + public boolean waitForAll(long ms) throws InterruptedException + { + long start = System.currentTimeMillis(); + boolean result = checkAll(true); + synchronized (this) + { + while (result == false) + { + wait(ms); + result = checkAll(true); + if ((System.currentTimeMillis() - start) > ms) + break; + } + } + + return result; + } + + /** + * Returns the status flags of all registered media objects ORed together. + * If <code>load</code> is <code>true</code> then media objects that + * are not already loading will be started to load. + * + * @param load if set to <code>true</code> then media objects that are + * not already loading are started + * + * @return the status flags of all tracked media objects ORed together + */ + public int statusAll(boolean load) + { + int result = 0; + MediaEntry e = head; + while (e != null) + { + if (load && e.status == 0) + { + if (target.prepareImage(e.image, e)) + e.status = COMPLETE; + else + { + e.status = LOADING; + int flags = target.checkImage(e.image, e); + if ((flags & ImageObserver.ABORT) != 0) + e.status = ABORTED; + else if ((flags & ImageObserver.ERROR) != 0) + e.status = ERRORED; + else if ((flags & ImageObserver.ALLBITS) != 0) + e.status = COMPLETE; + } + } + result |= e.status; + e = e.next; + } + return result; + } + + /** + * Checks if the media objects with <code>ID</code> have completed loading. + * + * @param id the ID of the media objects to check + * + * @return <code>true</code> if all media objects with <code>ID</code> + * have successfully finished + */ + public boolean checkID(int id) + { + return checkID(id, false); + } + + /** + * Checks if the media objects with <code>ID</code> have completed loading. + * If <code>load</code> is <code>true</code> then media objects that + * are not already loading will be started to load. + * + * @param id the ID of the media objects to check + * @param load if set to <code>true</code> then media objects that are + * not already loading are started + * + * @return <code>true</code> if all media objects with <code>ID</code> + * have successfully finished + */ + public boolean checkID(int id, boolean load) + { + MediaEntry e = head; + boolean result = true; + + while (e != null) + { + if (e.id == id && ((e.status & (COMPLETE | ABORTED | ERRORED)) == 0)) + { + if (load && ((e.status & LOADING) == 0)) + { + e.status = LOADING; + if (target.prepareImage(e.image, e)) + e.status = COMPLETE; + else + { + int flags = target.checkImage(e.image, e); + if ((flags & ImageObserver.ABORT) != 0) + e.status = ABORTED; + else if ((flags & ImageObserver.ERROR) != 0) + e.status = ERRORED; + else if ((flags & ImageObserver.ALLBITS) != 0) + e.status = COMPLETE; + } + boolean complete = (e.status + & (COMPLETE | ABORTED | ERRORED)) != 0; + if (!complete) + result = false; + } + else + result = false; + } + e = e.next; + } + return result; + } + + /** + * Returns <code>true</code> if any of the media objects with <code>ID</code> + * have encountered errors during loading, false otherwise. + * + * @param id the ID of the media objects to check + * + * @return <code>true</code> if any of the media objects with <code>ID</code> + * have encountered errors during loading, false otherwise + */ + public boolean isErrorID(int id) + { + MediaEntry e = head; + while (e != null) + { + if (e.id == id && ((e.status & ERRORED) != 0)) + return true; + e = e.next; + } + return false; + } + + /** + * Returns all media objects with the specified ID that have encountered + * an error. + * + * @param id the ID of the media objects to check + * + * @return an array of all media objects with the specified ID that + * have encountered an error + */ + public Object[] getErrorsID(int id) + { + MediaEntry e = head; + ArrayList result = null; + while (e != null) + { + if (e.id == id && ((e.status & ERRORED) != 0)) + { + if (result == null) + result = new ArrayList(); + result.add(e.image); + } + e = e.next; + } + if (result == null) + return null; + else + return result.toArray(); + } + + /** + * Waits for all media objects with the specified ID to finish loading, + * either by completing successfully or by aborting or encountering an error. + * + * @param id the ID of the media objects to wait for + * + * @throws InterruptedException if another thread interrupted the + * current thread while waiting + */ + public void waitForID(int id) throws InterruptedException + { + MediaEntry e = head; + synchronized (this) + { + while (checkID (id, true) == false) + wait(); + } + } + + /** + * Waits for all media objects with the specified ID to finish loading, + * either by completing successfully or by aborting or encountering an error. + * + * This method waits at most <code>ms</code> milliseconds. If the + * media objects have not completed loading within this timeframe, this + * method returns <code>false</code>, otherwise <code>true</code>. + * + * @param id the ID of the media objects to wait for + * @param ms timeframe in milliseconds to wait for the media objects to + * finish + * + * @return <code>true</code> if all media objects have successfully loaded + * within the timeframe, <code>false</code> otherwise + * + * @throws InterruptedException if another thread interrupted the + * current thread while waiting + */ + public boolean waitForID(int id, long ms) throws InterruptedException + { + MediaEntry e = head; + long start = System.currentTimeMillis(); + boolean result = checkID(id, true); + + synchronized (this) + { + while (result == false) + { + wait(ms); + result = checkID(id, true); + if ((System.currentTimeMillis() - start) > ms) + break; + } + } + + return result; + } + + /** + * Returns the status flags of the media objects with the specified ID + * ORed together. + * + * If <code>load</code> is <code>true</code> then media objects that + * are not already loading will be started to load. + * + * @param load if set to <code>true</code> then media objects that are + * not already loading are started + * + * @return the status flags of all tracked media objects ORed together + */ + public int statusID(int id, boolean load) + { + int result = 0; + MediaEntry e = head; + while (e != null) + { + if (e.id == id) + { + if (load && e.status == 0) + { + if (target.prepareImage(e.image, e)) + e.status = COMPLETE; + else + { + e.status = LOADING; + int flags = target.checkImage(e.image, e); + if ((flags & ImageObserver.ABORT) != 0) + e.status = ABORTED; + else if ((flags & ImageObserver.ERROR) != 0) + e.status = ERRORED; + else if ((flags & ImageObserver.ALLBITS) != 0) + e.status = COMPLETE; + } + } + result |= e.status; + } + e = e.next; + } + return result; + } + + /** + * Removes an image from this MediaTracker. + * + * @param image the image to be removed + */ + public void removeImage(Image image) + { + synchronized (this) + { + MediaEntry e = head; + MediaEntry prev = null; + while (e != null) + { + if (e.image == image) + { + if (prev == null) + head = e.next; + else + prev.next = e.next; + } + prev = e; + e = e.next; + } + } + } + + /** + * Removes an image with the specified ID from this MediaTracker. + * + * @param image the image to be removed + */ + public void removeImage(Image image, int id) + { + synchronized (this) + { + MediaEntry e = head; + MediaEntry prev = null; + while (e != null) + { + if (e.id == id && e.image == image) + { + if (prev == null) + head = e.next; + else + prev.next = e.next; + } + else + prev = e; + e = e.next; + } + } + } + + /** + * Removes an image with the specified ID and scale from this MediaTracker. + * + * @param image the image to be removed + */ + public void removeImage(Image image, int id, int width, int height) + { + synchronized (this) + { + MediaEntry e = head; + MediaEntry prev = null; + while (e != null) + { + if (e.id == id && e.image == image + && e.width == width && e.height == height) + { + if (prev == null) + head = e.next; + else + prev.next = e.next; + } + else + prev = e; + e = e.next; + } + } + } +} diff --git a/libjava/classpath/java/awt/Menu.java b/libjava/classpath/java/awt/Menu.java new file mode 100644 index 0000000..56ceccf --- /dev/null +++ b/libjava/classpath/java/awt/Menu.java @@ -0,0 +1,468 @@ +/* Menu.java -- A Java AWT Menu + Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.peer.MenuPeer; +import java.io.Serializable; +import java.util.Enumeration; +import java.util.Vector; + +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * This class represents a pull down or tear off menu in Java's AWT. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class Menu extends MenuItem implements MenuContainer, Serializable +{ + +/* + * Static Variables + */ + +// Serialization Constant +private static final long serialVersionUID = -8809584163345499784L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial The actual items in the menu + */ +private Vector items = new Vector(); + +/** + * @serial Flag indicating whether or not this menu is a tear off + */ +private boolean tearOff; + +/** + * @serial Indicates whether or not this is a help menu. + */ +private boolean isHelpMenu; + + /* + * @serial Unused in this implementation, but present in Sun's + * serialization spec. Value obtained via reflection. + */ + private int menuSerializedDataVersion = 1; + +static final transient String separatorLabel = "-"; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>Menu</code> with no label and that + * is not a tearoff; + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +Menu() +{ +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Menu</code> that is not a tearoff and + * that has the specified label. + * + * @param label The menu label. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +Menu(String label) +{ + this(label, false); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>Menu</code> with the specified + * label and tearoff status. + * + * @param label The label for this menu + * @param isTearOff <code>true</code> if this menu is a tear off menu, + * <code>false</code> otherwise. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +Menu(String label, boolean isTearOff) +{ + super(label); + + tearOff = isTearOff; + + if (label.equals("Help")) + isHelpMenu = true; + + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException (); +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Tests whether or not this menu is a tearoff. + * + * @return <code>true</code> if this menu is a tearoff, <code>false</code> + * otherwise. + */ +public boolean +isTearOff() +{ + return(tearOff); +} + +/*************************************************************************/ + +/** + * Returns the number of items in this menu. + * + * @return The number of items in this menu. + */ +public int +getItemCount() +{ + return countItems (); +} + +/** + * Returns the number of items in this menu. + * + * @return The number of items in this menu. + * + * @deprecated As of JDK 1.1, replaced by getItemCount(). + */ +public int countItems () +{ + return items.size (); +} + +/*************************************************************************/ + +/** + * Returns the item at the specified index. + * + * @return The item at the specified index. + * + * @exception ArrayIndexOutOfBoundsException If the index value is not valid. + */ +public MenuItem +getItem(int index) +{ + return((MenuItem)items.elementAt(index)); +} + +/*************************************************************************/ + +/** + * Adds the specified item to this menu. If it was previously part of + * another menu, it is first removed from that menu. + * + * @param item The new item to add. + * + * @return The item that was added. + */ +public MenuItem +add(MenuItem item) +{ + items.addElement(item); + if (item.parent != null) + { + item.parent.remove(item); + } + item.parent = this; + + if (peer != null) + { + MenuPeer mp = (MenuPeer) peer; + mp.addItem(item); + } + + return item; +} + +/*************************************************************************/ + +/** + * Add an item with the specified label to this menu. + * + * @param label The label of the menu item to add. + */ +public void +add(String label) +{ + add(new MenuItem(label)); +} + +/*************************************************************************/ + +/** + * Inserts the specified menu item into this menu at the specified index. + * + * @param item The menu item to add. + * @param index The index of the menu item. + * + * @exception IllegalArgumentException If the index is less than zero. + * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid. + */ +public void +insert(MenuItem item, int index) +{ + if (index < 0) + throw new IllegalArgumentException("Index is less than zero"); + + MenuPeer peer = (MenuPeer) getPeer(); + if (peer == null) + return; + + int count = getItemCount (); + + if (index >= count) + peer.addItem (item); + else + { + for (int i = count - 1; i >= index; i--) + peer.delItem (i); + + peer.addItem (item); + + for (int i = index; i < count; i++) + peer.addItem ((MenuItem) items.elementAt (i)); + } + + items.insertElementAt(item, index); +} + +/*************************************************************************/ + +/** + * Inserts an item with the specified label into this menu at the specified index. + * + * @param label The label of the item to add. + * @param index The index of the menu item. + * + * @exception IllegalArgumentException If the index is less than zero. + * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid. + */ +public void +insert(String label, int index) +{ + insert(new MenuItem(label), index); +} + +/*************************************************************************/ + +/** + * Adds a separator bar at the current menu location. + */ +public void +addSeparator() +{ + add(new MenuItem(separatorLabel)); +} + +/*************************************************************************/ + +/** + * Inserts a separator bar at the specified index value. + * + * @param index The index at which to insert a separator bar. + * + * @exception IllegalArgumentException If the index is less than zero. + * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid. + */ +public void +insertSeparator(int index) +{ + insert(new MenuItem(separatorLabel), index); +} + +/*************************************************************************/ + +/** + * Deletes the item at the specified index from this menu. + * + * @param index The index of the item to remove. + * + * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid. + */ +public synchronized void +remove(int index) +{ + items.removeElementAt(index); + + MenuPeer mp = (MenuPeer)getPeer(); + if (mp != null) + mp.delItem(index); +} + +/*************************************************************************/ + +/** + * Removes the specifed item from the menu. If the specified component + * does not exist, this method does nothing. + * + * @param item The component to remove. + */ +public void +remove(MenuComponent item) +{ + int index = items.indexOf(item); + if (index == -1) + return; + + remove(index); +} + +/*************************************************************************/ + +/** + * Removes all the elements from this menu. + */ +public synchronized void +removeAll() +{ + int count = getItemCount(); + for(int i = 0; i < count; i++) + { + // We must always remove item 0. + remove(0); + } +} + +/*************************************************************************/ + +/** + * Creates the native peer for this object. + */ +public void +addNotify() +{ + if (peer == null) + peer = getToolkit().createMenu(this); + Enumeration e = items.elements(); + while (e.hasMoreElements()) + { + MenuItem mi = (MenuItem)e.nextElement(); + mi.addNotify(); + } + super.addNotify (); +} + +/*************************************************************************/ + +/** + * Destroys the native peer for this object. + */ +public void +removeNotify() +{ + Enumeration e = items.elements(); + while (e.hasMoreElements()) + { + MenuItem mi = (MenuItem) e.nextElement(); + mi.removeNotify(); + } + super.removeNotify(); +} + +/*************************************************************************/ + +/** + * Returns a debugging string for this menu. + * + * @return A debugging string for this menu. + */ +public String +paramString() +{ + return (",tearOff=" + tearOff + ",isHelpMenu=" + isHelpMenu + + super.paramString()); +} + + /** + * Basic Accessibility class for Menu. Details get provided in derived + * classes. + */ + protected class AccessibleAWTMenu extends AccessibleAWTMenuItem + { + protected AccessibleAWTMenu() + { + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.MENU; + } + } + + /** + * Gets the AccessibleContext associated with this <code>Menu</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTMenu(); + return accessibleContext; + } + +} // class Menu diff --git a/libjava/classpath/java/awt/MenuBar.java b/libjava/classpath/java/awt/MenuBar.java new file mode 100644 index 0000000..4089fe1 --- /dev/null +++ b/libjava/classpath/java/awt/MenuBar.java @@ -0,0 +1,423 @@ +/* MenuBar.java -- An AWT menu bar class + Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.peer.MenuBarPeer; +import java.awt.peer.MenuComponentPeer; + +import java.io.Serializable; +import java.util.Enumeration; +import java.util.Vector; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * This class implements a menu bar in the AWT system. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Tom Tromey (tromey@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ +public class MenuBar extends MenuComponent + implements MenuContainer, Serializable, Accessible +{ + +/* + * Static Variables + */ + +// Serialization Constant +private static final long serialVersionUID = -4930327919388951260L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial The menu used for providing help information + */ +private Menu helpMenu; + +/** + * @serial The menus contained in this menu bar. + */ +private Vector menus = new Vector(); + + /** + * The accessible context for this component. + * + * @see #getAccessibleContext() + * @serial ignored. + */ + private transient AccessibleContext accessibleContext; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>MenuBar</code>. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +MenuBar() +{ + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException (); +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns the help menu for this menu bar. This may be <code>null</code>. + * + * @return The help menu for this menu bar. + */ +public Menu +getHelpMenu() +{ + return(helpMenu); +} + +/*************************************************************************/ + +/** + * Sets the help menu for this menu bar. + * + * @param menu The new help menu for this menu bar. + */ +public synchronized void +setHelpMenu(Menu menu) +{ + if (helpMenu != null) + { + helpMenu.removeNotify (); + helpMenu.parent = null; + } + helpMenu = menu; + + if (menu.parent != null) + menu.parent.remove (menu); + menu.parent = this; + + MenuBarPeer peer = (MenuBarPeer) getPeer (); + if (peer != null) + { + menu.addNotify(); + peer.addHelpMenu (menu); + } +} + +/*************************************************************************/ + +/** Add a menu to this MenuBar. If the menu has already has a + * parent, it is first removed from its old parent before being + * added. + * + * @param menu The menu to add. + * + * @return The menu that was added. + */ +public synchronized Menu +add(Menu menu) +{ + if (menu.parent != null) + menu.parent.remove (menu); + + menu.parent = this; + menus.addElement(menu); + + if (peer != null) + { + menu.addNotify(); + } + + return(menu); +} + +/*************************************************************************/ + +/** + * Removes the menu at the specified index. + * + * @param index The index of the menu to remove from the menu bar. + */ +public synchronized void +remove(int index) +{ + Menu m = (Menu) menus.get (index); + menus.remove (index); + m.removeNotify (); + m.parent = null; + + if (peer != null) + { + MenuBarPeer mp = (MenuBarPeer) peer; + mp.delMenu (index); + } +} + +/*************************************************************************/ + +/** + * Removes the specified menu from the menu bar. + * + * @param menu The menu to remove from the menu bar. + */ +public void +remove(MenuComponent menu) +{ + int index = menus.indexOf(menu); + if (index == -1) + return; + + remove(index); +} + +/*************************************************************************/ + +/** + * Returns the number of elements in this menu bar. + * + * @return The number of elements in the menu bar. + */ +public int +getMenuCount() +{ + return countMenus (); +} + +/*************************************************************************/ + +/** + * Returns the number of elements in this menu bar. + * + * @return The number of elements in the menu bar. + * + * @deprecated This method is deprecated in favor of <code>getMenuCount()</code>. + */ +public int +countMenus() +{ + return menus.size () + (getHelpMenu () == null ? 0 : 1); +} + +/*************************************************************************/ + +/** + * Returns the menu at the specified index. + * + * @param index the index of the menu + * + * @return The requested menu. + * + * @exception ArrayIndexOutOfBoundsException If the index is not valid. + */ +public Menu +getMenu(int index) +{ + return((Menu)menus.elementAt(index)); +} + +/*************************************************************************/ + +/** + * Creates this object's native peer. + */ +public void +addNotify() +{ + if (getPeer() == null) + setPeer((MenuComponentPeer)getToolkit().createMenuBar(this)); + Enumeration e = menus.elements(); + while (e.hasMoreElements()) + { + Menu mi = (Menu)e.nextElement(); + mi.addNotify(); + } + if (helpMenu != null) + { + helpMenu.addNotify(); + ((MenuBarPeer) peer).addHelpMenu(helpMenu); + } +} + +/*************************************************************************/ + +/** + * Destroys this object's native peer. + */ +public void +removeNotify() +{ + Enumeration e = menus.elements(); + while (e.hasMoreElements()) + { + Menu mi = (Menu) e.nextElement(); + mi.removeNotify(); + } + super.removeNotify(); +} + +/*************************************************************************/ + +/** + * Returns a list of all shortcuts for the menus in this menu bar. + * + * @return A list of all shortcuts for the menus in this menu bar. + */ +public synchronized Enumeration +shortcuts() +{ + Vector shortcuts = new Vector(); + Enumeration e = menus.elements(); + + while (e.hasMoreElements()) + { + Menu menu = (Menu)e.nextElement(); + if (menu.getShortcut() != null) + shortcuts.addElement(menu.getShortcut()); + } + + return(shortcuts.elements()); +} + +/*************************************************************************/ + +/** + * Returns the menu item for the specified shortcut, or <code>null</code> + * if no such item exists. + * + * @param shortcut The shortcut to return the menu item for. + * + * @return The menu item for the specified shortcut. + */ +public MenuItem +getShortcutMenuItem(MenuShortcut shortcut) +{ + Enumeration e = menus.elements(); + + while (e.hasMoreElements()) + { + Menu menu = (Menu)e.nextElement(); + MenuShortcut s = menu.getShortcut(); + if ((s != null) && (s.equals(shortcut))) + return(menu); + } + + return(null); +} + +/*************************************************************************/ + +/** + * Deletes the specified menu shortcut. + * + * @param shortcut The shortcut to delete. + */ +public void +deleteShortcut(MenuShortcut shortcut) +{ + MenuItem it; + // This is a slow implementation, but it probably doesn't matter. + while ((it = getShortcutMenuItem (shortcut)) != null) + it.deleteShortcut (); +} + +/** + * Gets the AccessibleContext associated with this <code>MenuBar</code>. + * The context is created, if necessary. + * + * @return the associated context + */ +public AccessibleContext getAccessibleContext() +{ + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTMenuBar(); + return accessibleContext; +} + +/** + * This class provides accessibility support for AWT menu bars. + * + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ +protected class AccessibleAWTMenuBar + extends AccessibleAWTMenuComponent +{ + + /** + * Compatible with JDK 1.4.2 revision 5 + */ + private static final long serialVersionUID = -8577604491830083815L; + + /** + * This is the default constructor, which simply calls the default + * constructor of the superclass. + */ + protected AccessibleAWTMenuBar() + { + super(); + } + + /** + * Returns the accessible role relating to the menu bar. + * + * @return <code>AccessibleRole.MENU_BAR</code>. + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.MENU_BAR; + } + +} // class AccessibleAWTMenuBar + +} // class MenuBar diff --git a/libjava/classpath/java/awt/MenuComponent.java b/libjava/classpath/java/awt/MenuComponent.java new file mode 100644 index 0000000..ec6980e1 --- /dev/null +++ b/libjava/classpath/java/awt/MenuComponent.java @@ -0,0 +1,1324 @@ +/* MenuComponent.java -- Superclass of all AWT menu components + Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.peer.MenuComponentPeer; +import java.io.Serializable; +import java.util.Locale; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleComponent; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleSelection; +import javax.accessibility.AccessibleStateSet; + +/** + * This is the superclass of all menu AWT widgets. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ +public abstract class MenuComponent implements Serializable +{ + +/* + * Static Variables + */ + +// Serialization Constant +private static final long serialVersionUID = -4536902356223894379L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * The font for this component. + * + * @see #getFont() + * @see #setFont(java.awt.Font) + * @serial the component's font. + */ + private Font font; + + /** + * The name of the component. + * + * @see #getName() + * @see #setName(String) + * @serial the component's name. + */ + private String name; + + /** + * The parent of this component. + * + * @see #getParent() + * @see #setParent(java.awt.MenuContainer) + * @serial ignored. + */ + transient MenuContainer parent; + + /** + * The native peer for this component. + * + * @see #getPeer() + * @see #setPeer(java.awt.peer.MenuComponentPeer) + * @serial ignored. + */ + transient MenuComponentPeer peer; + + /** + * The synchronization locking object for this component. + * + * @serial ignored. + */ + private transient Object tree_lock = this; + + /** + * The toolkit for this object. + * + * @see #getToolkit() + * @serial ignored. + */ + private static transient Toolkit toolkit = Toolkit.getDefaultToolkit(); + + /** + * The accessible context for this component. + * + * @see #getAccessibleContext() + * @serial the accessibility information for this component. + */ + AccessibleContext accessibleContext; + + /** + * Was the name of the component set? This value defaults + * to false and becomes true after a call to <code>setName()</code>. + * Please note that this does not guarantee that name will then + * be non-null, as this may be the value passed to <code>setName()</code>. + * + * @see #setName(String) + * @serial true if the name value has been explicitly set by calling + * <code>setName()</code>. + */ + private boolean nameExplicitlySet; + + /** + * Does this component handle new events? Events will be handled + * by this component if this is true. Otherwise, they will be forwarded + * up the component hierarchy. This implementation does not use this + * variable; it is merely provided for serialization compatability. + * + * @see #dispatchEvent(AWTEvent) + * @serial true if events are to be processed locally. Unused. + */ + private boolean newEventsOnly; + + /** + * The focus listener chain handler which deals with focus events for + * the accessible context of this component. + * + * @see AccessibleAWTMenuComponent#addFocusListener(java.awt.event.FocusListener) + * @serial ignored. + * This is package-private to avoid an accessor method. + */ + transient FocusListener focusListener; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Default constructor for subclasses. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +MenuComponent() +{ + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException (); +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns the font in use for this component. + * + * @return The font for this component. + */ +public Font +getFont() +{ + if (font != null) + return font; + + if (parent != null) + return parent.getFont (); + + return null; +} + +/*************************************************************************/ + +/** + * Sets the font for this component to the specified font. + * + * @param font The new font for this component. + */ +public void +setFont(Font font) +{ + this.font = font; +} + +/*************************************************************************/ + +/** + * Returns the name of this component. + * + * @return The name of this component. + */ +public String +getName() +{ + return(name); +} + +/*************************************************************************/ + +/** + * Sets the name of this component to the specified name. + * + * @param name The new name of this component. + */ +public void +setName(String name) +{ + this.name = name; + nameExplicitlySet = true; +} + +/*************************************************************************/ + +/** + * Returns the parent of this component. + * + * @return The parent of this component. + */ +public MenuContainer +getParent() +{ + return(parent); +} + +/*************************************************************************/ + +// Sets the parent of this component. +final void +setParent(MenuContainer parent) +{ + this.parent = parent; +} + +/*************************************************************************/ + +/** + * Returns the native windowing system peer for this component. + * + * @return The peer for this component. + * + * @deprecated + */ +public MenuComponentPeer +getPeer() +{ + return(peer); +} + +/*************************************************************************/ + +// Sets the peer for this component. +final void +setPeer(MenuComponentPeer peer) +{ + this.peer = peer; +} + +/*************************************************************************/ + +/** + * Destroys this component's native peer + */ +public void +removeNotify() +{ + if (peer != null) + peer.dispose(); + peer = null; +} + +/*************************************************************************/ + +/** + * Returns the toolkit in use for this component. + * + * @return The toolkit for this component. + */ +final Toolkit +getToolkit() +{ + return(toolkit); +} + +/*************************************************************************/ + +/** + * Returns the object used for synchronization locks on this component + * when performing tree and layout functions. + * + * @return The synchronization lock for this component. + */ +protected final Object +getTreeLock() +{ + return(tree_lock); +} + +/*************************************************************************/ + +// The sync lock object for this component. +final void +setTreeLock(Object tree_lock) +{ + this.tree_lock = tree_lock; +} + +/*************************************************************************/ + +/** + * AWT 1.0 event dispatcher. + * + * @deprecated Deprecated in favor of <code>dispatchEvent()</code>. + * @return true if the event was dispatched, false otherwise. + */ +public boolean +postEvent(Event event) +{ + // This is overridden by subclasses that support events. + return false; +} +/*************************************************************************/ + +/** + * Sends this event to this component or a subcomponent for processing. + * + * @param event The event to dispatch + */ +public final void dispatchEvent(AWTEvent event) +{ + // See comment in Component.dispatchEvent(). + dispatchEventImpl(event); +} + + +/** + * Implementation of dispatchEvent. Allows trusted package classes + * to dispatch additional events first. This implementation first + * translates <code>event</code> to an AWT 1.0 event and sends the + * result to {@link #postEvent}. The event is then + * passed on to {@link #processEvent} for local processing. + * + * @param event the event to dispatch. + */ +void dispatchEventImpl(AWTEvent event) +{ + Event oldStyleEvent; + + // This is overridden by subclasses that support events. + /* Convert AWT 1.1 event to AWT 1.0 event */ + oldStyleEvent = Component.translateEvent(event); + if (oldStyleEvent != null) + { + postEvent(oldStyleEvent); + } + /* Do local processing */ + processEvent(event); +} + +/*************************************************************************/ + +/** + * Processes the specified event. In this class, this method simply + * calls one of the more specific event handlers. + * + * @param event The event to process. + */ +protected void +processEvent(AWTEvent event) +{ + /* + Pass a focus event to the focus listener for + the accessibility context. + */ + if (event instanceof FocusEvent) + { + if (focusListener != null) + { + switch (event.id) + { + case FocusEvent.FOCUS_GAINED: + focusListener.focusGained((FocusEvent) event); + break; + case FocusEvent.FOCUS_LOST: + focusListener.focusLost((FocusEvent) event); + break; + } + } + } +} + +/*************************************************************************/ + +/** + * Returns a string representation of this component. + * + * @return A string representation of this component + */ +public String +toString() +{ + return this.getClass().getName() + "[" + paramString() + "]"; +} + +/*************************************************************************/ + +/** + * Returns a debugging string for this component + */ +protected String +paramString() +{ + return "name=" + getName(); +} + +/** + * Gets the AccessibleContext associated with this <code>MenuComponent</code>. + * As an abstract class, we return null. Concrete subclasses should return + * their implementation of the accessibility context. + * + * @return null. + */ + +public AccessibleContext getAccessibleContext() +{ + return null; +} + +/** + * This class provides a base for the accessibility support of menu + * components. + * + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ +protected abstract class AccessibleAWTMenuComponent + extends AccessibleContext + implements Serializable, AccessibleComponent, AccessibleSelection +{ + + /** + * Compatible with JDK 1.4.2 revision 5 + */ + private static final long serialVersionUID = -4269533416223798698L; + + /** + * This is the default constructor. It should be called by + * concrete subclasses to ensure necessary groundwork is completed. + */ + protected AccessibleAWTMenuComponent() + { + } + + /** + * Replaces or supplements the component's selection with the + * <code>Accessible</code> child at the supplied index. If + * the component supports multiple selection, the child is + * added to the current selection. Otherwise, the current + * selection becomes the specified child. If the child is + * already selected, nothing happens. + * <br /> + * <br /> + * As the existence of children can not be determined from + * this abstract class, the implementation of this method + * is left to subclasses. + * + * @param index the index of the specified child within a + * zero-based list of the component's children. + */ + public void addAccessibleSelection(int index) + { + /* Subclasses with children should implement this */ + } + + /** + * Registers the specified focus listener to receive + * focus events from this component. + * + * @param listener the new focus listener. + */ + public void addFocusListener(FocusListener listener) + { + /* + * Chain the new focus listener to the existing chain + * of focus listeners. Each new focus listener is + * coupled via multicasting to the existing chain. + */ + focusListener = AWTEventMulticaster.add(focusListener, listener); + } + + /** + * Clears the component's current selection. Following + * the calling of this method, no children of the component + * will be selected. + * <br /> + * <br /> + * As the existence of children can not be determined from + * this abstract class, the implementation of this method + * is left to subclasses. + */ + public void clearAccessibleSelection() + { + } + + /** + * Returns true if the specified point lies within the + * component. The supplied co-ordinates are assumed to + * be relative to the co-ordinate system of the component + * itself. Thus, the point (0,0) is the upper left corner + * of this component. + * <br /> + * <br /> + * Please note that this method depends on a correctly implemented + * version of the <code>getBounds()</code> method. Subclasses + * must provide the bounding rectangle via <code>getBounds()</code> + * in order for this method to work. + * + * @param point the point to check against this component. + * @return true if the point is within this component. + * @see #getBounds() + */ + public boolean contains(Point point) + { + /* + We can simply return the result of a + test for containment in the bounding rectangle + */ + return getBounds().contains(point); + } + + /** + * Returns the <code>Accessible</code> child of this component present + * at the specified point. The supplied co-ordinates are + * assumed to be relative to the co-ordinate system of this + * component (the parent of any returned accessible). Thus, + * the point (0,0) is the upper left corner of this menu + * component. + * <br /> + * <br /> + * As the existence of children can not be determined from + * this abstract class, the implementation of this method + * is left to subclasses. + * + * @param point the point at which the returned accessible + * is located. + * @return null. + */ + public Accessible getAccessibleAt(Point point) + { + return null; + } + + /** + * Returns the <code>Accessible</code> child at the supplied + * index within the list of children of this component. + * <br /> + * <br /> + * As the existence of children can not be determined from + * this abstract class, the implementation of this method + * is left to subclasses. + * + * @param index the index of the <code>Accessible</code> child + * to retrieve. + * @return null. + */ + public Accessible getAccessibleChild(int index) + { + return null; + } + + /** + * Returns the number of children of this component which + * implement the <code>Accessible</code> interface. If + * all children of this component are accessible, then + * the returned value will be the same as the number of + * children. + * <br /> + * <br /> + * + * @return 0. + */ + public int getAccessibleChildrenCount() + { + return 0; + } + + /** + * Retrieves the <code>AccessibleComponent</code> associated + * with this accessible context and its component. As the + * context itself implements <code>AccessibleComponent</code>, + * this is the return value. + * + * @return the context itself. + */ + public AccessibleComponent getAccessibleComponent() + { + return this; + } + + /** + * Returns the accessible name for this menu component. This + * is the name given to the component, which may be null if + * not set using <code>setName()</code>. + * <br /> + * <br /> + * The name is not the most appropriate description of this + * object. Subclasses should preferably provide a more + * accurate description. For example, a File menu could + * have the description `Lists commands related to the + * file system'. + * + * @return a description of the component. Currently, + * this is just the contents of the name property. + * @see MenuComponent#setName(String) + */ + public String getAccessibleDescription() + { + return MenuComponent.this.getName(); + } + + /** + * Retrieves the index of this component within its parent. + * If no parent exists, -1 is returned. + * + * @return -1 as the parent, a <code>MenuContainer</code> + * is not <code>Accessible</code>. + */ + public int getAccessibleIndexInParent() + { + return -1; + } + + /** + * Returns the accessible name of this component. This + * is the name given to the component, which may be null if + * not set using <code>setName()</code>. + * <br /> + * <br /> + * The name property is not the most suitable string to return + * for this method. The string should be localized, and + * relevant to the operation of the component. For example, + * it could be the text of a menu item. However, this can + * not be used at this level of abstraction, so it is the + * responsibility of subclasses to provide a more appropriate + * name. + * + * @return a localized name for this component. Currently, this + * is just the contents of the name property. + * @see MenuComponent#setName(String) + */ + public String getAccessibleName() + { + return MenuComponent.this.getName(); + } + + /** + * Returns the <code>Accessible</code> parent of this component. + * As the parent of a <code>MenuComponent</code> is a + * <code>MenuContainer</code>, which doesn't implement + * <code>Accessible</code>, this method returns null. + * + * @return null. + */ + public Accessible getAccessibleParent() + { + return null; + } + + /** + * Returns the accessible role of this component. + * <br /> + * <br /> + * The abstract implementation of this method returns + * <code>AccessibleRole.AWT_COMPONENT</code>, + * as the abstract component has no specific role. This + * method should be overridden by concrete subclasses, so + * as to return an appropriate role for the component. + * + * @return <code>AccessibleRole.AWT_COMPONENT</code>. + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.AWT_COMPONENT; + } + + /** + * Retrieves the <code>AccessibleSelection</code> associated + * with this accessible context and its component. As the + * context itself implements <code>AccessibleSelection</code>, + * this is the return value. + * + * @return the context itself. + */ + public AccessibleSelection getAccessibleSelection() + { + return this; + } + + /** + * Retrieves the <code>Accessible</code> selected child + * at the specified index. If there are no selected children + * or the index is outside the range of selected children, + * null is returned. Please note that the index refers + * to the index of the child in the list of <strong>selected + * children</strong>, and not the index of the child in + * the list of all <code>Accessible</code> children. + * <br /> + * <br /> + * As the existence of children can not be determined from + * this abstract class, the implementation of this method + * is left to subclasses. + * + * @param index the index of the selected <code>Accessible</code> + * child. + */ + public Accessible getAccessibleSelection(int index) + { + return null; + } + + /** + * Returns a count of the number of <code>Accessible</code> + * children of this component which are currently selected. + * If there are no children currently selected, 0 is returned. + * <br /> + * <br /> + * As the existence of children can not be determined from + * this abstract class, the implementation of this method + * is left to subclasses. + * + * @return 0. + */ + public int getAccessibleSelectionCount() + { + return 0; + } + + /** + * Retrieves the current state of this component + * in an accessible form. For example, a given component + * may be visible, selected, disabled, etc. + * <br /> + * <br /> + * As this class tells us virtually nothing about the component, + * except for its name and font, no state information can be + * provided. This implementation thus returns an empty + * state set, and it is left to concrete subclasses to provide + * a more acceptable and relevant state set. Changes to these + * properties also need to be handled using + * <code>PropertyChangeListener</code>s. + * + * @return an empty <code>AccessibleStateSet</code>. + */ + public AccessibleStateSet getAccessibleStateSet() + { + return new AccessibleStateSet(); + } + + /** + * Returns the background color of the component, or null + * if this property is unsupported. + * <br /> + * <br /> + * This abstract class knows nothing about how the component + * is drawn on screen, so this method simply returns the + * default system background color used for rendering menus. + * Concrete subclasses which handle the drawing of an onscreen + * menu component should override this method and provide + * the appropriate information. + * + * @return the default system background color for menus. + * @see #setBackground(java.awt.Color) + */ + public Color getBackground() + { + return SystemColor.menu; + } + + /** + * Returns a <code>Rectangle</code> which represents the + * bounds of this component. The returned rectangle has the + * height and width of the component's bounds, and is positioned + * at a location relative to this component's parent, the + * <code>MenuContainer</code>. null is returned if bounds + * are not supported by the component. + * <br /> + * <br /> + * This abstract class knows nothing about how the component + * is drawn on screen, so this method simply returns null. + * Concrete subclasses which handle the drawing of an onscreen + * menu component should override this method and provide + * the appropriate information. + * + * @return null. + * @see #setBounds(java.awt.Rectangle) + */ + public Rectangle getBounds() + { + return null; + } + + /** + * Returns the <code>Cursor</code> displayed when the pointer + * is positioned over this component. Alternatively, null + * is returned if the component doesn't support the cursor + * property. + * <br /> + * <br /> + * This abstract class knows nothing about how the component + * is drawn on screen, so this method simply returns the default + * system cursor. Concrete subclasses which handle the drawing + * of an onscreen menu component may override this method and provide + * the appropriate information. + * + * @return the default system cursor. + * @see #setCursor(java.awt.Cursor) + */ + public Cursor getCursor() + { + return Cursor.getDefaultCursor(); + } + + /** + * Returns the <code>Font</code> used for text created by this component. + * + * @return the current font. + * @see #setFont(java.awt.Font) + */ + public Font getFont() + { + return MenuComponent.this.getFont(); + } + + /** + * Retrieves information on the rendering and metrics of the supplied + * font. If font metrics are not supported by this component, null + * is returned. + * <br /> + * <br /> + * The abstract implementation of this method simply uses the toolkit + * to obtain the <code>FontMetrics</code>. Concrete subclasses may + * find it more efficient to invoke their peer class directly, if one + * is available. + * + * @param font the font about which to retrieve rendering and metric + * information. + * @return the metrics of the given font, as provided by the system + * toolkit. + * @throws NullPointerException if the supplied font was null. + */ + public FontMetrics getFontMetrics(Font font) + { + return MenuComponent.this.getToolkit().getFontMetrics(font); + } + + /** + * Returns the foreground color of the component, or null + * if this property is unsupported. + * <br /> + * <br /> + * This abstract class knows nothing about how the component + * is drawn on screen, so this method simply returns the + * default system text color used for rendering menus. + * Concrete subclasses which handle the drawing of an onscreen + * menu component should override this method and provide + * the appropriate information. + * + * @return the default system text color for menus. + * @see #setForeground(java.awt.Color) + */ + public Color getForeground() + { + return SystemColor.menuText; + } + + /** + * Returns the locale currently in use by this component. + * <br /> + * <br /> + * This abstract class has no property relating to the + * locale used by the component, so this method simply + * returns the default locale for the current instance + * of the Java Virtual Machine (JVM). Concrete subclasses + * which maintain such a property should override this method + * and provide the locale information more accurately. + * + * @return the default locale for this JVM instance. + */ + public Locale getLocale() + { + return Locale.getDefault(); + } + + /** + * Returns the location of the component, with co-ordinates + * relative to the parent component and using the co-ordinate + * space of the screen. Thus, the point (0,0) is the upper + * left corner of the parent component. + * <br /> + * <br /> + * Please note that this method depends on a correctly implemented + * version of the <code>getBounds()</code> method. Subclasses + * must provide the bounding rectangle via <code>getBounds()</code> + * in order for this method to work. + * + * @return the location of the component, relative to its parent. + * @see #setLocation(java.awt.Point) + */ + public Point getLocation() + { + /* Simply return the location of the bounding rectangle */ + return getBounds().getLocation(); + } + + /** + * Returns the location of the component, with co-ordinates + * relative to the screen. Thus, the point (0,0) is the upper + * left corner of the screen. null is returned if the component + * is either not on screen or if this property is unsupported. + * <br /> + * <br /> + * This abstract class knows nothing about how the component + * is drawn on screen, so this method simply returns null. + * Concrete subclasses which handle the drawing of an onscreen + * menu component should override this method and provide + * the appropriate information. + * + * @return the location of the component, relative to the screen. + */ + public Point getLocationOnScreen() + { + return null; + } + + /** + * Returns the size of the component. + * <br /> + * <br /> + * Please note that this method depends on a correctly implemented + * version of the <code>getBounds()</code> method. Subclasses + * must provide the bounding rectangle via <code>getBounds()</code> + * in order for this method to work. + * + * @return the size of the component. + * @see #setSize(java.awt.Dimension) + */ + public Dimension getSize() + { + /* Simply return the size of the bounding rectangle */ + return getBounds().getSize(); + } + + /** + * Returns true if the accessible child specified by the supplied index + * is currently selected. + * <br /> + * <br /> + * As the existence of children can not be determined from + * this abstract class, the implementation of this method + * is left to subclasses. + * + * @param index the index of the accessible child to check for selection. + * @return false. + */ + public boolean isAccessibleChildSelected(int index) + { + return false; + } + + /** + * Returns true if this component is currently enabled. + * <br /> + * <br /> + * As this abstract component has no properties related to + * its enabled or disabled state, the implementation of this + * method is left to subclasses. + * + * @return false. + * @see #setEnabled(boolean) + */ + public boolean isEnabled() + { + return false; + } + + /** + * Returns true if this component is included in the traversal + * of the current focus from one component to the other. + * <br /> + * <br /> + * As this abstract component has no properties related to + * its ability to accept the focus, the implementation of this + * method is left to subclasses. + * + * @return false. + */ + public boolean isFocusTraversable() + { + return false; + } + + /** + * Returns true if the component is being shown on screen. + * A component is determined to be shown if it is visible, + * and each parent component is also visible. Please note + * that, even when a component is showing, it may still be + * obscured by other components in front. This method only + * determines if the component is being drawn on the screen. + * <br /> + * <br /> + * As this abstract component and its parent have no properties + * relating to visibility, the implementation of this method is + * left to subclasses. + * + * @return false. + * @see #isVisible() + */ + public boolean isShowing() + { + return false; + } + + /** + * Returns true if the component is visible. A component may + * be visible but not drawn on the screen if one of its parent + * components is not visible. To determine if the component is + * actually drawn on screen, <code>isShowing()</code> should be + * used. + * <br /> + * <br /> + * As this abstract component has no properties relating to its + * visibility, the implementation of this method is left to subclasses. + * + * @return false. + * @see #isShowing() + * @see #setVisible(boolean) + */ + public boolean isVisible() + { + return false; + } + + /** + * Removes the accessible child specified by the supplied index from + * the list of currently selected children. If the child specified + * is not selected, nothing happens. + * <br /> + * <br /> + * As the existence of children can not be determined from + * this abstract class, the implementation of this method + * is left to subclasses. + * + * @param index the index of the <code>Accessible</code> child. + */ + public void removeAccessibleSelection(int index) + { + /* Subclasses with children should implement this */ + } + + /** + * Removes the specified focus listener from the list of registered + * focus listeners for this component. + * + * @param listener the listener to remove. + */ + public void removeFocusListener(FocusListener listener) + { + /* Remove the focus listener from the chain */ + focusListener = AWTEventMulticaster.remove(focusListener, listener); + } + + /** + * Requests that this component gains focus. This depends on the + * component being focus traversable. + * <br /> + * <br /> + * As this abstract component has no properties relating to its + * focus traversability, or access to a peer with request focusing + * abilities, the implementation of this method is left to subclasses. + */ + public void requestFocus() + { + /* Ignored */ + } + + /** + * Selects all <code>Accessible</code> children of this component which + * it is possible to select. The component needs to support multiple + * selections. + * <br /> + * <br /> + * This abstract component provides a simplistic implementation of this + * method, which ignores the ability of the component to support multiple + * selections and simply uses <code>addAccessibleSelection</code> to + * add each <code>Accessible</code> child to the selection. The last + * <code>Accessible</code> component is thus selected for components + * which don't support multiple selections. Concrete implementations should + * override this with a more appopriate and efficient implementation, which + * properly takes into account the ability of the component to support multiple + * selections. + */ + public void selectAllAccessibleSelection() + { + /* Simply call addAccessibleSelection() on all accessible children */ + for (int a = 0; a < getAccessibleChildrenCount(); ++a) + { + addAccessibleSelection(a); + } + } + + /** + * Sets the background color of the component to that specified. + * Unspecified behaviour occurs when null is given as the new + * background color. + * <br /> + * <br /> + * This abstract class knows nothing about how the component + * is drawn on screen, so this method simply ignores the supplied + * color and continues to use the default system color. + * Concrete subclasses which handle the drawing of an onscreen + * menu component should override this method and provide + * the appropriate information. + * + * @param color the new color to use for the background. + * @see getBackground() + */ + public void setBackground(Color color) + { + /* Ignored */ + } + + /** + * Sets the height and width of the component, and its position + * relative to this component's parent, to the values specified + * by the supplied rectangle. Unspecified behaviour occurs when + * null is given as the new bounds. + * <br /> + * <br /> + * This abstract class knows nothing about how the component + * is drawn on screen, so this method simply ignores the new + * rectangle and continues to return null from <code>getBounds()</code>. + * Concrete subclasses which handle the drawing of an onscreen + * menu component should override this method and provide + * the appropriate information. + * + * @param rectangle a rectangle which specifies the new bounds of + * the component. + * @see #getBounds() + */ + public void setBounds(Rectangle rectangle) + { + /* Ignored */ + } + + /** + * Sets the <code>Cursor</code> used when the pointer is positioned over the + * component. Unspecified behaviour occurs when null is given as the new + * cursor. + * <br /> + * <br /> + * This abstract class knows nothing about how the component + * is drawn on screen, so this method simply ignores the new cursor + * and continues to return the default system cursor. Concrete + * subclasses which handle the drawing of an onscreen menu component + * may override this method and provide the appropriate information. + * + * @param cursor the new cursor to use. + * @see #getCursor() + */ + public void setCursor(Cursor cursor) + { + /* Ignored */ + } + + /** + * Sets the enabled/disabled state of this component. + * <br /> + * <br /> + * As this abstract component has no properties related to + * its enabled or disabled state, the implementation of this + * method is left to subclasses. + * + * @param enabled true if the component should be enabled, + * false otherwise. + * @see #getEnabled() + */ + public void setEnabled(boolean enabled) + { + /* Ignored */ + } + + /** + * Sets the <code>Font</code> used for text created by this component. + * Unspecified behaviour occurs when null is given as the new + * font. + * + * @param font the new font to use for text. + * @see #getFont() + */ + public void setFont(Font font) + { + /* Call the method of the enclosing component */ + MenuComponent.this.setFont(font); + } + + /** + * Sets the foreground color of the component to that specified. + * Unspecified behaviour occurs when null is given as the new + * background color. + * <br /> + * <br /> + * This abstract class knows nothing about how the component + * is drawn on screen, so this method simply ignores the supplied + * color and continues to return the default system text color used + * for rendering menus. + * Concrete subclasses which handle the drawing of an onscreen + * menu component should override this method and provide + * the appropriate information. + * + * @param color the new foreground color. + * @see #getForeground() + */ + public void setForeground(Color color) + { + /* Ignored */ + } + + /** + * Sets the location of the component, with co-ordinates + * relative to the parent component and using the co-ordinate + * space of the screen. Thus, the point (0,0) is the upper + * left corner of the parent component. + * <br /> + * <br /> + * Please note that this method depends on a correctly implemented + * version of the <code>getBounds()</code> method. Subclasses + * must provide the bounding rectangle via <code>getBounds()</code> + * in order for this method to work. + * + * @param point the location of the component, relative to its parent. + * @see #getLocation() + */ + public void setLocation(Point point) + { + getBounds().setLocation(point); + } + + /** + * Sets the size of the component. + * <br /> + * <br /> + * Please note that this method depends on a correctly implemented + * version of the <code>getBounds()</code> method. Subclasses + * must provide the bounding rectangle via <code>getBounds()</code> + * in order for this method to work. + * + * @param size the new size of the component. + * @see #getSize() + */ + public void setSize(Dimension size) + { + getBounds().setSize(size); + } + + /** + * Sets the visibility state of the component. A component may + * be visible but not drawn on the screen if one of its parent + * components is not visible. To determine if the component is + * actually drawn on screen, <code>isShowing()</code> should be + * used. + * <br /> + * <br /> + * As this abstract component has no properties relating to its + * visibility, the implementation of this method is left to subclasses. + * + * @param visibility the new visibility of the component -- true if + * the component is visible, false if not. + * @see #isShowing() + * @see #isVisible() + */ + public void setVisible(boolean visibility) + { + /* Ignored */ + } + +} /* class AccessibleAWTMenuComponent */ + + +} // class MenuComponent diff --git a/libjava/classpath/java/awt/MenuContainer.java b/libjava/classpath/java/awt/MenuContainer.java new file mode 100644 index 0000000..c76ec96 --- /dev/null +++ b/libjava/classpath/java/awt/MenuContainer.java @@ -0,0 +1,71 @@ +/* MenuContainer.java -- container for menu items + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This interface is a container for menu components. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @since 1.0 + * @status updated to 1.4 + */ +public interface MenuContainer +{ + /** + * Returns the font in use by this container. + * + * @return the menu font + */ + Font getFont(); + + /** + * Removes the specified menu component from the menu. + * + * @param component the menu component to remove + */ + void remove(MenuComponent component); + + /** + * Posts an event to the listeners. + * + * @param event the event to dispatch + * @deprecated use {@link MenuComponent#dispatchEvent(AWTEvent)} instead + */ + boolean postEvent(Event event); +} // interface MenuContainer diff --git a/libjava/classpath/java/awt/MenuItem.java b/libjava/classpath/java/awt/MenuItem.java new file mode 100644 index 0000000..66798c8 --- /dev/null +++ b/libjava/classpath/java/awt/MenuItem.java @@ -0,0 +1,603 @@ +/* MenuItem.java -- An item in a menu + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.peer.MenuItemPeer; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.EventListener; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleValue; + +/** + * This class represents an item in a menu. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class MenuItem extends MenuComponent + implements Serializable, Accessible +{ + +/* + * Static Variables + */ + +// Serialization Constant +private static final long serialVersionUID = -21757335363267194L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial The name of the action command generated by this item. + * This is package-private to avoid an accessor method. + */ +String actionCommand; + +/** + * @serial Indicates whether or not this menu item is enabled. + * This is package-private to avoid an accessor method. + */ +boolean enabled = true; + +/** + * @serial The mask of events that are enabled for this menu item. + */ +long eventMask; + +/** + * @serial This menu item's label + * This is package-private to avoid an accessor method. + */ +String label = ""; + +/** + * @serial The shortcut for this menu item, if any + */ +private MenuShortcut shortcut; + +// The list of action listeners for this menu item. +private transient ActionListener action_listeners; + + protected class AccessibleAWTMenuItem + extends MenuComponent.AccessibleAWTMenuComponent + implements AccessibleAction, AccessibleValue + { + /** Constructor */ + public AccessibleAWTMenuItem() + { + super(); + } + + + + public String getAccessibleName() + { + return label; + } + + public AccessibleAction getAccessibleAction() + { + return this; + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.MENU_ITEM; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleAction#getAccessibleActionCount() + */ + public int getAccessibleActionCount() + { + return 1; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleAction#getAccessibleActionDescription(int) + */ + public String getAccessibleActionDescription(int i) + { + if (i == 0) + return label; + else + return null; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleAction#doAccessibleAction(int) + */ + public boolean doAccessibleAction(int i) + { + if (i != 0) + return false; + processActionEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, actionCommand)); + return true; + } + + public AccessibleValue getAccessibleValue() + { + return this; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue() + */ + public Number getCurrentAccessibleValue() + { + return (enabled) ? new Integer(1) : new Integer(0); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number) + */ + public boolean setCurrentAccessibleValue(Number number) + { + if (number.intValue() == 0) + { + setEnabled(false); + return false; + } + + setEnabled(true); + return true; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue() + */ + public Number getMinimumAccessibleValue() + { + return new Integer(0); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue() + */ + public Number getMaximumAccessibleValue() + { + return new Integer(0); + } + + } + + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>MenuItem</code> with no label + * and no shortcut. + */ +public +MenuItem() +{ +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>MenuItem</code> with the specified + * label and no shortcut. + * + * @param label The label for this menu item. + */ +public +MenuItem(String label) +{ + this.label = label; +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>MenuItem</code> with the specified + * label and shortcut. + * + * @param label The label for this menu item. + * @param shortcut The shortcut for this menu item. + */ +public +MenuItem(String label, MenuShortcut shortcut) +{ + this.label = label; + this.shortcut = shortcut; +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns the label for this menu item, which may be <code>null</code>. + * + * @return The label for this menu item. + */ +public String +getLabel() +{ + return(label); +} + +/*************************************************************************/ + +/** + * This method sets the label for this menu to the specified value. + * + * @param label The new label for this menu item. + */ +public synchronized void +setLabel(String label) +{ + this.label = label; + if (peer != null) + { + MenuItemPeer mp = (MenuItemPeer) peer; + mp.setLabel (label); + } +} + +/*************************************************************************/ + +/** + * Tests whether or not this menu item is enabled. + * + * @return <code>true</code> if this menu item is enabled, <code>false</code> + * otherwise. + */ +public boolean +isEnabled() +{ + return(enabled); +} + +/*************************************************************************/ + +/** + * Sets the enabled status of this menu item. + * + * @param enabled <code>true</code> to enable this menu item, + * <code>false</code> otherwise. + */ +public synchronized void +setEnabled(boolean enabled) +{ + enable (enabled); +} + +/*************************************************************************/ + +/** + * Sets the enabled status of this menu item. + * + * @param enabled <code>true</code> to enable this menu item, + * <code>false</code> otherwise. + * + * @deprecated This method is deprecated in favor of <code>setEnabled()</code>. + */ +public void +enable(boolean enabled) +{ + if (enabled) + enable (); + else + disable (); +} + +/*************************************************************************/ + +/** + * Enables this menu item. + * + * @deprecated This method is deprecated in favor of <code>setEnabled()</code>. + */ +public void +enable() +{ + if (enabled) + return; + + this.enabled = true; + if (peer != null) + ((MenuItemPeer) peer).setEnabled (true); +} + +/*************************************************************************/ + +/** + * Disables this menu item. + * + * @deprecated This method is deprecated in favor of <code>setEnabled()</code>. + */ +public void +disable() +{ + if (!enabled) + return; + + this.enabled = false; + if (peer != null) + ((MenuItemPeer) peer).setEnabled (false); +} + +/*************************************************************************/ + +/** + * Returns the shortcut for this menu item, which may be <code>null</code>. + * + * @return The shortcut for this menu item. + */ +public MenuShortcut +getShortcut() +{ + return(shortcut); +} + +/*************************************************************************/ + +/** + * Sets the shortcut for this menu item to the specified value. This + * must be done before the native peer is created. + * + * @param shortcut The new shortcut for this menu item. + */ +public void +setShortcut(MenuShortcut shortcut) +{ + this.shortcut = shortcut; +} + +/*************************************************************************/ + +/** + * Deletes the shortcut for this menu item if one exists. This must be + * done before the native peer is created. + */ +public void +deleteShortcut() +{ + shortcut = null; +} + +/*************************************************************************/ + +/** + * Returns the name of the action command in the action events + * generated by this menu item. + * + * @return The action command name + */ +public String +getActionCommand() +{ + if (actionCommand == null) + return label; + else + return actionCommand; +} + +/*************************************************************************/ + +/** + * Sets the name of the action command in the action events generated by + * this menu item. + * + * @param actionCommand The new action command name. + */ +public void +setActionCommand(String actionCommand) +{ + this.actionCommand = actionCommand; +} + +/*************************************************************************/ + +/** + * Enables the specified events. This is done automatically when a + * listener is added and does not normally need to be done by + * application code. + * + * @param events The events to enable, which should be the bit masks + * from <code>AWTEvent</code>. + */ +protected final void +enableEvents(long events) +{ + eventMask |= events; + // TODO: see comment in Component.enableEvents(). +} + +/*************************************************************************/ + +/** + * Disables the specified events. + * + * @param events The events to enable, which should be the bit masks + * from <code>AWTEvent</code>. + */ +protected final void +disableEvents(long events) +{ + eventMask &= ~events; +} + +/*************************************************************************/ + +/** + * Creates the native peer for this object. + */ +public void +addNotify() +{ + if (peer == null) + peer = getToolkit ().createMenuItem (this); +} + +/*************************************************************************/ + +/** + * Adds the specified listener to the list of registered action listeners + * for this component. + * + * @param listener The listener to add. + */ +public synchronized void +addActionListener(ActionListener listener) +{ + action_listeners = AWTEventMulticaster.add(action_listeners, listener); + + enableEvents(AWTEvent.ACTION_EVENT_MASK); +} + +public synchronized void +removeActionListener(ActionListener l) +{ + action_listeners = AWTEventMulticaster.remove(action_listeners, l); +} + + public synchronized ActionListener[] getActionListeners() + { + return (ActionListener[]) + AWTEventMulticaster.getListeners(action_listeners, + ActionListener.class); + } + +/** Returns all registered EventListers of the given listenerType. + * listenerType must be a subclass of EventListener, or a + * ClassClassException is thrown. + * @since 1.3 + */ + public EventListener[] getListeners(Class listenerType) + { + if (listenerType == ActionListener.class) + return getActionListeners(); + return (EventListener[]) Array.newInstance(listenerType, 0); + } + +/*************************************************************************/ + +void +dispatchEventImpl(AWTEvent e) +{ + if (e.id <= ActionEvent.ACTION_LAST + && e.id >= ActionEvent.ACTION_FIRST + && (action_listeners != null + || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0)) + processEvent(e); + + // Send the event to the parent menu if it has not yet been + // consumed. + if (!e.isConsumed ()) + ((Menu) getParent ()).processEvent (e); +} + +/** + * Processes the specified event by calling <code>processActionEvent()</code> + * if it is an instance of <code>ActionEvent</code>. + * + * @param event The event to process. + */ +protected void +processEvent(AWTEvent event) +{ + if (event instanceof ActionEvent) + processActionEvent((ActionEvent)event); +} + +/*************************************************************************/ + +/** + * Processes the specified event by dispatching it to any registered listeners. + * + * @param event The event to process. + */ +protected void +processActionEvent(ActionEvent event) +{ + if (action_listeners != null) + { + event.setSource(this); + action_listeners.actionPerformed(event); + } +} + +/*************************************************************************/ + +/** + * Returns a debugging string for this object. + * + * @return A debugging string for this object. + */ +public String +paramString() +{ + return ("label=" + label + ",enabled=" + enabled + + ",actionCommand=" + actionCommand + "," + super.paramString()); +} + +/** + * Gets the AccessibleContext associated with this <code>MenuItem</code>. + * The context is created, if necessary. + * + * @return the associated context + */ +public AccessibleContext getAccessibleContext() +{ + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTMenuItem(); + return accessibleContext; +} + +} // class MenuItem diff --git a/libjava/classpath/java/awt/MenuShortcut.java b/libjava/classpath/java/awt/MenuShortcut.java new file mode 100644 index 0000000..adfd1d3 --- /dev/null +++ b/libjava/classpath/java/awt/MenuShortcut.java @@ -0,0 +1,207 @@ +/* MenuShortcut.java -- A class for menu accelerators + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This class implements a keyboard accelerator for a menu item. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class MenuShortcut implements java.io.Serializable +{ + +/* + * Static Variables + */ + +// Serialization Constant +private static final long serialVersionUID = 143448358473180225L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial The virtual keycode for the shortcut. + */ +private int key; + +/** + * @serial <code>true</code> if the shift key was used with this shortcut, + * or <code>false</code> otherwise. + */ +private boolean usesShift; + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>MenuShortcut</code> with the + * specified virtual key value. + * + * @param key The virtual keycode for the shortcut. + */ +public +MenuShortcut(int key) +{ + this(key, false); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>MenuShortcut</code> with the + * specified virtual key value and shift setting. + * + * @param key The virtual keycode for the shortcut. + * @param usesShift <code>true</code> if the shift key was pressed, + * <code>false</code> otherwise. + */ +public +MenuShortcut(int key, boolean usesShift) +{ + this.key = key; + this.usesShift = usesShift; +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns the virtual keycode for this shortcut. + * + * @return The virtual keycode for this shortcut. + */ +public int +getKey() +{ + return(key); +} + +/*************************************************************************/ + +/** + * Returns the shift setting for this shortcut. + * + * @return <code>true</code> if the shift key was pressed, <code>false</code> + * otherwise. + */ +public boolean +usesShiftModifier() +{ + return(usesShift); +} + +/*************************************************************************/ + +/** + * Tests this object for equality against the specified object. The two + * objects will be considered equal if and only if the specified object + * is an instance of <code>MenuShortcut</code> and has the same key value + * and shift setting as this object. + * + * @param obj The object to test for equality against. + * + * @return <code>true</code> if the two objects are equal, <code>false</code> + * otherwise. + */ +public boolean +equals(MenuShortcut obj) +{ + if (obj == null) + return(false); + + if (obj.key != this.key) + return(false); + + if (obj.usesShift != this.usesShift) + return(false); + + return(true); +} + +public boolean +equals(Object obj) +{ + if (obj instanceof MenuShortcut) + { + MenuShortcut ms = (MenuShortcut) obj; + return (ms.key == key && ms.usesShift == usesShift); + } + return false; +} + +/*************************************************************************/ + +/** + * Returns a string representation of this shortcut. + * + * @return A string representation of this shortcut. + */ +public String +toString() +{ + return(getClass().getName() + "[" + paramString () + "]"); +} + +public int +hashCode() +{ + // Arbitrary. + return key + (usesShift ? 23 : 57); +} + +/*************************************************************************/ + +/** + * Returns a debugging string for this object. + * + * @return A debugging string for this object. + */ +protected String +paramString() +{ + return "key=" + key + ",usesShift=" + usesShift; +} + +} // class MenuShortcut diff --git a/libjava/classpath/java/awt/PageAttributes.java b/libjava/classpath/java/awt/PageAttributes.java new file mode 100644 index 0000000..38fb696 --- /dev/null +++ b/libjava/classpath/java/awt/PageAttributes.java @@ -0,0 +1,482 @@ +/* PageAttributes.java -- + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.util.Locale; + +/** + * Missing Documentation + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + * @status updated to 1.4, but missing documentation + */ +public final class PageAttributes implements Cloneable +{ + public static final class ColorType extends AttributeValue + { + private static final String[] NAMES = { "color", "monochrome" }; + public static final ColorType COLOR = new ColorType(0); + public static final ColorType MONOCHROME = new ColorType(1); + private ColorType(int value) + { + super(value, NAMES); + } + } // class ColorType + public static final class MediaType extends AttributeValue + { + private static final String[] NAMES + = { "iso-4a0", "iso-2a0", "iso-a0", "iso-a1", "iso-a2", "iso-a3", + "iso-a4", "iso-a5", "iso-a6", "iso-a7", "iso-a8", "iso-a9", + "iso-a10", "iso-b0", "iso-b1", "iso-b2", "iso-b3", "iso-b4", + "iso-b5", "iso-b6", "iso-b7", "iso-b8", "iso-b9", "iso-b10", + "jis-b0", "jis-b1", "jis-b2", "jis-b3", "jis-b4", "jis-b5", + "jis-b6", "jis-b7", "jis-b8", "jis-b9", "jis-b10", "iso-c0", + "iso-c1", "iso-c2", "iso-c3", "iso-c4", "iso-c5", "iso-c6", + "iso-c7", "iso-c8", "iso-c9", "iso-c10", "iso-designated-long", + "executive", "folio", "invoice", "ledger", "na-letter", "na-legal", + "quarto", "a", "b", "c", "d", "e", "na-10x15-envelope", + "na-10x14-envelope", "na-10x13-envelope", "na-9x12-envelope", + "na-9x11-envelope", "na-7x9-envelope", "na-6x9-envelope", + "na-number-9-envelope", "na-number-10-envelope", + "na-number-11-envelope", "na-number-12-envelope", + "na-number-14-envelope", "invite-envelope", "italy-envelope", + "monarch-envelope", "personal-envelope" }; + public static final MediaType ISO_4A0 = new MediaType(0); + public static final MediaType ISO_2A0 = new MediaType(1); + public static final MediaType ISO_A0 = new MediaType(2); + public static final MediaType ISO_A1 = new MediaType(3); + public static final MediaType ISO_A2 = new MediaType(4); + public static final MediaType ISO_A3 = new MediaType(5); + public static final MediaType ISO_A4 = new MediaType(6); + public static final MediaType ISO_A5 = new MediaType(7); + public static final MediaType ISO_A6 = new MediaType(8); + public static final MediaType ISO_A7 = new MediaType(9); + public static final MediaType ISO_A8 = new MediaType(10); + public static final MediaType ISO_A9 = new MediaType(11); + public static final MediaType ISO_A10 = new MediaType(12); + public static final MediaType ISO_B0 = new MediaType(13); + public static final MediaType ISO_B1 = new MediaType(14); + public static final MediaType ISO_B2 = new MediaType(15); + public static final MediaType ISO_B3 = new MediaType(16); + public static final MediaType ISO_B4 = new MediaType(17); + public static final MediaType ISO_B5 = new MediaType(18); + public static final MediaType ISO_B6 = new MediaType(19); + public static final MediaType ISO_B7 = new MediaType(20); + public static final MediaType ISO_B8 = new MediaType(21); + public static final MediaType ISO_B9 = new MediaType(22); + public static final MediaType ISO_B10 = new MediaType(23); + public static final MediaType JIS_B0 = new MediaType(24); + public static final MediaType JIS_B1 = new MediaType(25); + public static final MediaType JIS_B2 = new MediaType(26); + public static final MediaType JIS_B3 = new MediaType(27); + public static final MediaType JIS_B4 = new MediaType(28); + public static final MediaType JIS_B5 = new MediaType(29); + public static final MediaType JIS_B6 = new MediaType(30); + public static final MediaType JIS_B7 = new MediaType(31); + public static final MediaType JIS_B8 = new MediaType(32); + public static final MediaType JIS_B9 = new MediaType(33); + public static final MediaType JIS_B10 = new MediaType(34); + public static final MediaType ISO_C0 = new MediaType(35); + public static final MediaType ISO_C1 = new MediaType(36); + public static final MediaType ISO_C2 = new MediaType(37); + public static final MediaType ISO_C3 = new MediaType(38); + public static final MediaType ISO_C4 = new MediaType(39); + public static final MediaType ISO_C5 = new MediaType(40); + public static final MediaType ISO_C6 = new MediaType(41); + public static final MediaType ISO_C7 = new MediaType(42); + public static final MediaType ISO_C8 = new MediaType(43); + public static final MediaType ISO_C9 = new MediaType(44); + public static final MediaType ISO_C10 = new MediaType(45); + public static final MediaType ISO_DESIGNATED_LONG = new MediaType(46); + public static final MediaType EXECUTIVE = new MediaType(47); + public static final MediaType FOLIO = new MediaType(48); + public static final MediaType INVOICE = new MediaType(49); + public static final MediaType LEDGER = new MediaType(50); + public static final MediaType NA_LETTER = new MediaType(51); + public static final MediaType NA_LEGAL = new MediaType(52); + public static final MediaType QUARTO = new MediaType(53); + public static final MediaType A = new MediaType(54); + public static final MediaType B = new MediaType(55); + public static final MediaType C = new MediaType(56); + public static final MediaType D = new MediaType(57); + public static final MediaType E = new MediaType(58); + public static final MediaType NA_10X15_ENVELOPE = new MediaType(59); + public static final MediaType NA_10X14_ENVELOPE = new MediaType(60); + public static final MediaType NA_10X13_ENVELOPE = new MediaType(61); + public static final MediaType NA_9X12_ENVELOPE = new MediaType(62); + public static final MediaType NA_9X11_ENVELOPE = new MediaType(63); + public static final MediaType NA_7X9_ENVELOPE = new MediaType(64); + public static final MediaType NA_6X9_ENVELOPE = new MediaType(65); + public static final MediaType NA_NUMBER_9_ENVELOPE = new MediaType(66); + public static final MediaType NA_NUMBER_10_ENVELOPE = new MediaType(67); + public static final MediaType NA_NUMBER_11_ENVELOPE = new MediaType(68); + public static final MediaType NA_NUMBER_12_ENVELOPE = new MediaType(69); + public static final MediaType NA_NUMBER_14_ENVELOPE = new MediaType(70); + public static final MediaType INVITE_ENVELOPE = new MediaType(71); + public static final MediaType ITALY_ENVELOPE = new MediaType(72); + public static final MediaType MONARCH_ENVELOPE = new MediaType(73); + public static final MediaType PERSONAL_ENVELOPE = new MediaType(74); + public static final MediaType A0 = ISO_A0; + public static final MediaType A1 = ISO_A1; + public static final MediaType A2 = ISO_A2; + public static final MediaType A3 = ISO_A3; + public static final MediaType A4 = ISO_A4; + public static final MediaType A5 = ISO_A5; + public static final MediaType A6 = ISO_A6; + public static final MediaType A7 = ISO_A7; + public static final MediaType A8 = ISO_A8; + public static final MediaType A9 = ISO_A9; + public static final MediaType A10 = ISO_A10; + public static final MediaType B0 = ISO_B0; + public static final MediaType B1 = ISO_B1; + public static final MediaType B2 = ISO_B2; + public static final MediaType B3 = ISO_B3; + public static final MediaType B4 = ISO_B4; + public static final MediaType ISO_B4_ENVELOPE = ISO_B4; + public static final MediaType B5 = ISO_B5; + public static final MediaType ISO_B5_ENVELOPE = ISO_B4; + public static final MediaType B6 = ISO_B6; + public static final MediaType B7 = ISO_B7; + public static final MediaType B8 = ISO_B8; + public static final MediaType B9 = ISO_B9; + public static final MediaType B10 = ISO_B10; + public static final MediaType C0 = ISO_B0; + public static final MediaType ISO_C0_ENVELOPE = ISO_C0; + public static final MediaType C1 = ISO_C1; + public static final MediaType ISO_C1_ENVELOPE = ISO_C1; + public static final MediaType C2 = ISO_C2; + public static final MediaType ISO_C2_ENVELOPE = ISO_C2; + public static final MediaType C3 = ISO_C3; + public static final MediaType ISO_C3_ENVELOPE = ISO_C3; + public static final MediaType C4 = ISO_C4; + public static final MediaType ISO_C4_ENVELOPE = ISO_C4; + public static final MediaType C5 = ISO_C5; + public static final MediaType ISO_C5_ENVELOPE = ISO_C5; + public static final MediaType C6 = ISO_C6; + public static final MediaType ISO_C6_ENVELOPE = ISO_C6; + public static final MediaType C7 = ISO_C7; + public static final MediaType ISO_C7_ENVELOPE = ISO_C7; + public static final MediaType C8 = ISO_C8; + public static final MediaType ISO_C8_ENVELOPE = ISO_C8; + public static final MediaType C9 = ISO_C9; + public static final MediaType ISO_C9_ENVELOPE = ISO_C9; + public static final MediaType C10 = ISO_C10; + public static final MediaType ISO_C10_ENVELOPE = ISO_C10; + public static final MediaType ISO_DESIGNATED_LONG_ENVELOPE + = ISO_DESIGNATED_LONG; + public static final MediaType STATEMENT = INVOICE; + public static final MediaType TABLOID = LEDGER; + public static final MediaType LETTER = NA_LETTER; + public static final MediaType NOTE = NA_LETTER; + public static final MediaType LEGAL = NA_LEGAL; + public static final MediaType ENV_10X15 = NA_10X15_ENVELOPE; + public static final MediaType ENV_10X14 = NA_10X14_ENVELOPE; + public static final MediaType ENV_10X13 = NA_10X13_ENVELOPE; + public static final MediaType ENV_9X12 = NA_9X12_ENVELOPE; + public static final MediaType ENV_9X11 = NA_9X11_ENVELOPE; + public static final MediaType ENV_7X9 = NA_7X9_ENVELOPE; + public static final MediaType ENV_6X9 = NA_6X9_ENVELOPE; + public static final MediaType ENV_9 = NA_NUMBER_9_ENVELOPE; + public static final MediaType ENV_10 = NA_NUMBER_10_ENVELOPE; + public static final MediaType ENV_11 = NA_NUMBER_11_ENVELOPE; + public static final MediaType ENV_12 = NA_NUMBER_12_ENVELOPE; + public static final MediaType ENV_14 = NA_NUMBER_14_ENVELOPE; + public static final MediaType ENV_INVITE = INVITE_ENVELOPE; + public static final MediaType ENV_ITALY = ITALY_ENVELOPE; + public static final MediaType ENV_MONARCH = MONARCH_ENVELOPE; + public static final MediaType ENV_PERSONAL = PERSONAL_ENVELOPE; + public static final MediaType INVITE = INVITE_ENVELOPE; + public static final MediaType ITALY = ITALY_ENVELOPE; + public static final MediaType MONARCH = MONARCH_ENVELOPE; + public static final MediaType PERSONAL = PERSONAL_ENVELOPE; + private MediaType(int value) + { + super(value, NAMES); + } + } // class MediaType + public static final class OrientationRequestedType extends AttributeValue + { + private static final String[] NAMES = { "portrait", "landscape" }; + public static final OrientationRequestedType PORTRAIT + = new OrientationRequestedType(0); + public static final OrientationRequestedType LANDSCAPE + = new OrientationRequestedType(1); + private OrientationRequestedType(int value) + { + super(value, NAMES); + } + } // class OrientationRequestedType + public static final class OriginType extends AttributeValue + { + private static final String[] NAMES = { "physical", "printable" }; + public static final OriginType PHYSICAL = new OriginType(0); + public static final OriginType PRINTABLE = new OriginType(1); + private OriginType(int value) + { + super(value, NAMES); + } + } // class OriginType + public static final class PrintQualityType extends AttributeValue + { + private static final String[] NAMES = { "high", "normal", "draft" }; + public static final PrintQualityType HIGH = new PrintQualityType(0); + public static final PrintQualityType NORMAL = new PrintQualityType(1); + public static final PrintQualityType DRAFT = new PrintQualityType(2); + private PrintQualityType(int value) + { + super(value, NAMES); + } + } // class PrintQualityType + + + private ColorType color; + private MediaType media; + private OrientationRequestedType orientation; + private OriginType origin; + private PrintQualityType quality; + private int resolutionX; + private int resolutionY; + private int resolutionScale; + public PageAttributes() + { + color = ColorType.MONOCHROME; + setMediaToDefault(); + orientation = OrientationRequestedType.PORTRAIT; + origin = OriginType.PHYSICAL; + quality = PrintQualityType.NORMAL; + setPrinterResolutionToDefault(); + } + + public PageAttributes(PageAttributes attr) + { + set(attr); + } + + public PageAttributes(ColorType color, MediaType media, + OrientationRequestedType orientation, + OriginType origin, PrintQualityType quality, + int[] resolution) + { + if (color == null || media == null || orientation == null + || origin == null || quality == null) + throw new IllegalArgumentException(); + setPrinterResolution(resolution); + this.color = color; + this.media = media; + this.orientation = orientation; + this.origin = origin; + this.quality = quality; + } + + public Object clone() + { + return new PageAttributes(this); + } + + public void set(PageAttributes attr) + { + color = attr.color; + media = attr.media; + orientation = attr.orientation; + origin = attr.origin; + quality = attr.quality; + resolutionX = attr.resolutionX; + resolutionY = attr.resolutionY; + resolutionScale = attr.resolutionScale; + } + + public ColorType getColor() + { + return color; + } + + public void setColor(ColorType color) + { + if (color == null) + throw new IllegalArgumentException(); + this.color = color; + } + + public MediaType getMedia() + { + return media; + } + + public void setMedia(MediaType media) + { + if (media == null) + throw new IllegalArgumentException(); + this.media = media; + } + + public void setMediaToDefault() + { + String country = Locale.getDefault().getCountry(); + media = ("US".equals(country) || "CA".equals(country)) ? MediaType.LETTER + : MediaType.A4; + } + + public OrientationRequestedType getOrientationRequested() + { + return orientation; + } + + public void setOrientationRequested(OrientationRequestedType orientation) + { + if (orientation == null) + throw new IllegalArgumentException(); + this.orientation = orientation; + } + + public void setOrientationRequested(int orientation) + { + if (orientation == 3) + this.orientation = OrientationRequestedType.PORTRAIT; + else if (orientation == 4) + this.orientation = OrientationRequestedType.LANDSCAPE; + else + throw new IllegalArgumentException(); + } + + public void setOrientationRequestedToDefault() + { + orientation = OrientationRequestedType.PORTRAIT; + } + + public OriginType getOrigin() + { + return origin; + } + + public void setOrigin(OriginType origin) + { + if (origin == null) + throw new IllegalArgumentException(); + this.origin = origin; + } + + public PrintQualityType getPrintQuality() + { + return quality; + } + + public void setPrintQuality(PrintQualityType quality) + { + if (quality == null) + throw new IllegalArgumentException(); + this.quality = quality; + } + + public void setPrintQuality(int quality) + { + if (quality == 3) + this.quality = PrintQualityType.DRAFT; + else if (quality == 4) + this.quality = PrintQualityType.NORMAL; + else if (quality == 5) + this.quality = PrintQualityType.HIGH; + else + throw new IllegalArgumentException(); + } + + public void setPrintQualityToDefault() + { + quality = PrintQualityType.NORMAL; + } + + public int[] getPrinterResolution() + { + return new int[] { resolutionX, resolutionY, resolutionScale }; + } + + public void setPrinterResolution(int[] resolution) + { + if (resolution == null || resolution.length != 3 || resolution[0] <= 0 + || resolution[1] <= 0 || resolution[2] < 3 || resolution[2] > 4) + throw new IllegalArgumentException(); + resolutionX = resolution[0]; + resolutionY = resolution[1]; + resolutionScale = resolution[2]; + } + + public void setPrinterResolution(int resolution) + { + if (resolution <= 0) + throw new IllegalArgumentException(); + resolutionX = resolution; + resolutionY = resolution; + resolutionScale = 3; + } + + public void setPrinterResolutionToDefault() + { + resolutionX = 72; + resolutionY = 72; + resolutionScale = 3; + } + + public boolean equals(Object o) + { + if (this == o) + return true; + if (! (o instanceof PageAttributes)) + return false; + PageAttributes pa = (PageAttributes) o; + return color == pa.color && media == pa.media + && orientation == pa.orientation && origin == pa.origin + && quality == pa.quality && resolutionX == pa.resolutionX + && resolutionY == pa.resolutionY + && resolutionScale == pa.resolutionScale; + } + public int hashCode() + { + return (color.value << 31) ^ (media.value << 24) + ^ (orientation.value << 23) ^ (origin.value << 22) + ^ (quality.value << 20) ^ (resolutionScale << 19) + ^ (resolutionY << 10) ^ resolutionX; + } + public String toString() + { + return "color=" + color + ",media=" + media + ",orientation-requested=" + + orientation + ",origin=" + origin + ",print-quality=" + quality + + ",printer-resolution=[" + resolutionX + ',' + resolutionY + ',' + + resolutionScale + ']'; + } +} // class PageAttributes diff --git a/libjava/classpath/java/awt/Paint.java b/libjava/classpath/java/awt/Paint.java new file mode 100644 index 0000000..0f099cc --- /dev/null +++ b/libjava/classpath/java/awt/Paint.java @@ -0,0 +1,79 @@ +/* Paint.java -- generate colors for Graphics2D operations + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.ColorModel; + +/** + * Defines how color patterns are generated for Graphics2D operations. This + * is used to perform the <code>draw</code> and <code>fill</code> methods + * of the graphics object. Instances must be immutable, because the graphics + * object does not clone them. + * + * @author Warren Levy (warrenl@cygnus.com) + * @see PaintContext + * @see Color + * @see GradientPaint + * @see TexturePaint + * @see Graphics2D#setPaint(Paint) + * @since 1.1 + * @status updated to 1.4 + */ +public interface Paint extends Transparency +{ + /** + * Create the context necessary for performing the color pattern generation. + * The color model is a hint, and may be null for Classpath implementations; + * however some legacy code may throw a NullPointerException when passed a + * null. Leaving the color model null provides the most efficiency and leeway + * in the generation of the color pattern. + * + * @param cm the color model, used as a hint + * @param deviceBounds the device space bounding box of the painted area + * @param userBounds the user space bounding box of the painted area + * @param xform the transformation from user space to device space + * @param hints any hints for choosing between rendering alternatives + * @return the context for performing the paint + */ + PaintContext createContext(ColorModel cm, Rectangle deviceBounds, + Rectangle2D userBounds, AffineTransform xform, + RenderingHints hints); +} // interface Paint diff --git a/libjava/classpath/java/awt/PaintContext.java b/libjava/classpath/java/awt/PaintContext.java new file mode 100644 index 0000000..3d5fdcd --- /dev/null +++ b/libjava/classpath/java/awt/PaintContext.java @@ -0,0 +1,76 @@ +/* PaintContext.java -- the environment for performing a paint operation + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.image.ColorModel; +import java.awt.image.Raster; + +/** + * @author Warren Levy (warrenl@cygnus.com) + * @see Paint + * @since 1.1 + * @status updated to 1.4 + */ +public interface PaintContext +{ + /** + * Release the resources allocated for the paint. + */ + void dispose(); + + /** + * Return the color model of this context. It may be different from the + * hint specified during createContext, as not all contexts can generate + * color patterns in an arbitrary model. + * + * @return the context color model + */ + ColorModel getColorModel(); + + /** + * Return a raster containing the colors for the graphics operation. + * + * @param x the x-coordinate, in device space + * @param y the y-coordinate, in device space + * @param w the width, in device space + * @param h the height, in device space + * @return a raster for the given area and color + */ + Raster getRaster(int x, int y, int w, int h); +} // interface PaintContext diff --git a/libjava/classpath/java/awt/Panel.java b/libjava/classpath/java/awt/Panel.java new file mode 100644 index 0000000..cc17eef --- /dev/null +++ b/libjava/classpath/java/awt/Panel.java @@ -0,0 +1,173 @@ +/* Panel.java -- Simple container object + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * A panel is a simple container class. It's default layout is the + * <code>FlowLayout</code> manager. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @see FlowLayout + * @since 1.0 + * @status updated to 1.4 + */ +public class Panel extends Container implements Accessible +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -2728009084054400034L; + + /** The cached accessible context. */ + private transient AccessibleContext context; + + /** Flag set when the first system-requested paint event is + dispatched. */ + private transient boolean initialSystemUpdateDone; + + /** Flag set when the first application-requested paint event is + consumed. */ + private transient boolean initialUpdateConsumed; + + /* + * The number used to generate the name returned by getName. + */ + private static transient long next_panel_number; + + /** + * Initializes a new instance of <code>Panel</code> that has a default + * layout manager of <code>FlowLayout</code>. + */ + public Panel() + { + this(new FlowLayout()); + } + + /** + * Initializes a new instance of <code>Panel</code> with the specified + * layout manager. + * + * @param layoutManager the layout manager for this object + * @since 1.1 + */ + public Panel(LayoutManager layoutManager) + { + setLayout(layoutManager); + } + + /** + * Notifies this object to create its native peer. + * + * @see #isDisplayable() + * @see #removeNotify() + */ + public void addNotify() + { + if (peer == null) + peer = getToolkit().createPanel(this); + super.addNotify(); + } + + /** + * Gets the AccessibleContext associated with this panel, creating one if + * necessary. This always returns an instance of {@link AccessibleAWTPanel}. + * + * @return the accessibility context of this panel + * @since 1.3 + */ + public AccessibleContext getAccessibleContext() + { + if (context == null) + context = new AccessibleAWTPanel(); + return context; + } + + /** + * This class provides accessibility support for Panels, and is the + * runtime type returned by {@link #getAccessibleContext()}. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + */ + protected class AccessibleAWTPanel extends AccessibleAWTContainer + { + /** + * Compatible with JDK 1.4+. + */ + private static final long serialVersionUID = -6409552226660031050L; + + /** + * The default constructor. + */ + protected AccessibleAWTPanel() + { + } + + /** + * Get the role of this accessible object, a panel. + * + * @return the role of the object + * @see AccessibleRole#PANEL + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.PANEL; + } + } + + /** + * Generate a unique name for this panel. + * + * @return A unique name for this panel. + */ + String generateName () + { + return "panel" + getUniqueLong (); + } + + private static synchronized long getUniqueLong () + { + return next_panel_number++; + } +} diff --git a/libjava/classpath/java/awt/Point.java b/libjava/classpath/java/awt/Point.java new file mode 100644 index 0000000..492749b --- /dev/null +++ b/libjava/classpath/java/awt/Point.java @@ -0,0 +1,245 @@ +/* Point.java -- represents a point in 2-D space + Copyright (C) 1999, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.geom.Point2D; +import java.io.Serializable; + +/** + * This class represents a point on the screen using cartesian coordinates. + * Remember that in screen coordinates, increasing x values go from left to + * right, and increasing y values go from top to bottom. + * + * <p>There are some public fields; if you mess with them in an inconsistent + * manner, it is your own fault when you get invalid results. Also, this + * class is not threadsafe. + * + * @author Per Bothner (bothner@cygnus.com) + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status updated to 1.4 + */ +public class Point extends Point2D implements Serializable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -5276940640259749850L; + + /** + * The x coordinate. + * + * @see #getLocation() + * @see #move(int, int) + * @serial the X coordinate of the point + */ + public int x; + + /** + * The y coordinate. + * + * @see #getLocation() + * @see #move(int, int) + * @serial The Y coordinate of the point + */ + public int y; + + /** + * Initializes a new instance of <code>Point</code> representing the + * coordiates (0,0). + * + * @since 1.1 + */ + public Point() + { + } + + /** + * Initializes a new instance of <code>Point</code> with coordinates + * identical to the coordinates of the specified points. + * + * @param p the point to copy the coordinates from + * @throws NullPointerException if p is null + */ + public Point(Point p) + { + x = p.x; + y = p.y; + } + + /** + * Initializes a new instance of <code>Point</code> with the specified + * coordinates. + * + * @param x the X coordinate + * @param y the Y coordinate + */ + public Point(int x, int y) + { + this.x = x; + this.y = y; + } + + /** + * Get the x coordinate. + * + * @return the value of x, as a double + */ + public double getX() + { + return x; + } + + /** + * Get the y coordinate. + * + * @return the value of y, as a double + */ + public double getY() + { + return y; + } + + /** + * Returns the location of this point. A pretty useless method, as this + * is already a point. + * + * @return a copy of this point + * @see #setLocation(Point) + * @since 1.1 + */ + public Point getLocation() + { + return new Point(x, y); + } + + /** + * Sets this object's coordinates to match those of the specified point. + * + * @param p the point to copy the coordinates from + * @throws NullPointerException if p is null + * @since 1.1 + */ + public void setLocation(Point p) + { + x = p.x; + y = p.y; + } + + /** + * Sets this object's coordinates to the specified values. This method + * is identical to the <code>move()</code> method. + * + * @param x the new X coordinate + * @param y the new Y coordinate + */ + public void setLocation(int x, int y) + { + this.x = x; + this.y = y; + } + + /** + * Sets this object's coordinates to the specified values. This method + * performs normal casting from double to int, so you may lose precision. + * + * @param x the new X coordinate + * @param y the new Y coordinate + */ + public void setLocation(double x, double y) + { + this.x = (int) x; + this.y = (int) y; + } + + /** + * Sets this object's coordinates to the specified values. This method + * is identical to the <code>setLocation(int, int)</code> method. + * + * @param x the new X coordinate + * @param y the new Y coordinate + */ + public void move(int x, int y) + { + this.x = x; + this.y = y; + } + + /** + * Changes the coordinates of this point such that the specified + * <code>dx</code> parameter is added to the existing X coordinate and + * <code>dy</code> is added to the existing Y coordinate. + * + * @param dx the amount to add to the X coordinate + * @param dy the amount to add to the Y coordinate + */ + public void translate(int dx, int dy) + { + x += dx; + y += dy; + } + + /** + * Tests whether or not this object is equal to the specified object. + * This will be true if and only if the specified object is an instance + * of Point2D and has the same X and Y coordinates. + * + * @param obj the object to test against for equality + * @return true if the specified object is equal + */ + public boolean equals(Object obj) + { + if (! (obj instanceof Point2D)) + return false; + Point2D p = (Point2D) obj; + return x == p.getX() && y == p.getY(); + } + + /** + * Returns a string representation of this object. The format is: + * <code>getClass().getName() + "[x=" + x + ",y=" + y + ']'</code>. + * + * @return a string representation of this object + */ + public String toString() + { + return getClass().getName() + "[x=" + x + ",y=" + y + ']'; + } +} // class Point diff --git a/libjava/classpath/java/awt/Polygon.java b/libjava/classpath/java/awt/Polygon.java new file mode 100644 index 0000000..a72522c --- /dev/null +++ b/libjava/classpath/java/awt/Polygon.java @@ -0,0 +1,613 @@ +/* Polygon.java -- class representing a polygon + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.io.Serializable; + +/** + * This class represents a polygon, a closed, two-dimensional region in a + * coordinate space. The region is bounded by an arbitrary number of line + * segments, between (x,y) coordinate vertices. The polygon has even-odd + * winding, meaning that a point is inside the shape if it crosses the + * boundary an odd number of times on the way to infinity. + * + * <p>There are some public fields; if you mess with them in an inconsistent + * manner, it is your own fault when you get NullPointerException, + * ArrayIndexOutOfBoundsException, or invalid results. Also, this class is + * not threadsafe. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status updated to 1.4 + */ +public class Polygon implements Shape, Serializable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -6460061437900069969L; + + /** + * This total number of endpoints. + * + * @serial the number of endpoints, possibly less than the array sizes + */ + public int npoints; + + /** + * The array of X coordinates of endpoints. This should not be null. + * + * @see #addPoint(int, int) + * @serial the x coordinates + */ + public int[] xpoints; + + /** + * The array of Y coordinates of endpoints. This should not be null. + * + * @see #addPoint(int, int) + * @serial the y coordinates + */ + public int[] ypoints; + + /** + * The bounding box of this polygon. This is lazily created and cached, so + * it must be invalidated after changing points. + * + * @see #getBounds() + * @serial the bounding box, or null + */ + protected Rectangle bounds; + + /** A big number, but not so big it can't survive a few float operations */ + private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0; + + /** + * Initializes an empty polygon. + */ + public Polygon() + { + // Leave room for growth. + xpoints = new int[4]; + ypoints = new int[4]; + } + + /** + * Create a new polygon with the specified endpoints. The arrays are copied, + * so that future modifications to the parameters do not affect the polygon. + * + * @param xpoints the array of X coordinates for this polygon + * @param ypoints the array of Y coordinates for this polygon + * @param npoints the total number of endpoints in this polygon + * @throws NegativeArraySizeException if npoints is negative + * @throws IndexOutOfBoundsException if npoints exceeds either array + * @throws NullPointerException if xpoints or ypoints is null + */ + public Polygon(int[] xpoints, int[] ypoints, int npoints) + { + this.xpoints = new int[npoints]; + this.ypoints = new int[npoints]; + System.arraycopy(xpoints, 0, this.xpoints, 0, npoints); + System.arraycopy(ypoints, 0, this.ypoints, 0, npoints); + this.npoints = npoints; + } + + /** + * Reset the polygon to be empty. The arrays are left alone, to avoid object + * allocation, but the number of points is set to 0, and all cached data + * is discarded. If you are discarding a huge number of points, it may be + * more efficient to just create a new Polygon. + * + * @see #invalidate() + * @since 1.4 + */ + public void reset() + { + npoints = 0; + invalidate(); + } + + /** + * Invalidate or flush all cached data. After direct manipulation of the + * public member fields, this is necessary to avoid inconsistent results + * in methods like <code>contains</code>. + * + * @see #getBounds() + * @since 1.4 + */ + public void invalidate() + { + bounds = null; + } + + /** + * Translates the polygon by adding the specified values to all X and Y + * coordinates. This updates the bounding box, if it has been calculated. + * + * @param dx the amount to add to all X coordinates + * @param dy the amount to add to all Y coordinates + * @since 1.1 + */ + public void translate(int dx, int dy) + { + int i = npoints; + while (--i >= 0) + { + xpoints[i] += dx; + ypoints[i] += dy; + } + if (bounds != null) + { + bounds.x += dx; + bounds.y += dy; + } + } + + /** + * Adds the specified endpoint to the polygon. This updates the bounding + * box, if it has been created. + * + * @param x the X coordinate of the point to add + * @param y the Y coordiante of the point to add + */ + public void addPoint(int x, int y) + { + if (npoints + 1 > xpoints.length) + { + int[] newx = new int[npoints + 1]; + System.arraycopy(xpoints, 0, newx, 0, npoints); + xpoints = newx; + } + if (npoints + 1 > ypoints.length) + { + int[] newy = new int[npoints + 1]; + System.arraycopy(ypoints, 0, newy, 0, npoints); + ypoints = newy; + } + xpoints[npoints] = x; + ypoints[npoints] = y; + npoints++; + if (bounds != null) + { + if (npoints == 1) + { + bounds.x = x; + bounds.y = y; + } + else + { + if (x < bounds.x) + { + bounds.width += bounds.x - x; + bounds.x = x; + } + else if (x > bounds.x + bounds.width) + bounds.width = x - bounds.x; + if (y < bounds.y) + { + bounds.height += bounds.y - y; + bounds.y = y; + } + else if (y > bounds.y + bounds.height) + bounds.height = y - bounds.y; + } + } + } + + /** + * Returns the bounding box of this polygon. This is the smallest + * rectangle with sides parallel to the X axis that will contain this + * polygon. + * + * @return the bounding box for this polygon + * @see #getBounds2D() + * @since 1.1 + */ + public Rectangle getBounds() + { + return getBoundingBox(); + } + + /** + * Returns the bounding box of this polygon. This is the smallest + * rectangle with sides parallel to the X axis that will contain this + * polygon. + * + * @return the bounding box for this polygon + * @see #getBounds2D() + * @deprecated use {@link #getBounds()} instead + */ + public Rectangle getBoundingBox() + { + if (bounds == null) + { + if (npoints == 0) + return bounds = new Rectangle(); + int i = npoints - 1; + int minx = xpoints[i]; + int maxx = minx; + int miny = ypoints[i]; + int maxy = miny; + while (--i >= 0) + { + int x = xpoints[i]; + int y = ypoints[i]; + if (x < minx) + minx = x; + else if (x > maxx) + maxx = x; + if (y < miny) + miny = y; + else if (y > maxy) + maxy = y; + } + bounds = new Rectangle(minx, miny, maxx - minx, maxy - miny); + } + return bounds; + } + + /** + * Tests whether or not the specified point is inside this polygon. + * + * @param p the point to test + * @return true if the point is inside this polygon + * @throws NullPointerException if p is null + * @see #contains(double, double) + */ + public boolean contains(Point p) + { + return contains(p.getX(), p.getY()); + } + + /** + * Tests whether or not the specified point is inside this polygon. + * + * @param x the X coordinate of the point to test + * @param y the Y coordinate of the point to test + * @return true if the point is inside this polygon + * @see #contains(double, double) + * @since 1.1 + */ + public boolean contains(int x, int y) + { + return contains((double) x, (double) y); + } + + /** + * Tests whether or not the specified point is inside this polygon. + * + * @param x the X coordinate of the point to test + * @param y the Y coordinate of the point to test + * @return true if the point is inside this polygon + * @see #contains(double, double) + * @deprecated use {@link #contains(int, int)} instead + */ + public boolean inside(int x, int y) + { + return contains((double) x, (double) y); + } + + /** + * Returns a high-precision bounding box of this polygon. This is the + * smallest rectangle with sides parallel to the X axis that will contain + * this polygon. + * + * @return the bounding box for this polygon + * @see #getBounds() + * @since 1.2 + */ + public Rectangle2D getBounds2D() + { + // For polygons, the integer version is exact! + return getBounds(); + } + + /** + * Tests whether or not the specified point is inside this polygon. + * + * @param x the X coordinate of the point to test + * @param y the Y coordinate of the point to test + * @return true if the point is inside this polygon + * @since 1.2 + */ + public boolean contains(double x, double y) + { + return ((evaluateCrossings(x, y, false, BIG_VALUE) & 1) != 0); + } + + /** + * Tests whether or not the specified point is inside this polygon. + * + * @param p the point to test + * @return true if the point is inside this polygon + * @throws NullPointerException if p is null + * @see #contains(double, double) + * @since 1.2 + */ + public boolean contains(Point2D p) + { + return contains(p.getX(), p.getY()); + } + + /** + * Test if a high-precision rectangle intersects the shape. This is true + * if any point in the rectangle is in the shape. This implementation is + * precise. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle, treated as point if negative + * @param h the height of the rectangle, treated as point if negative + * @return true if the rectangle intersects this shape + * @since 1.2 + */ + public boolean intersects(double x, double y, double w, double h) + { + /* Does any edge intersect? */ + if (evaluateCrossings(x, y, false, w) != 0 /* top */ + || evaluateCrossings(x, y + h, false, w) != 0 /* bottom */ + || evaluateCrossings(x + w, y, true, h) != 0 /* right */ + || evaluateCrossings(x, y, true, h) != 0) /* left */ + return true; + + /* No intersections, is any point inside? */ + if ((evaluateCrossings(x, y, false, BIG_VALUE) & 1) != 0) + return true; + + return false; + } + + /** + * Test if a high-precision rectangle intersects the shape. This is true + * if any point in the rectangle is in the shape. This implementation is + * precise. + * + * @param r the rectangle + * @return true if the rectangle intersects this shape + * @throws NullPointerException if r is null + * @see #intersects(double, double, double, double) + * @since 1.2 + */ + public boolean intersects(Rectangle2D r) + { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Test if a high-precision rectangle lies completely in the shape. This is + * true if all points in the rectangle are in the shape. This implementation + * is precise. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle, treated as point if negative + * @param h the height of the rectangle, treated as point if negative + * @return true if the rectangle is contained in this shape + * @since 1.2 + */ + public boolean contains(double x, double y, double w, double h) + { + if (! getBounds2D().intersects(x, y, w, h)) + return false; + + /* Does any edge intersect? */ + if (evaluateCrossings(x, y, false, w) != 0 /* top */ + || evaluateCrossings(x, y + h, false, w) != 0 /* bottom */ + || evaluateCrossings(x + w, y, true, h) != 0 /* right */ + || evaluateCrossings(x, y, true, h) != 0) /* left */ + return false; + + /* No intersections, is any point inside? */ + if ((evaluateCrossings(x, y, false, BIG_VALUE) & 1) != 0) + return true; + + return false; + } + + /** + * Test if a high-precision rectangle lies completely in the shape. This is + * true if all points in the rectangle are in the shape. This implementation + * is precise. + * + * @param r the rectangle + * @return true if the rectangle is contained in this shape + * @throws NullPointerException if r is null + * @see #contains(double, double, double, double) + * @since 1.2 + */ + public boolean contains(Rectangle2D r) + { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Return an iterator along the shape boundary. If the optional transform + * is provided, the iterator is transformed accordingly. Each call returns + * a new object, independent from others in use. This class is not + * threadsafe to begin with, so the path iterator is not either. + * + * @param transform an optional transform to apply to the iterator + * @return a new iterator over the boundary + * @since 1.2 + */ + public PathIterator getPathIterator(final AffineTransform transform) + { + return new PathIterator() + { + /** The current vertex of iteration. */ + private int vertex; + + public int getWindingRule() + { + return WIND_EVEN_ODD; + } + + public boolean isDone() + { + return vertex > npoints; + } + + public void next() + { + vertex++; + } + + public int currentSegment(float[] coords) + { + if (vertex >= npoints) + return SEG_CLOSE; + coords[0] = xpoints[vertex]; + coords[1] = ypoints[vertex]; + if (transform != null) + transform.transform(coords, 0, coords, 0, 1); + return vertex == 0 ? SEG_MOVETO : SEG_LINETO; + } + + public int currentSegment(double[] coords) + { + if (vertex >= npoints) + return SEG_CLOSE; + coords[0] = xpoints[vertex]; + coords[1] = ypoints[vertex]; + if (transform != null) + transform.transform(coords, 0, coords, 0, 1); + return vertex == 0 ? SEG_MOVETO : SEG_LINETO; + } + }; + } + + /** + * Return an iterator along the flattened version of the shape boundary. + * Since polygons are already flat, the flatness parameter is ignored, and + * the resulting iterator only has SEG_MOVETO, SEG_LINETO and SEG_CLOSE + * points. If the optional transform is provided, the iterator is + * transformed accordingly. Each call returns a new object, independent + * from others in use. This class is not threadsafe to begin with, so the + * path iterator is not either. + * + * @param transform an optional transform to apply to the iterator + * @param flatness the maximum distance for deviation from the real boundary + * @return a new iterator over the boundary + * @since 1.2 + */ + public PathIterator getPathIterator(AffineTransform transform, + double flatness) + { + return getPathIterator(transform); + } + + /** + * Helper for contains, intersects, calculates the number of intersections + * between the polygon and a line extending from the point (x, y) along + * the positive X, or Y axis, within a given interval. + * + * @return the winding number. + * @see #condensed + * @see #contains(double, double) + */ + private int evaluateCrossings(double x, double y, boolean useYaxis, + double distance) + { + double x0; + double x1; + double y0; + double y1; + double epsilon = 0.0; + int crossings = 0; + int[] xp; + int[] yp; + + if (useYaxis) + { + xp = ypoints; + yp = xpoints; + double swap; + swap = y; + y = x; + x = swap; + } + else + { + xp = xpoints; + yp = ypoints; + } + + /* Get a value which is small but not insignificant relative the path. */ + epsilon = 1E-7; + + x0 = xp[0] - x; + y0 = yp[0] - y; + for (int i = 1; i < npoints; i++) + { + x1 = xp[i] - x; + y1 = yp[i] - y; + + if (y0 == 0.0) + y0 -= epsilon; + if (y1 == 0.0) + y1 -= epsilon; + if (y0 * y1 < 0) + if (Line2D.linesIntersect(x0, y0, x1, y1, epsilon, 0.0, distance, 0.0)) + ++crossings; + + x0 = xp[i] - x; + y0 = yp[i] - y; + } + + // end segment + x1 = xp[0] - x; + y1 = yp[0] - y; + if (y0 == 0.0) + y0 -= epsilon; + if (y1 == 0.0) + y1 -= epsilon; + if (y0 * y1 < 0) + if (Line2D.linesIntersect(x0, y0, x1, y1, epsilon, 0.0, distance, 0.0)) + ++crossings; + + return crossings; + } +} // class Polygon + diff --git a/libjava/classpath/java/awt/PopupMenu.java b/libjava/classpath/java/awt/PopupMenu.java new file mode 100644 index 0000000..90d48d9 --- /dev/null +++ b/libjava/classpath/java/awt/PopupMenu.java @@ -0,0 +1,169 @@ +/* PopupMenu.java -- An AWT popup menu + Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.peer.PopupMenuPeer; + +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * This class implement an AWT popup menu widget + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class PopupMenu extends Menu +{ + +/* + * Static Variables + */ + +// Serialization Constant +private static final long serialVersionUID = -4620452533522760060L; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>PopupMenu</code>. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true. + */ +public +PopupMenu() +{ +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>PopupMenu</code> with the specified + * label. + * + * @param label The label for this popup menu. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true. + */ +public +PopupMenu(String label) +{ + super(label); + + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException (); +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Creates this object's native peer. + */ +public void +addNotify() +{ + if (peer == null) + peer = getToolkit ().createPopupMenu (this); + super.addNotify (); +} + +/*************************************************************************/ + +/** + * Displays this popup menu at the specified coordinates relative to + * the specified component. + * + * @param component The component to which the display coordinates are relative. + * @param x The X coordinate of the menu. + * @param y The Y coordinate of the menu. + */ +public void +show(Component component, int x, int y) +{ + if (getPeer() == null) + this.addNotify(); + PopupMenuPeer pmp = (PopupMenuPeer)getPeer(); + if (pmp != null) + { + /* XXX + Event e = new Event (component, Event.ACTION_EVENT, component); + e.x = x; + e.y = y;*/ + pmp.show (component, x, y); + } +} + + protected class AccessibleAWTPopupMenu extends AccessibleAWTMenu + { + protected AccessibleAWTPopupMenu() + { + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.POPUP_MENU; + } + + } + + /** + * Gets the AccessibleContext associated with this <code>PopupMenu</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTPopupMenu(); + return accessibleContext; + } + +} // class PopupMenu + diff --git a/libjava/classpath/java/awt/PrintGraphics.java b/libjava/classpath/java/awt/PrintGraphics.java new file mode 100644 index 0000000..e7f8577 --- /dev/null +++ b/libjava/classpath/java/awt/PrintGraphics.java @@ -0,0 +1,57 @@ +/* PrintGraphics.java -- a print graphics context + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This interface allows the originating print job to be obtained. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @since 1.0 + * @status updated to 1.4 + */ +public interface PrintGraphics +{ + /** + * Returns the <code>PrintJob</code> that this object is being + * managed by. + * + * @return the print job for this object + */ + PrintJob getPrintJob(); +} // interface PrintGraphics diff --git a/libjava/classpath/java/awt/PrintJob.java b/libjava/classpath/java/awt/PrintJob.java new file mode 100644 index 0000000..62aa8b1 --- /dev/null +++ b/libjava/classpath/java/awt/PrintJob.java @@ -0,0 +1,104 @@ +/* PrintJob.java -- A print job class + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.util.Properties; + +/** + * This abstract class represents a print job. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see Toolkit#getPrintJob(Frame, String, Properties) + * @since 1.0 + * @status updated to 1.4 + */ +public abstract class PrintJob +{ + /** + * Create a new PrintJob. + */ + public PrintJob() + { + } + + /** + * Returns a graphics context suitable for rendering the next page. The + * return must also implement {@link PrintGraphics}. + * + * @return a graphics context for printing the next page + */ + public abstract Graphics getGraphics(); + + /** + * Returns the dimension of the page in pixels. The resolution will be + * chosen to be similar to the on screen image. + * + * @return the page dimensions + */ + public abstract Dimension getPageDimension(); + + /** + * Returns the resolution of the page in pixels per inch. Note that this is + * not necessarily the printer's resolution. + * + * @return the resolution of the page in pixels per inch + */ + public abstract int getPageResolution(); + + /** + * Tests whether or not the last page will be printed first. + * + * @return true if the last page prints first + */ + public abstract boolean lastPageFirst(); + + /** + * Informs the print job that printing is complete or should be aborted. + */ + public abstract void end(); + + /** + * This method explicitly ends the print job in the event the job + * becomes un-referenced without the application having done so. + */ + public void finalize() + { + end(); + } +} // class PrintJob diff --git a/libjava/classpath/java/awt/Rectangle.java b/libjava/classpath/java/awt/Rectangle.java new file mode 100644 index 0000000..0f21d49 --- /dev/null +++ b/libjava/classpath/java/awt/Rectangle.java @@ -0,0 +1,749 @@ +/* Rectangle.java -- represents a graphics rectangle + Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.geom.Rectangle2D; +import java.io.Serializable; + +/** + * This class represents a rectangle and all the interesting things you + * might want to do with it. Note that the coordinate system uses + * the origin (0,0) as the top left of the screen, with the x and y + * values increasing as they move to the right and down respectively. + * + * <p>It is valid for a rectangle to have negative width or height; but it + * is considered to have no area or internal points. Therefore, the behavior + * in methods like <code>contains</code> or <code>intersects</code> is + * undefined unless the rectangle has positive width and height. + * + * <p>There are some public fields; if you mess with them in an inconsistent + * manner, it is your own fault when you get NullPointerException, + * ArrayIndexOutOfBoundsException, or invalid results. Also, this class is + * not threadsafe. + * + * @author Warren Levy (warrenl@cygnus.com) + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status updated to 1.4 + */ +public class Rectangle extends Rectangle2D implements Shape, Serializable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -4345857070255674764L; + + /** + * The X coordinate of the top-left corner of the rectangle. + * + * @see #setLocation(int, int) + * @see #getLocation() + * @serial the x coordinate + */ + public int x; + + /** + * The Y coordinate of the top-left corner of the rectangle. + * + * @see #setLocation(int, int) + * @see #getLocation() + * @serial the y coordinate + */ + public int y; + + /** + * The width of the rectangle. + * + * @see #setSize(int, int) + * @see #getSize() + * @serial + */ + public int width; + + /** + * The height of the rectangle. + * + * @see #setSize(int, int) + * @see #getSize() + * @serial + */ + public int height; + + /** + * Initializes a new instance of <code>Rectangle</code> with a top + * left corner at (0,0) and a width and height of 0. + */ + public Rectangle() + { + } + + /** + * Initializes a new instance of <code>Rectangle</code> from the + * coordinates of the specified rectangle. + * + * @param r the rectangle to copy from + * @throws NullPointerException if r is null + * @since 1.1 + */ + public Rectangle(Rectangle r) + { + x = r.x; + y = r.y; + width = r.width; + height = r.height; + } + + /** + * Initializes a new instance of <code>Rectangle</code> from the specified + * inputs. + * + * @param x the X coordinate of the top left corner + * @param y the Y coordinate of the top left corner + * @param width the width of the rectangle + * @param height the height of the rectangle + */ + public Rectangle(int x, int y, int width, int height) + { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + /** + * Initializes a new instance of <code>Rectangle</code> with the specified + * width and height. The upper left corner of the rectangle will be at + * the origin (0,0). + * + * @param width the width of the rectangle + * @param height the height of the rectange + */ + public Rectangle(int width, int height) + { + this.width = width; + this.height = height; + } + + /** + * Initializes a new instance of <code>Rectangle</code> with a top-left + * corner represented by the specified point and the width and height + * represented by the specified dimension. + * + * @param p the upper left corner of the rectangle + * @param d the width and height of the rectangle + * @throws NullPointerException if p or d is null + */ + public Rectangle(Point p, Dimension d) + { + x = p.x; + y = p.y; + width = d.width; + height = d.height; + } + + /** + * Initializes a new instance of <code>Rectangle</code> with a top left + * corner at the specified point and a width and height of zero. + * + * @param p the upper left corner of the rectangle + */ + public Rectangle(Point p) + { + x = p.x; + y = p.y; + } + + /** + * Initializes a new instance of <code>Rectangle</code> with an + * upper left corner at the origin (0,0) and a width and height represented + * by the specified dimension. + * + * @param d the width and height of the rectangle + */ + public Rectangle(Dimension d) + { + width = d.width; + height = d.height; + } + + /** + * Get the X coordinate of the upper-left corner. + * + * @return the value of x, as a double + */ + public double getX() + { + return x; + } + + /** + * Get the Y coordinate of the upper-left corner. + * + * @return the value of y, as a double + */ + public double getY() + { + return y; + } + + /** + * Get the width of the rectangle. + * + * @return the value of width, as a double + */ + public double getWidth() + { + return width; + } + + /** + * Get the height of the rectangle. + * + * @return the value of height, as a double + */ + public double getHeight() + { + return height; + } + + /** + * Returns the bounds of this rectangle. A pretty useless method, as this + * is already a rectangle; it is included to mimic the + * <code>getBounds</code> method in Component. + * + * @return a copy of this rectangle + * @see #setBounds(Rectangle) + * @since 1.1 + */ + public Rectangle getBounds() + { + return new Rectangle(this); + } + + /** + * Returns the high-precision bounds of this rectangle. A pretty useless + * method, as this is already a rectangle. + * + * @return a copy of this rectangle + * @see #setBounds(Rectangle) + * @since 1.2 + */ + public Rectangle2D getBounds2D() + { + return new Rectangle(x, y, width, height); + } + + /** + * Updates this rectangle to match the dimensions of the specified + * rectangle. + * + * @param r the rectangle to update from + * @throws NullPointerException if r is null + * @see #setBounds(int, int, int, int) + * @since 1.1 + */ + public void setBounds(Rectangle r) + { + setBounds (r.x, r.y, r.width, r.height); + } + + /** + * Updates this rectangle to have the specified dimensions. + * + * @param x the new X coordinate of the upper left hand corner + * @param y the new Y coordinate of the upper left hand corner + * @param width the new width of this rectangle + * @param height the new height of this rectangle + * @since 1.1 + */ + public void setBounds(int x, int y, int width, int height) + { + reshape (x, y, width, height); + } + + /** + * Updates this rectangle to have the specified dimensions, as rounded to + * integers. + * + * @param x the new X coordinate of the upper left hand corner + * @param y the new Y coordinate of the upper left hand corner + * @param width the new width of this rectangle + * @param height the new height of this rectangle + * @since 1.2 + */ + public void setRect(double x, double y, double width, double height) + { + this.x = (int) x; + this.y = (int) y; + this.width = (int) width; + this.height = (int) height; + } + + /** + * Updates this rectangle to have the specified dimensions. + * + * @param x the new X coordinate of the upper left hand corner + * @param y the new Y coordinate of the upper left hand corner + * @param width the new width of this rectangle + * @param height the new height of this rectangle + * @deprecated use {@link #setBounds(int, int, int, int)} instead + */ + public void reshape(int x, int y, int width, int height) + { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + /** + * Returns the location of this rectangle, which is the coordinates of + * its upper left corner. + * + * @return the point where this rectangle is located + * @see #setLocation(Point) + * @since 1.1 + */ + public Point getLocation() + { + return new Point(x,y); + } + + /** + * Moves the location of this rectangle by setting its upper left + * corner to the specified point. + * + * @param p the point to move the rectangle to + * @throws NullPointerException if p is null + * @see #getLocation() + * @since 1.1 + */ + public void setLocation(Point p) + { + setLocation (p.x, p.y); + } + + /** + * Moves the location of this rectangle by setting its upper left + * corner to the specified coordinates. + * + * @param x the new X coordinate for this rectangle + * @param y the new Y coordinate for this rectangle + * @since 1.1 + */ + public void setLocation(int x, int y) + { + move (x, y); + } + + /** + * Moves the location of this rectangle by setting its upper left + * corner to the specified coordinates. + * + * @param x the new X coordinate for this rectangle + * @param y the new Y coordinate for this rectangle + * @deprecated use {@link #setLocation(int, int)} instead + */ + public void move(int x, int y) + { + this.x = x; + this.y = y; + } + + /** + * Translate the location of this rectangle by the given amounts. + * + * @param dx the x distance to move by + * @param dy the y distance to move by + * @see #setLocation(int, int) + */ + public void translate(int dx, int dy) + { + x += dx; + y += dy; + } + + /** + * Returns the size of this rectangle. + * + * @return the size of this rectangle + * @see #setSize(Dimension) + * @since 1.1 + */ + public Dimension getSize() + { + return new Dimension(width, height); + } + + /** + * Sets the size of this rectangle based on the specified dimensions. + * + * @param d the new dimensions of the rectangle + * @throws NullPointerException if d is null + * @see #getSize() + * @since 1.1 + */ + public void setSize(Dimension d) + { + setSize (d.width, d.height); + } + + /** + * Sets the size of this rectangle based on the specified dimensions. + * + * @param width the new width of the rectangle + * @param height the new height of the rectangle + * @since 1.1 + */ + public void setSize(int width, int height) + { + resize (width, height); + } + + /** + * Sets the size of this rectangle based on the specified dimensions. + * + * @param width the new width of the rectangle + * @param height the new height of the rectangle + * @deprecated use {@link #setSize(int, int)} instead + */ + public void resize(int width, int height) + { + this.width = width; + this.height = height; + } + + /** + * Tests whether or not the specified point is inside this rectangle. + * According to the contract of Shape, a point on the border is in only if + * it has an adjacent point inside the rectangle in either the increasing + * x or y direction. + * + * @param p the point to test + * @return true if the point is inside the rectangle + * @throws NullPointerException if p is null + * @see #contains(int, int) + * @since 1.1 + */ + public boolean contains(Point p) + { + return contains (p.x, p.y); + } + + /** + * Tests whether or not the specified point is inside this rectangle. + * According to the contract of Shape, a point on the border is in only if + * it has an adjacent point inside the rectangle in either the increasing + * x or y direction. + * + * @param x the X coordinate of the point to test + * @param y the Y coordinate of the point to test + * @return true if the point is inside the rectangle + * @since 1.1 + */ + public boolean contains(int x, int y) + { + return inside (x, y); + } + + /** + * Checks whether all points in the given rectangle are contained in this + * rectangle. + * + * @param r the rectangle to check + * @return true if r is contained in this rectangle + * @throws NullPointerException if r is null + * @see #contains(int, int, int, int) + * @since 1.1 + */ + public boolean contains(Rectangle r) + { + return contains (r.x, r.y, r.width, r.height); + } + + /** + * Checks whether all points in the given rectangle are contained in this + * rectangle. + * + * @param x the x coordinate of the rectangle to check + * @param y the y coordinate of the rectangle to check + * @param w the width of the rectangle to check + * @param h the height of the rectangle to check + * @return true if the parameters are contained in this rectangle + * @since 1.1 + */ + public boolean contains(int x, int y, int w, int h) + { + return width > 0 && height > 0 && w > 0 && h > 0 + && x >= this.x && x + w <= this.x + this.width + && y >= this.y && y + h <= this.y + this.height; + } + + /** + * Tests whether or not the specified point is inside this rectangle. + * + * @param x the X coordinate of the point to test + * @param y the Y coordinate of the point to test + * @return true if the point is inside the rectangle + * @deprecated use {@link #contains(int, int)} instead + */ + public boolean inside(int x, int y) + { + return width > 0 && height > 0 + && x >= this.x && x < this.x + width + && y >= this.y && y < this.y + height; + } + + /** + * Tests whether or not the specified rectangle intersects this rectangle. + * This means the two rectangles share at least one internal point. + * + * @param r the rectangle to test against + * @return true if the specified rectangle intersects this one + * @throws NullPointerException if r is null + * @since 1.2 + */ + public boolean intersects(Rectangle r) + { + return r.width > 0 && r.height > 0 && width > 0 && height > 0 + && r.x < x + width && r.x + r.width > x + && r.y < y + height && r.y + r.height > y; + } + + /** + * Determines the rectangle which is formed by the intersection of this + * rectangle with the specified rectangle. If the two do not intersect, + * an empty rectangle will be returned (meaning the width and/or height + * will be non-positive). + * + * @param r the rectange to calculate the intersection with + * @return a new rectangle bounding the intersection + * @throws NullPointerException if r is null + */ + public Rectangle intersection(Rectangle r) + { + Rectangle res = new Rectangle(); + intersect(this, r, res); + return res; + } + + /** + * Returns the smallest rectangle that contains both this rectangle + * and the specified rectangle. + * + * @param r the rectangle to compute the union with + * @return the smallest rectangle containing both rectangles + * @throws NullPointerException if r is null + */ + public Rectangle union(Rectangle r) + { + Rectangle res = new Rectangle(); + union(this, r, res); + return res; + } + + /** + * Modifies this rectangle so that it represents the smallest rectangle + * that contains both the existing rectangle and the specified point. + * However, if the point falls on one of the two borders which are not + * inside the rectangle, a subsequent call to <code>contains</code> may + * return false. + * + * @param x the X coordinate of the point to add to this rectangle + * @param y the Y coordinate of the point to add to this rectangle + */ + public void add(int x, int y) + { + add((double) x, (double) y); + } + + /** + * Modifies this rectangle so that it represents the smallest rectangle + * that contains both the existing rectangle and the specified point. + * However, if the point falls on one of the two borders which are not + * inside the rectangle, a subsequent call to <code>contains</code> may + * return false. + * + * @param p the point to add to this rectangle + * @throws NullPointerException if p is null + */ + public void add(Point p) + { + add((double) p.x, (double) p.y); + } + + /** + * Modifies this rectangle so that it represents the smallest rectangle + * that contains both the existing rectangle and the specified rectangle. + * + * @param r the rectangle to add to this rectangle + * @throws NullPointerException if r is null + * @see #union(Rectangle) + */ + public void add(Rectangle r) + { + union(this, r, this); + } + + /** + * Expands the rectangle by the specified amount. The horizontal + * and vertical expansion values are applied both to the X,Y coordinate + * of this rectangle, and its width and height. Thus the width and + * height will increase by 2h and 2v accordingly. + * + * @param h the horizontal expansion value + * @param v the vertical expansion value + */ + public void grow(int h, int v) + { + x -= h; + y -= v; + width += h + h; + height += v + v; + } + + /** + * Tests whether or not this rectangle is empty. An empty rectangle + * has a non-positive width or height. + * + * @return true if the rectangle is empty + */ + public boolean isEmpty() + { + return width <= 0 || height <= 0; + } + + /** + * Determine where the point lies with respect to this rectangle. The + * result will be the binary OR of the appropriate bit masks. + * + * @param x the x coordinate to check + * @param y the y coordinate to check + * @return the binary OR of the result + * @see #OUT_LEFT + * @see #OUT_TOP + * @see #OUT_RIGHT + * @see #OUT_BOTTOM + * @since 1.2 + */ + public int outcode(double x, double y) + { + int result = 0; + if (width <= 0) + result |= OUT_LEFT | OUT_RIGHT; + else if (x < this.x) + result |= OUT_LEFT; + else if (x > this.x + width) + result |= OUT_RIGHT; + if (height <= 0) + result |= OUT_BOTTOM | OUT_TOP; + else if (y < this.y) // Remember that +y heads top-to-bottom. + result |= OUT_TOP; + else if (y > this.y + height) + result |= OUT_BOTTOM; + return result; + } + + /** + * Determines the rectangle which is formed by the intersection of this + * rectangle with the specified rectangle. If the two do not intersect, + * an empty rectangle will be returned (meaning the width and/or height + * will be non-positive). + * + * @param r the rectange to calculate the intersection with + * @return a new rectangle bounding the intersection + * @throws NullPointerException if r is null + * @since 1.2 + */ + public Rectangle2D createIntersection(Rectangle2D r) + { + // Favor runtime type of other rectangle. + Rectangle2D res = r.getBounds2D(); + intersect(this, r, res); + return res; + } + + /** + * Returns the smallest rectangle that contains both this rectangle + * and the specified rectangle. + * + * @param r the rectangle to compute the union with + * @return the smallest rectangle containing both rectangles + * @throws NullPointerException if r is null + * @since 1.2 + */ + public Rectangle2D createUnion(Rectangle2D r) + { + // Favor runtime type of other rectangle. + Rectangle2D res = r.getBounds2D(); + union(this, r, res); + return res; + } + + /** + * Tests this rectangle for equality against the specified object. This + * will be true if an only if the specified object is an instance of + * Rectangle2D with the same coordinates and dimensions. + * + * @param obj the object to test against for equality + * @return true if the specified object is equal to this one + */ + public boolean equals(Object obj) + { + if (! (obj instanceof Rectangle2D)) + return false; + Rectangle2D r = (Rectangle2D) obj; + return r.getX() == x && r.getY() == y + && r.getWidth() == width && r.getHeight() == height; + } + + /** + * Returns a string representation of this rectangle. This is in the form + * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + * + ",height=" + height + ']'</code>. + * + * @return a string representation of this rectangle + */ + public String toString() + { + return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + + ",height=" + height + ']'; + } +} // class Rectangle diff --git a/libjava/classpath/java/awt/RenderingHints.java b/libjava/classpath/java/awt/RenderingHints.java new file mode 100644 index 0000000..0e1db72 --- /dev/null +++ b/libjava/classpath/java/awt/RenderingHints.java @@ -0,0 +1,803 @@ +/* RenderingHints.java -- + Copyright (C) 2000, 2001, 2002, 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +/** + * A collection of (key, value) items that provide 'hints' for the + * {@link java.awt.Graphics2D} rendering pipeline. Because these + * items are hints only, they may be ignored by a particular + * {@link java.awt.Graphics2D} implementation. + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + * @author Eric Blake (ebb9@email.byu.edu) + */ +public class RenderingHints implements Map, Cloneable +{ + /** + * The base class used to represent keys. + */ + public abstract static class Key + { + private final int key; + + /** + * Creates a new key. + * + * @param privateKey the private key. + */ + protected Key(int privateKey) + { + key = privateKey; + } + + /** + * Returns <code>true</code> if the specified value is compatible with + * this key, and <code>false</code> otherwise. + * + * @param value the value (<code>null</code> permitted). + * + * @return A boolean. + */ + public abstract boolean isCompatibleValue(Object value); + + /** + * Returns the private key for this instance. + * + * @return The private key. + */ + protected final int intKey() + { + return key; + } + + /** + * Returns a hash code for the key. + * + * @return A hash code. + */ + public final int hashCode() + { + return System.identityHashCode(this); + } + + /** + * Checks this key for equality with an arbitrary object. + * + * @param other the object (<code>null</code> permitted) + * + * @return A boolean. + */ + public final boolean equals(Object other) + { + return this == other; + } + } // class Key + + private static final class KeyImpl extends Key + { + final String description; + final Object v1; + final Object v2; + final Object v3; + + KeyImpl(int privateKey, String description, + Object v1, Object v2, Object v3) + { + super(privateKey); + this.description = description; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + /** + * Returns <code>true</code> if the specified value is compatible with + * this key, and <code>false</code> otherwise. + * + * @param value the value (<code>null</code> permitted). + * + * @return A boolean. + */ + public boolean isCompatibleValue(Object value) + { + return value == v1 || value == v2 || value == v3; + } + + /** + * Returns a string representation of the key. + * + * @return A string. + */ + public String toString() + { + return description; + } + } // class KeyImpl + + private HashMap hintMap = new HashMap(); + + /** + * A key for the 'antialiasing' hint. Permitted values are: + * <p> + * <table> + * <tr> + * <td>{@link #VALUE_ANTIALIAS_OFF}</td> + * <td>Render without antialiasing (better speed).</td> + * </tr> + * <tr> + * <td>{@link #VALUE_ANTIALIAS_ON}</td> + * <td>Render with antialiasing (better quality).</td> + * </tr> + * <tr> + * <td>{@link #VALUE_ANTIALIAS_DEFAULT}</td> + * <td>Use the default value for antialiasing.</td> + * </tr> + * </table> + */ + public static final Key KEY_ANTIALIASING; + + /** + * This value is for use with the {@link #KEY_ANTIALIASING} key. + */ + public static final Object VALUE_ANTIALIAS_ON + = "Antialiased rendering mode"; + + /** + * This value is for use with the {@link #KEY_ANTIALIASING} key. + */ + public static final Object VALUE_ANTIALIAS_OFF + = "Nonantialiased rendering mode"; + + /** + * This value is for use with the {@link #KEY_ANTIALIASING} key. + */ + public static final Object VALUE_ANTIALIAS_DEFAULT + = "Default antialiasing rendering mode"; + + /** + * A key for the 'rendering' hint. Permitted values are: + * <p> + * <table> + * <tr> + * <td>{@link #VALUE_RENDER_SPEED}</td> + * <td>Prefer speed over quality when rendering.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_RENDER_QUALITY}</td> + * <td>Prefer quality over speed when rendering.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_RENDER_DEFAULT}</td> + * <td>Use the default value for quality vs. speed when rendering.</td> + * </tr> + * </table> + */ + public static final Key KEY_RENDERING; + + /** + * This value is for use with the {@link #KEY_RENDERING} key. + */ + public static final Object VALUE_RENDER_SPEED + = "Fastest rendering methods"; + + /** + * This value is for use with the {@link #KEY_RENDERING} key. + */ + public static final Object VALUE_RENDER_QUALITY + = "Highest quality rendering methods"; + + /** + * This value is for use with the {@link #KEY_RENDERING} key. + */ + public static final Object VALUE_RENDER_DEFAULT + = "Default rendering methods"; + + /** + * A key for the 'dithering' hint. Permitted values are: + * <p> + * <table> + * <tr> + * <td>{@link #VALUE_DITHER_DISABLE}</td> + * <td>Disable dithering.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_DITHER_ENABLE}</td> + * <td>Enable dithering.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_DITHER_DEFAULT}</td> + * <td>Use the default value for dithering.</td> + * </tr> + * </table> + */ + public static final Key KEY_DITHERING; + + /** + * This value is for use with the {@link #KEY_DITHERING} key. + */ + public static final Object VALUE_DITHER_DISABLE + = "Nondithered rendering mode"; + + /** + * This value is for use with the {@link #KEY_DITHERING} key. + */ + public static final Object VALUE_DITHER_ENABLE + = "Dithered rendering mode"; + + /** + * This value is for use with the {@link #KEY_DITHERING} key. + */ + public static final Object VALUE_DITHER_DEFAULT + = "Default dithering mode"; + + /** + * A key for the 'text antialiasing' hint. Permitted values are: + * <p> + * <table> + * <tr> + * <td>{@link #VALUE_TEXT_ANTIALIAS_ON}</td> + * <td>Render text with antialiasing (better quality usually).</td> + * </tr> + * <tr> + * <td>{@link #VALUE_TEXT_ANTIALIAS_OFF}</td> + * <td>Render test without antialiasing (better speed).</td> + * </tr> + * <tr> + * <td>{@link #VALUE_TEXT_ANTIALIAS_DEFAULT}</td> + * <td>Use the default value for text antialiasing.</td> + * </tr> + * </table> + */ + public static final Key KEY_TEXT_ANTIALIASING; + + /** + * This value is for use with the {@link #KEY_TEXT_ANTIALIASING} key. + */ + public static final Object VALUE_TEXT_ANTIALIAS_ON + = "Antialiased text mode"; + + /** + * This value is for use with the {@link #KEY_TEXT_ANTIALIASING} key. + */ + public static final Object VALUE_TEXT_ANTIALIAS_OFF + = "Nonantialiased text mode"; + + /** + * This value is for use with the {@link #KEY_TEXT_ANTIALIASING} key. + */ + public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT + = "Default antialiasing text mode"; + + /** + * A key for the 'fractional metrics' hint. Permitted values are: + * <p> + * <table> + * <tr> + * <td>{@link #VALUE_FRACTIONALMETRICS_OFF}</td> + * <td>Render text with fractional metrics off.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_FRACTIONALMETRICS_ON}</td> + * <td>Render text with fractional metrics on.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_FRACTIONALMETRICS_DEFAULT}</td> + * <td>Use the default value for fractional metrics.</td> + * </tr> + * </table> + */ + public static final Key KEY_FRACTIONALMETRICS; + + /** + * This value is for use with the {@link #KEY_FRACTIONALMETRICS} key. + */ + public static final Object VALUE_FRACTIONALMETRICS_OFF + = "Integer text metrics mode"; + + /** + * This value is for use with the {@link #KEY_FRACTIONALMETRICS} key. + */ + public static final Object VALUE_FRACTIONALMETRICS_ON + = "Fractional text metrics mode"; + + /** + * This value is for use with the {@link #KEY_FRACTIONALMETRICS} key. + */ + public static final Object VALUE_FRACTIONALMETRICS_DEFAULT + = "Default fractional text metrics mode"; + + /** + * A key for the 'interpolation' hint. Permitted values are: + * <p> + * <table> + * <tr> + * <td>{@link #VALUE_INTERPOLATION_NEAREST_NEIGHBOR}</td> + * <td>Use nearest neighbour interpolation.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_INTERPOLATION_BILINEAR}</td> + * <td>Use bilinear interpolation.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_INTERPOLATION_BICUBIC}</td> + * <td>Use bicubic interpolation.</td> + * </tr> + * </table> + */ + public static final Key KEY_INTERPOLATION; + + /** + * This value is for use with the {@link #KEY_INTERPOLATION} key. + */ + public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR + = "Nearest Neighbor image interpolation mode"; + + /** + * This value is for use with the {@link #KEY_INTERPOLATION} key. + */ + public static final Object VALUE_INTERPOLATION_BILINEAR + = "Bilinear image interpolation mode"; + + /** + * This value is for use with the {@link #KEY_INTERPOLATION} key. + */ + public static final Object VALUE_INTERPOLATION_BICUBIC + = "Bicubic image interpolation mode"; + + /** + * A key for the 'alpha interpolation' hint. Permitted values are: + * <p> + * <table> + * <tr> + * <td>{@link #VALUE_ALPHA_INTERPOLATION_SPEED}</td> + * <td>Prefer speed over quality.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_ALPHA_INTERPOLATION_QUALITY}</td> + * <td>Prefer quality over speed.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_ALPHA_INTERPOLATION_DEFAULT}</td> + * <td>Use the default setting.</td> + * </tr> + * </table> + */ + public static final Key KEY_ALPHA_INTERPOLATION; + + /** + * This value is for use with the {@link #KEY_ALPHA_INTERPOLATION} key. + */ + public static final Object VALUE_ALPHA_INTERPOLATION_SPEED + = "Fastest alpha blending methods"; + + /** + * This value is for use with the {@link #KEY_ALPHA_INTERPOLATION} key. + */ + public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY + = "Highest quality alpha blending methods"; + + /** + * This value is for use with the {@link #KEY_ALPHA_INTERPOLATION} key. + */ + public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT + = "Default alpha blending methods"; + + /** + * A key for the 'color rendering' hint. Permitted values are: + * <p> + * <table> + * <tr> + * <td>{@link #VALUE_COLOR_RENDER_SPEED}</td> + * <td>Prefer speed over quality.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_COLOR_RENDER_QUALITY}</td> + * <td>Prefer quality over speed.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_COLOR_RENDER_DEFAULT}</td> + * <td>Use the default setting.</td> + * </tr> + * </table> + */ + public static final Key KEY_COLOR_RENDERING; + + /** + * This value is for use with the {@link #KEY_COLOR_RENDERING} key. + */ + public static final Object VALUE_COLOR_RENDER_SPEED + = "Fastest color rendering mode"; + + /** + * This value is for use with the {@link #KEY_COLOR_RENDERING} key. + */ + public static final Object VALUE_COLOR_RENDER_QUALITY + = "Highest quality color rendering mode"; + + /** + * This value is for use with the {@link #KEY_COLOR_RENDERING} key. + */ + public static final Object VALUE_COLOR_RENDER_DEFAULT + = "Default color rendering mode"; + + /** + * A key for the 'stroke control' hint. Permitted values are: + * <p> + * <table> + * <tr> + * <td>{@link #VALUE_STROKE_DEFAULT}</td> + * <td>Use the default setting.</td> + * </tr> + * <tr> + * <td>{@link #VALUE_STROKE_NORMALIZE}</td> + * <td>XXX</td> + * </tr> + * <tr> + * <td>{@link #VALUE_STROKE_PURE}</td> + * <td>XXX</td> + * </tr> + * </table> + */ + public static final Key KEY_STROKE_CONTROL; + + /** + * This value is for use with the {@link #KEY_STROKE_CONTROL} key. + */ + public static final Object VALUE_STROKE_DEFAULT + = "Default stroke normalization"; + + /** + * This value is for use with the {@link #KEY_STROKE_CONTROL} key. + */ + public static final Object VALUE_STROKE_NORMALIZE + = "Normalize strokes for consistent rendering"; + + /** + * This value is for use with the {@link #KEY_STROKE_CONTROL} key. + */ + public static final Object VALUE_STROKE_PURE + = "Pure stroke conversion for accurate paths"; + + static + { + KEY_ANTIALIASING = new KeyImpl(1, "Global antialiasing enable key", + VALUE_ANTIALIAS_ON, + VALUE_ANTIALIAS_OFF, + VALUE_ANTIALIAS_DEFAULT); + KEY_RENDERING = new KeyImpl(2, "Global rendering quality key", + VALUE_RENDER_SPEED, + VALUE_RENDER_QUALITY, + VALUE_RENDER_DEFAULT); + KEY_DITHERING = new KeyImpl(3, "Dithering quality key", + VALUE_DITHER_DISABLE, + VALUE_DITHER_ENABLE, + VALUE_DITHER_DEFAULT); + KEY_TEXT_ANTIALIASING + = new KeyImpl(4, "Text-specific antialiasing enable key", + VALUE_TEXT_ANTIALIAS_ON, + VALUE_TEXT_ANTIALIAS_OFF, + VALUE_TEXT_ANTIALIAS_DEFAULT); + KEY_FRACTIONALMETRICS = new KeyImpl(5, "Fractional metrics enable key", + VALUE_FRACTIONALMETRICS_OFF, + VALUE_FRACTIONALMETRICS_ON, + VALUE_FRACTIONALMETRICS_DEFAULT); + KEY_INTERPOLATION = new KeyImpl(6, "Image interpolation method key", + VALUE_INTERPOLATION_NEAREST_NEIGHBOR, + VALUE_INTERPOLATION_BILINEAR, + VALUE_INTERPOLATION_BICUBIC); + KEY_ALPHA_INTERPOLATION + = new KeyImpl(7, "Alpha blending interpolation method key", + VALUE_ALPHA_INTERPOLATION_SPEED, + VALUE_ALPHA_INTERPOLATION_QUALITY, + VALUE_ALPHA_INTERPOLATION_DEFAULT); + KEY_COLOR_RENDERING = new KeyImpl(8, "Color rendering quality key", + VALUE_COLOR_RENDER_SPEED, + VALUE_COLOR_RENDER_QUALITY, + VALUE_COLOR_RENDER_DEFAULT); + KEY_STROKE_CONTROL = new KeyImpl(9, "Stroke normalization control key", + VALUE_STROKE_DEFAULT, + VALUE_STROKE_NORMALIZE, + VALUE_STROKE_PURE); + } + + /** + * Creates a new collection of hints containing all the (key, value) pairs + * in the specified map. + * + * @param init a map containing a collection of hints (<code>null</code> + * permitted). + */ + public RenderingHints(Map init) + { + if (init != null) + putAll(init); + } + + /** + * Creates a new collection containing a single (key, value) pair. + * + * @param key the key. + * @param value the value. + */ + public RenderingHints(Key key, Object value) + { + put(key, value); + } + + /** + * Returns the number of hints in the collection. + * + * @return The number of hints. + */ + public int size() + { + return hintMap.size(); + } + + /** + * Returns <code>true</code> if there are no hints in the collection, + * and <code>false</code> otherwise. + * + * @return A boolean. + */ + public boolean isEmpty() + { + return hintMap.isEmpty(); + } + + /** + * Returns <code>true</code> if the collection of hints contains the + * specified key, and <code>false</code> otherwise. + * + * @param key the key (<code>null</code> not permitted). + * + * @return A boolean. + * + * @throws NullPointerException if <code>key</code> is <code>null</code>. + * @throws ClassCastException if <code>key</code> is not a {@link Key}. + */ + public boolean containsKey(Object key) + { + if (key == null) + throw new NullPointerException(); + // don't remove the cast, it is necessary to throw the required exception + return hintMap.containsKey((Key) key); + } + + /** + * Returns <code>true</code> if the collection of hints contains the + * specified value, and <code>false</code> otherwise. + * + * @param value the value. + * + * @return A boolean. + */ + public boolean containsValue(Object value) + { + return hintMap.containsValue(value); + } + + /** + * Returns the value associated with the specified key, or <code>null</code> + * if there is no value defined for the key. + * + * @param key the key (<code>null</code> permitted). + * + * @return The value (possibly <code>null</code>). + * + * @throws ClassCastException if <code>key</code> is not a {@link Key}. + * + * @see #containsKey(Object) + */ + public Object get(Object key) + { + // don't remove the cast, it is necessary to throw the required exception + return hintMap.get((Key) key); + } + + /** + * Adds a (key, value) pair to the collection of hints (if the + * collection already contains the specified key, then the + * value is updated). + * + * @param key the key. + * @param value the value. + * + * @return the previous value of the key or <code>null</code> if the key + * didn't have a value yet. + */ + public Object put(Object key, Object value) + { + if (key == null || value == null) + throw new NullPointerException(); + if (! ((Key) key).isCompatibleValue(value)) + throw new IllegalArgumentException(); + return hintMap.put(key, value); + } + + /** + * Adds all the hints from a collection to this collection. + * + * @param hints the hint collection. + */ + public void add(RenderingHints hints) + { + hintMap.putAll(hints); + } + + /** + * Clears all the hints from this collection. + */ + public void clear() + { + hintMap.clear(); + } + + /** + * Removes a hint from the collection. + * + * @param key the key. + * + * @return The value that was associated with the key, or <code>null</code> if + * the key was not part of the collection + * + * @throws ClassCastException if the key is not a subclass of + * {@link RenderingHints.Key}. + */ + public Object remove(Object key) + { + // don't remove the (Key) cast, it is necessary to throw the exception + // required by the spec + return hintMap.remove((Key) key); + } + + /** + * Adds a collection of (key, value) pairs to the collection. + * + * @param m a map containing (key, value) items. + * + * @throws ClassCastException if the map contains a key that is not + * a subclass of {@link RenderingHints.Key}. + * @throws IllegalArgumentException if the map contains a value that is + * not compatible with its key. + */ + public void putAll(Map m) + { + // preprocess map to generate appropriate exceptions + Iterator iterator = m.keySet().iterator(); + while (iterator.hasNext()) + { + Key key = (Key) iterator.next(); + if (!key.isCompatibleValue(m.get(key))) + throw new IllegalArgumentException(); + } + // map is OK, update + hintMap.putAll(m); + } + + /** + * Returns a set containing the keys from this collection. + * + * @return A set of keys. + */ + public Set keySet() + { + return hintMap.keySet(); + } + + /** + * Returns a collection of the values from this hint collection. The + * collection is backed by the <code>RenderingHints</code> instance, + * so updates to one will affect the other. + * + * @return A collection of values. + */ + public Collection values() + { + return hintMap.values(); + } + + /** + * Returns a set of entries from the collection. + * + * @return A set of entries. + */ + public Set entrySet() + { + return Collections.unmodifiableSet(hintMap.entrySet()); + } + + /** + * Checks this collection for equality with an arbitrary object. + * + * @param o the object (<code>null</code> permitted) + * + * @return A boolean. + */ + public boolean equals(Object o) + { + return hintMap.equals(o); + } + + /** + * Returns a hash code for the collection of hints. + * + * @return A hash code. + */ + public int hashCode() + { + return hintMap.hashCode(); + } + + /** + * Creates a clone of this instance. + * + * @return A clone. + */ + public Object clone() + { + try + { + RenderingHints copy = (RenderingHints) super.clone(); + copy.hintMap = (HashMap) hintMap.clone(); + return copy; + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // Impossible + } + } + + /** + * Returns a string representation of this instance. + * + * @return A string. + */ + public String toString() + { + return hintMap.toString(); + } +} // class RenderingHints diff --git a/libjava/classpath/java/awt/Robot.java b/libjava/classpath/java/awt/Robot.java new file mode 100644 index 0000000..485a14e --- /dev/null +++ b/libjava/classpath/java/awt/Robot.java @@ -0,0 +1,423 @@ +/* Robot.java -- a native input event generator + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import gnu.java.awt.ClasspathToolkit; + +import java.lang.reflect.InvocationTargetException; +import java.awt.event.InputEvent; +import java.awt.image.BufferedImage; +import java.awt.peer.RobotPeer; + +/** + * The Robot class is used to simulate user interaction with graphical + * programs. It can generate native windowing system input events and + * retrieve image data from the current screen. Robot is used to test + * the AWT and Swing library implementations; it can also be used to + * create self-running demo programs. + * + * Since Robot generates native windowing system events, rather than + * simply inserting {@link AWTEvent}s on the AWT event queue, its use + * is not restricted to Java programs. It can be used to + * programatically drive any graphical application. + * + * This implementation requires an X server that supports the XTest + * extension. + * + * @author Thomas Fitzsimmons (fitzsim@redhat.com) + * + * @since 1.3 + */ +public class Robot +{ + private boolean waitForIdle; + private int autoDelay; + private RobotPeer peer; + + /** + * Construct a Robot object that operates on the default screen. + * + * @exception AWTException if GraphicsEnvironment.isHeadless() + * returns true or if the X server does not support the XTest + * extension + * @exception SecurityException if createRobot permission is not + * granted + */ + public Robot () throws AWTException + { + if (GraphicsEnvironment.isHeadless ()) + throw new AWTException ("Robot: headless graphics environment"); + + SecurityManager sm = System.getSecurityManager (); + if (sm != null) + sm.checkPermission (new AWTPermission ("createRobot")); + + ClasspathToolkit tk = (ClasspathToolkit) Toolkit.getDefaultToolkit (); + + // createRobot will throw AWTException if XTest is not supported. + peer = tk.createRobot (GraphicsEnvironment.getLocalGraphicsEnvironment () + .getDefaultScreenDevice ()); + } + + /** + * Construct a Robot object that operates on the specified screen. + * + * @exception AWTException if GraphicsEnvironment.isHeadless() + * returns true or if the X server does not support the XTest + * extension + * @exception IllegalArgumentException if screen is not a screen + * GraphicsDevice + * @exception SecurityException if createRobot permission is not + * granted + */ + public Robot (GraphicsDevice screen) throws AWTException + { + if (GraphicsEnvironment.isHeadless ()) + throw new AWTException ("Robot: headless graphics environment"); + + if (screen.getType () != GraphicsDevice.TYPE_RASTER_SCREEN) + throw new IllegalArgumentException ("Robot: graphics" + + " device is not a screen"); + + SecurityManager sm = System.getSecurityManager (); + if (sm != null) + sm.checkPermission (new AWTPermission ("createRobot")); + + ClasspathToolkit tk = (ClasspathToolkit) Toolkit.getDefaultToolkit (); + + // createRobot will throw AWTException if XTest is not supported. + peer = tk.createRobot (screen); + } + + /** + * Move the mouse pointer to absolute coordinates (x, y). + * + * @param x the destination x coordinate + * @param y the destination y coordinate + */ + public void mouseMove(int x, int y) + { + peer.mouseMove (x, y); + + if (waitForIdle) + waitForIdle (); + + if (autoDelay > 0) + delay (autoDelay); + } + + /** + * Press one or more mouse buttons. + * + * @param buttons the buttons to press; a bitmask of one or more of + * these {@link InputEvent} fields: + * + * <ul> + * <li>BUTTON1_MASK</li> + * <li>BUTTON2_MASK</li> + * <li>BUTTON3_MASK</li> + * </ul> + * + * @exception IllegalArgumentException if the button mask is invalid + */ + public void mousePress (int buttons) + { + if ((buttons & InputEvent.BUTTON1_MASK) == 0 + && (buttons & InputEvent.BUTTON2_MASK) == 0 + && (buttons & InputEvent.BUTTON3_MASK) == 0) + throw new IllegalArgumentException ("Robot: mousePress:" + + " invalid button mask"); + + peer.mousePress (buttons); + + if (waitForIdle) + waitForIdle (); + + if (autoDelay > 0) + delay (autoDelay); + } + + /** + * Release one or more mouse buttons. + * + * @param buttons the buttons to release; a bitmask of one or more + * of these {@link InputEvent} fields: + * + * <ul> + * <li>BUTTON1_MASK</li> + * <li>BUTTON2_MASK</li> + * <li>BUTTON3_MASK</li> + * </ul> + * + * @exception IllegalArgumentException if the button mask is invalid + */ + public void mouseRelease(int buttons) + { + if ((buttons & InputEvent.BUTTON1_MASK) == 0 + && (buttons & InputEvent.BUTTON2_MASK) == 0 + && (buttons & InputEvent.BUTTON3_MASK) == 0) + throw new IllegalArgumentException ("Robot: mouseRelease:" + + " invalid button mask"); + + peer.mouseRelease (buttons); + + if (waitForIdle) + waitForIdle (); + + if (autoDelay > 0) + delay (autoDelay); + } + + /** + * Rotate the mouse scroll wheel. + * + * @param wheelAmt number of steps to rotate mouse wheel. negative + * to rotate wheel up (away from the user), positive to rotate wheel + * down (toward the user). + * + * @since 1.4 + */ + public void mouseWheel (int wheelAmt) + { + peer.mouseWheel (wheelAmt); + + if (waitForIdle) + waitForIdle (); + + if (autoDelay > 0) + delay (autoDelay); + } + + /** + * Press a key. + * + * @param keycode key to press, a {@link java.awt.event.KeyEvent} VK_ constant + * + * @exception IllegalArgumentException if keycode is not a valid key + */ + public void keyPress (int keycode) + { + peer.keyPress (keycode); + + if (waitForIdle) + waitForIdle (); + + if (autoDelay > 0) + delay (autoDelay); + } + + /** + * Release a key. + * + * @param keycode key to release, a {@link java.awt.event.KeyEvent} VK_ + * constant + * + * @exception IllegalArgumentException if keycode is not a valid key + */ + public void keyRelease (int keycode) + { + peer.keyRelease (keycode); + + if (waitForIdle) + waitForIdle (); + + if (autoDelay > 0) + delay (autoDelay); + } + + /** + * Return the color of the pixel at the given screen coordinates. + * + * @param x the x coordinate of the pixel + * @param y the y coordinate of the pixel + * + * @return the Color of the pixel at screen coodinates <code>(x, y)</code> + */ + public Color getPixelColor (int x, int y) + { + return new Color (peer.getRGBPixel (x, y)); + } + + /** + * Create an image containing pixels read from the screen. The + * image does not include the mouse pointer. + * + * @param screenRect the rectangle of pixels to capture, in screen + * coordinates + * + * @return a BufferedImage containing the requested pixels + * + * @exception IllegalArgumentException if requested width and height + * are not both greater than zero + * @exception SecurityException if readDisplayPixels permission is + * not granted + */ + public BufferedImage createScreenCapture (Rectangle screenRect) + { + if (screenRect.width <= 0) + throw new IllegalArgumentException ("Robot: capture width is <= 0"); + + if (screenRect.height <= 0) + throw new IllegalArgumentException ("Robot: capture height is <= 0"); + + SecurityManager sm = System.getSecurityManager (); + if (sm != null) + sm.checkPermission (new AWTPermission ("readDisplayPixels")); + + int[] pixels = peer.getRGBPixels (screenRect); + + BufferedImage bufferedImage = + new BufferedImage (screenRect.width, screenRect.height, + BufferedImage.TYPE_INT_ARGB); + + bufferedImage.setRGB (0, 0, screenRect.width, screenRect.height, + pixels, 0, screenRect.width); + + return bufferedImage; + } + + /** + * Check if this Robot automatically calls {@link #waitForIdle()} after + * generating an event. + * + * @return true if waitForIdle is automatically called + */ + public boolean isAutoWaitForIdle () + { + return waitForIdle; + } + + /** + * Set whether or not this Robot automatically calls {@link + * #waitForIdle()} after generating an event. + * + * @param isOn true if waitForIdle should be called automatically + */ + public void setAutoWaitForIdle (boolean isOn) + { + waitForIdle = isOn; + } + + /** + * Retrieve the length of time this Robot sleeps after generating an + * event. + * + * @return the length of time in milliseconds + */ + public int getAutoDelay () + { + return autoDelay; + } + + /** + * Set the length of time this Robot sleeps after generating an + * event. + * + * @param ms the length of time in milliseconds + * + * @exception IllegalArgumentException if ms is not between 0 and + * 60,000 milliseconds inclusive + */ + public void setAutoDelay (int ms) + { + if (ms <= 0 || ms >= 60000) + throw new IllegalArgumentException ("Robot: delay length out-of-bounds"); + + autoDelay = ms; + } + + /** + * Sleep for a specified length of time. + * + * @param ms the length of time in milliseconds + * + * @exception IllegalArgumentException if ms is not between 0 and + * 60,000 milliseconds inclusive + */ + public void delay (int ms) + { + if (ms < 0 || ms > 60000) + throw new IllegalArgumentException ("Robot: delay length out-of-bounds"); + + try + { + Thread.sleep (ms); + } + catch (InterruptedException e) + { + System.err.println ("Robot: delay interrupted"); + } + } + + /** + * Wait until all events currently on the event queue have been + * dispatched. + */ + public void waitForIdle () + { + if (EventQueue.isDispatchThread ()) + throw new IllegalThreadStateException ("Robot: waitForIdle called from " + + "the event dispatch thread"); + + try + { + EventQueue.invokeAndWait (new Runnable () { public void run () { } }); + } + catch (InterruptedException e) + { + System.err.println ("Robot: waitForIdle interrupted"); + } + catch (InvocationTargetException e) + { + System.err.println ("Robot: waitForIdle cannot invoke target"); + } + } + + /** + * Return a string representation of this Robot. + * + * @return a string representation + */ + public String toString () + { + return getClass ().getName () + + "[ autoDelay = " + autoDelay + ", autoWaitForIdle = " + + waitForIdle + " ]"; + } +} diff --git a/libjava/classpath/java/awt/ScrollPane.java b/libjava/classpath/java/awt/ScrollPane.java new file mode 100644 index 0000000..b3ecc59 --- /dev/null +++ b/libjava/classpath/java/awt/ScrollPane.java @@ -0,0 +1,615 @@ +/* ScrollPane.java -- Scrolling window + Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.MouseEvent; +import java.awt.peer.ComponentPeer; +import java.awt.peer.ScrollPanePeer; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; + +/** + * This widget provides a scrollable region that allows a single + * subcomponent to be viewed through a smaller window. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class ScrollPane extends Container implements Accessible +{ + +/* + * Static Variables + */ + +/** + * Constant indicating that scrollbars are created as needed in this + * windows. + */ +public static final int SCROLLBARS_AS_NEEDED = 0; + +/** + * Constant indicating that scrollbars are always displayed in this + * window. + */ +public static final int SCROLLBARS_ALWAYS = 1; + +/** + * Constant indicating that scrollbars are never displayed in this window. + */ +public static final int SCROLLBARS_NEVER = 2; + +// Serialization constant +private static final long serialVersionUID = 7956609840827222915L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial The horizontal scrollbar for this window. The methods + * <code>setMinimum()</code>, <code>setMaximum</code>, and + * <code>setVisibleAmount</code> must not be called on this scrollbar. + */ +private ScrollPaneAdjustable hAdjustable; + +/** + * @serial The vertical scrollbar for this window. The methods + * <code>setMinimum()</code>, <code>setMaximum</code>, and + * <code>setVisibleAmount</code> must not be called on this scrollbar. + */ +private ScrollPaneAdjustable vAdjustable; + +/** + * @serial Indicates when scrollbars are displayed in this window, will + * be one of the constants from this class. + */ +private int scrollbarDisplayPolicy; + +// Current scroll position +private Point scrollPosition = new Point(0, 0); + +private boolean wheelScrollingEnabled; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>ScrollPane</code> with a default + * scrollbar policy of <code>SCROLLBARS_AS_NEEDED</code>. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +ScrollPane() +{ + this(SCROLLBARS_AS_NEEDED); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>ScrollPane</code> with the + * specified scrollbar policy. + * + * @param scrollbarDisplayPolicy When to display scrollbars, which must + * be one of the constants defined in this class. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ +public +ScrollPane(int scrollbarDisplayPolicy) +{ + if (GraphicsEnvironment.isHeadless ()) + throw new HeadlessException (); + + this.scrollbarDisplayPolicy = scrollbarDisplayPolicy; + + if (scrollbarDisplayPolicy != SCROLLBARS_ALWAYS + && scrollbarDisplayPolicy != SCROLLBARS_AS_NEEDED + && scrollbarDisplayPolicy != SCROLLBARS_NEVER) + throw new IllegalArgumentException("Bad scrollbarDisplayPolicy: " + + scrollbarDisplayPolicy); + + if (scrollbarDisplayPolicy != SCROLLBARS_NEVER) + { + hAdjustable = new ScrollPaneAdjustable (this, Scrollbar.HORIZONTAL); + vAdjustable = new ScrollPaneAdjustable (this, Scrollbar.VERTICAL); + } + + wheelScrollingEnabled = true; + + // Default size. + setSize(100,100); +} + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * Returns the current scrollbar display policy. + * + * @return The current scrollbar display policy. + */ +public int +getScrollbarDisplayPolicy() +{ + return(scrollbarDisplayPolicy); +} + +/*************************************************************************/ + +/** + * Returns the horizontal scrollbar for this object. If the scrollbar + * display policy is set to <code>SCROLLBARS_NEVER</code> then this + * will be <code>null</code>. + * + * @return The horizontal scrollbar for this window. + */ +public Adjustable +getHAdjustable() +{ + return(hAdjustable); +} + +/*************************************************************************/ + +/** + * Returns the vertical scrollbar for this object. If the scrollbar + * display policy is set to <code>SCROLLBARS_NEVER</code> then this + * will be <code>null</code>. + * + * @return The horizontal scrollbar for this window. + */ +public Adjustable +getVAdjustable() +{ + return(vAdjustable); +} + +/*************************************************************************/ + +/** + * Returns the current viewport size. The viewport is the region of + * this object's window where the child is actually displayed. + * + * @return The viewport size. + */ +public Dimension getViewportSize () +{ + Dimension viewsize = getSize (); + Insets insets = getInsets (); + + viewsize.width -= (insets.left + insets.right); + viewsize.height -= (insets.top + insets.bottom); + + Component[] list = getComponents(); + if ((list == null) || (list.length <= 0)) + return viewsize; + + Dimension dim = list[0].getPreferredSize(); + + if (dim.width <= 0 && dim.height <= 0) + return viewsize; + + int vScrollbarWidth = getVScrollbarWidth (); + int hScrollbarHeight = getHScrollbarHeight (); + + if (scrollbarDisplayPolicy == SCROLLBARS_ALWAYS) + { + viewsize.width -= vScrollbarWidth; + viewsize.height -= hScrollbarHeight; + return viewsize; + } + + if (scrollbarDisplayPolicy == SCROLLBARS_NEVER) + return viewsize; + + // The scroll policy is SCROLLBARS_AS_NEEDED, so we need to see if + // either scrollbar is needed. + + // Assume we don't need either scrollbar. + boolean mayNeedVertical = false; + boolean mayNeedHorizontal = false; + + boolean needVertical = false; + boolean needHorizontal = false; + + // Check if we need vertical scrollbars. If we do, then we need to + // subtract the width of the vertical scrollbar from the viewport's + // width. + if (dim.height > viewsize.height) + needVertical = true; + else if (dim.height > (viewsize.height - hScrollbarHeight)) + // This is tricky. In this case the child is tall enough that its + // bottom edge would be covered by a horizontal scrollbar, if one + // were present. This means that if there's a horizontal + // scrollbar then we need a vertical scrollbar. + mayNeedVertical = true; + + if (dim.width > viewsize.width) + needHorizontal = true; + else if (dim.width > (viewsize.width - vScrollbarWidth)) + mayNeedHorizontal = true; + + if (needVertical && mayNeedHorizontal) + needHorizontal = true; + + if (needHorizontal && mayNeedVertical) + needVertical = true; + + if (needHorizontal) + viewsize.height -= hScrollbarHeight; + + if (needVertical) + viewsize.width -= vScrollbarWidth; + + return viewsize; +} + +/*************************************************************************/ + +/** + * Returns the height of a horizontal scrollbar. + * + * @return The height of a horizontal scrollbar. + */ +public int +getHScrollbarHeight() +{ + ScrollPanePeer spp = (ScrollPanePeer)getPeer(); + if (spp != null) + return(spp.getHScrollbarHeight()); + else + return(0); // FIXME: What to do here? +} + +/*************************************************************************/ + +/** + * Returns the width of a vertical scrollbar. + * + * @return The width of a vertical scrollbar. + */ +public int +getVScrollbarWidth() +{ + ScrollPanePeer spp = (ScrollPanePeer)getPeer(); + if (spp != null) + return(spp.getVScrollbarWidth()); + else + return(0); // FIXME: What to do here? +} + +/*************************************************************************/ + +/** + * Returns the current scroll position of the viewport. + * + * @return The current scroll position of the viewport. + */ +public Point +getScrollPosition() +{ + int x = 0; + int y = 0; + + Adjustable v = getVAdjustable(); + Adjustable h = getHAdjustable(); + + if (v != null) + y = v.getValue(); + if (h != null) + x = h.getValue(); + + return(new Point(x, y)); +} + +/*************************************************************************/ + +/** + * Sets the scroll position to the specified value. + * + * @param scrollPosition The new scrollPosition. + * + * @exception IllegalArgumentException If the specified value is outside + * the legal scrolling range. + */ +public void +setScrollPosition(Point scrollPosition) throws IllegalArgumentException +{ + setScrollPosition(scrollPosition.x, scrollPosition.y); +} + +/*************************************************************************/ + +/** + * Sets the scroll position to the specified value. + * + * @param x The new X coordinate of the scroll position. + * @param y The new Y coordinate of the scroll position. + * + * @exception IllegalArgumentException If the specified value is outside + * the legal scrolling range. + */ +public void +setScrollPosition(int x, int y) +{ + Adjustable h = getHAdjustable(); + Adjustable v = getVAdjustable(); + + if (h != null) + h.setValue(x); + if (v != null) + v.setValue(y); + + ScrollPanePeer spp = (ScrollPanePeer)getPeer(); + if (spp != null) + spp.setScrollPosition(x, y); +} + +/*************************************************************************/ + +/** + * Notifies this object that it should create its native peer. + */ +public void +addNotify() +{ + if (!isDisplayable ()) + return; + + setPeer((ComponentPeer)getToolkit().createScrollPane(this)); + super.addNotify(); + + Component[] list = getComponents(); + if (list != null && list.length > 0 && ! (list[0] instanceof Panel)) + { + Panel panel = new Panel(); + panel.setLayout(new BorderLayout()); + panel.add(list[0], BorderLayout.CENTER); + add(panel); + } +} + +/*************************************************************************/ + +/** + * Notifies this object that it should destroy its native peers. + */ +public void +removeNotify() +{ + super.removeNotify(); +} + +/*************************************************************************/ + +/** + * Adds the specified child component to this container. A + * <code>ScrollPane</code> can have at most one child, so if a second + * one is added, then first one is removed. + * + * @param component The component to add to this container. + * @param constraints A list of layout constraints for this object. + * @param index The index at which to add the child, which is ignored + * in this implementation. + */ + protected final void addImpl (Component component, Object constraints, + int index) +{ + Component[] list = getComponents(); + if ((list != null) && (list.length > 0)) + remove(list[0]); + + super.addImpl(component, constraints, -1); + + doLayout(); +} + +/*************************************************************************/ + +/** + * Lays out this component. This consists of resizing the sole child + * component to its perferred size. + */ +public void +doLayout() +{ + layout (); +} + +/*************************************************************************/ + +/** + * Lays out this component. This consists of resizing the sole child + * component to its perferred size. + * + * @deprecated This method is deprecated in favor of + * <code>doLayout()</code>. + */ +public void +layout() +{ + Component[] list = getComponents (); + if ((list != null) && (list.length > 0)) + { + Dimension dim = list[0].getPreferredSize (); + Dimension vp = getViewportSize (); + + if (dim.width < vp.width) + dim.width = vp.width; + + if (dim.height < vp.height) + dim.height = vp.height; + + ScrollPanePeer peer = (ScrollPanePeer) getPeer (); + if (peer != null) + peer.childResized (dim.width, dim.height); + + list[0].setSize (dim); + + Point p = getScrollPosition (); + if (p.x > dim.width) + p.x = dim.width; + if (p.y > dim.height) + p.y = dim.height; + + setScrollPosition (p); + } +} + +/*************************************************************************/ + +/** + * This method overrides its superclass method to ensure no layout + * manager is set for this container. <code>ScrollPane</code>'s do + * not have layout managers. + * + * @param layoutManager Ignored + */ +public final void +setLayout(LayoutManager layoutManager) +{ + return; +} + +/*************************************************************************/ + +/** + * Prints all of the components in this container. + * + * @param graphics The desired graphics context for printing. + */ +public void +printComponents(Graphics graphics) +{ + super.printComponents(graphics); +} + +/*************************************************************************/ + +/** + * Returns a debug string for this object. + * + * @return A debug string for this object. + */ +public String +paramString() +{ + Insets insets = getInsets(); + return getName() + "," + + getX() + "," + + getY() + "," + + getWidth() + "x" + getHeight() + "," + + "ScrollPosition=(" + scrollPosition.getX() + "," + + scrollPosition.getY() + ")," + + "Insets=(" + insets.top + "," + + insets.left + "," + + insets.bottom + "," + + insets.right + ")," + + "ScrollbarDisplayPolicy=" + getScrollbarDisplayPolicy() + "," + + "wheelScrollingEnabled=" + isWheelScrollingEnabled(); +} + + /** + * Tells whether or not an event is enabled. + * + * @since 1.4 + */ + protected boolean eventTypeEnabled (int type) + { + if (type == MouseEvent.MOUSE_WHEEL) + return wheelScrollingEnabled; + + return super.eventTypeEnabled (type); + } + + /** + * Tells whether or not wheel scrolling is enabled. + * + * @since 1.4 + */ + public boolean isWheelScrollingEnabled () + { + return wheelScrollingEnabled; + } + + /** + * Enables/disables wheel scrolling. + * + * @since 1.4 + */ + public void setWheelScrollingEnabled (boolean enable) + { + wheelScrollingEnabled = enable; + } + + protected class AccessibleAWTScrollPane extends AccessibleAWTContainer + { + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.SCROLL_PANE; + } + } + + /** + * Gets the AccessibleContext associated with this <code>ScrollPane</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTScrollPane(); + return accessibleContext; + } +} // class ScrollPane + diff --git a/libjava/classpath/java/awt/ScrollPaneAdjustable.java b/libjava/classpath/java/awt/ScrollPaneAdjustable.java new file mode 100644 index 0000000..cfca19b --- /dev/null +++ b/libjava/classpath/java/awt/ScrollPaneAdjustable.java @@ -0,0 +1,200 @@ +/* ScrollPaneAdjustable.java -- Scrollbars for a ScrollPane + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.AdjustmentListener; +import java.io.Serializable; + +/** + * Need this class since the serialization spec for ScrollPane + * uses it. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @since 1.4 + */ +public class ScrollPaneAdjustable + implements Adjustable, Serializable +{ + private static final long serialVersionUID = -3359745691033257079L; + + ScrollPane sp; + int orientation; + int value; + int minimum; + int maximum; + int visibleAmount; + int unitIncrement = 1; + int blockIncrement = 1; + AdjustmentListener adjustmentListener; + + private transient boolean valueIsAdjusting = false; + + ScrollPaneAdjustable (ScrollPane sp, int orientation) + { + this.sp = sp; + this.orientation = orientation; + } + + ScrollPaneAdjustable (ScrollPane sp, int orientation, int value, int minimum, + int maximum, int visibleAmount, int unitIncrement, + int blockIncrement) + { + this.sp = sp; + this.orientation = orientation; + this.value = value; + this.minimum = minimum; + this.maximum = maximum; + this.visibleAmount = visibleAmount; + this.unitIncrement = unitIncrement; + this.blockIncrement = blockIncrement; + } + + public void addAdjustmentListener (AdjustmentListener listener) + { + AWTEventMulticaster.add (adjustmentListener, listener); + } + + public void removeAdjustmentListener (AdjustmentListener listener) + { + AWTEventMulticaster.remove (adjustmentListener, listener); + } + + public AdjustmentListener[] getAdjustmentListeners () + { + return (AdjustmentListener[]) AWTEventMulticaster.getListeners + (adjustmentListener, AdjustmentListener.class); + } + + public int getBlockIncrement () + { + return blockIncrement; + } + + public int getMaximum () + { + return maximum; + } + + public int getMinimum () + { + return minimum; + } + + public int getOrientation () + { + return orientation; + } + + public int getUnitIncrement () + { + return unitIncrement; + } + + public int getValue () + { + return value; + } + + public int getVisibleAmount () + { + return visibleAmount; + } + + public void setBlockIncrement (int blockIncrement) + { + this.blockIncrement = blockIncrement; + } + + public void setMaximum (int maximum) + { + this.maximum = maximum; + } + + public void setMinimum (int minimum) + { + this.minimum = minimum; + } + + public void setUnitIncrement (int unitIncrement) + { + this.unitIncrement = unitIncrement; + } + + public void setValue (int value) + { + this.value = value; + + if (value < minimum) + minimum = value; + + if (value > maximum) + maximum = value; + } + + public void setVisibleAmount (int visibleAmount) + { + this.visibleAmount = visibleAmount; + } + + public String paramString () + { + throw new Error ("not implemented"); + } + + /** + * Returns true if the value is in the process of changing. + * + * @since 1.4 + */ + public boolean getValueIsAdjusting () + { + return valueIsAdjusting; + } + + /** + * Sets the value of valueIsAdjusting. + * + * @since 1.4 + */ + public void setValueIsAdjusting (boolean valueIsAdjusting) + { + this.valueIsAdjusting = valueIsAdjusting; + } +} // class ScrollPaneAdjustable + diff --git a/libjava/classpath/java/awt/Scrollbar.java b/libjava/classpath/java/awt/Scrollbar.java new file mode 100644 index 0000000..6e506c7 --- /dev/null +++ b/libjava/classpath/java/awt/Scrollbar.java @@ -0,0 +1,825 @@ +/* Scrollbar.java -- AWT Scrollbar widget + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.awt.peer.ScrollbarPeer; +import java.util.EventListener; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleValue; + +/** + * This class implements a scrollbar widget. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Tom Tromey (tromey@cygnus.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ +public class Scrollbar extends Component implements Accessible, Adjustable +{ + // FIXME: Serialization readObject/writeObject + + /** + * Constant indicating that a scrollbar is horizontal. + */ + public static final int HORIZONTAL = 0; + + /** + * Constant indicating that a scrollbar is vertical. + */ + public static final int VERTICAL = 1; + + /** + * Serialization Constant. + */ + private static final long serialVersionUID = 8451667562882310543L; + + /** + * @serial The amount by which the value of the scrollbar is changed + * when incrementing in line mode. + */ + private int lineIncrement; + + /** + * @serial The amount by which the value of the scrollbar is changed + * when incrementing in page mode. + */ + private int pageIncrement; + + /** + * @serial The maximum value for this scrollbar + */ + private int maximum; + + /** + * @serial The minimum value for this scrollbar + */ + private int minimum; + + /** + * @serial The orientation of this scrollbar, which will be either + * the <code>HORIZONTAL</code> or <code>VERTICAL</code> constant + * from this class. + */ + private int orientation; + + /** + * @serial The current value of this scrollbar. + */ + private int value; + + /** + * @serial The width of the scrollbar's thumb, which is relative + * to the minimum and maximum value of the scrollbar. + */ + private int visibleAmount; + + /** + * List of AdjustmentListener's. + */ + private AdjustmentListener adjustment_listeners; + + /** + * true if the scrollbar is adjusting, false otherwise. + */ + private transient boolean valueIsAdjusting = false; + + /** + * The number used to generate the name returned by getName. + */ + private static transient long next_scrollbar_number; + + /** + * Initializes a new instance of <code>Scrollbar</code> with a + * vertical orientation and default values for all other parameters. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true, + */ + public Scrollbar() + { + this(VERTICAL); + } + + /** + * Initializes a new instance of <code>Scrollbar</code> with the + * specified orientation and default values for all other parameters. + * The orientation must be either the constant <code>HORIZONTAL</code> or + * <code>VERTICAL</code> from this class. An incorrect value will throw + * an exception. + * + * @param orientation The orientation of this scrollbar. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true, + * @exception IllegalArgumentException If the orientation value is not valid. + */ + public Scrollbar(int orientation) throws IllegalArgumentException + { + this(orientation, 0, 10, 0, 100); + } + + /** + * Initializes a new instance of <code>Scrollbar</code> with the + * specified parameters. The orientation must be either the constant + * <code>HORIZONTAL</code> or <code>VERTICAL</code>. An incorrect value + * will throw an exception. Inconsistent values for other parameters + * are silently corrected to valid values. + * + * @param orientation The orientation of this scrollbar. + * @param value The initial value of the scrollbar. + * @param visibleAmount The width of the scrollbar thumb. + * @param minimum The minimum value of the scrollbar. + * @param maximum The maximum value of the scrollbar. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true, + * @exception IllegalArgumentException If the orientation value is not valid. + */ + public Scrollbar(int orientation, int value, int visibleAmount, int minimum, + int maximum) throws IllegalArgumentException + { + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException(); + + if ((orientation != HORIZONTAL) && (orientation != VERTICAL)) + throw new IllegalArgumentException("Bad orientation value: " + + orientation); + + this.orientation = orientation; + + setValues(value, visibleAmount, minimum, maximum); + + // Default is 1 according to online docs. + lineIncrement = 1; + + // Default is 10 according to javadocs. + pageIncrement = 10; + } + + /** + * Returns the orientation constant for this object. + * + * @return The orientation constant for this object. + */ + public int getOrientation() + { + return orientation; + } + + /** + * Sets the orientation of this scrollbar to the specified value. This + * value must be either the constant <code>HORIZONTAL</code> or + * <code>VERTICAL</code> from this class or an exception will be thrown. + * + * @param orientation The new orientation value. + * + * @exception IllegalArgumentException If the orientation value is not valid. + */ + public void setOrientation(int orientation) + { + if ((orientation != HORIZONTAL) && (orientation != VERTICAL)) + throw new IllegalArgumentException("Bad orientation value: " + + orientation); + + // FIXME: Communicate to peer? Or must this be called before peer creation? + this.orientation = orientation; + } + + /** + * Returns the current value for this scrollbar. + * + * @return The current value for this scrollbar. + */ + public int getValue() + { + return value; + } + + /** + * Sets the current value for this scrollbar to the specified value. + * If this is inconsistent with the minimum and maximum values for this + * scrollbar, the value is silently adjusted. + * + * @param value The new value for this scrollbar. + */ + public void setValue(int value) + { + setValues(value, visibleAmount, minimum, maximum); + } + + /** + * Returns the maximum value for this scrollbar. + * + * @return The maximum value for this scrollbar. + */ + public int getMaximum() + { + return maximum; + } + + /** + * Sets the maximum value for this scrollbar to the specified value. + * If the value is less than the current minimum value, it is silent + * set to equal the minimum value. + * + * @param maximum The new maximum value for this scrollbar. + */ + public void setMaximum(int maximum) + { + setValues(value, visibleAmount, minimum, maximum); + } + + /** + * Returns the minimum value for this scrollbar. + * + * @return The minimum value for this scrollbar. + */ + public int getMinimum() + { + return minimum; + } + + /** + * Sets the minimum value for this scrollbar to the specified value. If + * this is not consistent with the current value and maximum, it is + * silently adjusted to be consistent. + * + * @param minimum The new minimum value for this scrollbar. + */ + public void setMinimum(int minimum) + { + setValues(value, visibleAmount, minimum, maximum); + } + + /** + * Returns the width of the scrollbar's thumb, in units relative to the + * maximum and minimum value of the scrollbar. + * + * @return The width of the scrollbar's thumb. + */ + public int getVisibleAmount() + { + return getVisible(); + } + + /** + * Returns the width of the scrollbar's thumb, in units relative to the + * maximum and minimum value of the scrollbar. + * + * @return The width of the scrollbar's thumb. + * + * @deprecated This method is deprecated in favor of + * <code>getVisibleAmount()</code>. + */ + public int getVisible() + { + return visibleAmount; + } + + /** + * Sets the width of the scrollbar's thumb, in units relative to the + * maximum and minimum value of the scrollbar. + * + * @param visibleAmount The new visible amount value of the scrollbar. + */ + public void setVisibleAmount(int visibleAmount) + { + setValues(value, visibleAmount, minimum, maximum); + } + + /** + * Sets the current value, visible amount, minimum, and maximum for this + * scrollbar. These values are adjusted to be internally consistent + * if necessary. + * + * @param value The new value for this scrollbar. + * @param visibleAmount The new visible amount for this scrollbar. + * @param minimum The new minimum value for this scrollbar. + * @param maximum The new maximum value for this scrollbar. + */ + public synchronized void setValues(int value, int visibleAmount, + int minimum, int maximum) + { + if (maximum < minimum) + maximum = minimum; + + if (value < minimum) + value = minimum; + + if (value > maximum) + value = maximum; + + if (visibleAmount > maximum - minimum) + visibleAmount = maximum - minimum; + + ScrollbarPeer peer = (ScrollbarPeer) getPeer(); + if (peer != null + && (this.value != value || this.visibleAmount != visibleAmount + || this.minimum != minimum || this.maximum != maximum)) + peer.setValues(value, visibleAmount, minimum, maximum); + + this.value = value; + this.visibleAmount = visibleAmount; + this.minimum = minimum; + this.maximum = maximum; + + int range = maximum - minimum; + if (lineIncrement > range) + { + if (range == 0) + lineIncrement = 1; + else + lineIncrement = range; + + if (peer != null) + peer.setLineIncrement(lineIncrement); + } + + if (pageIncrement > range) + { + if (range == 0) + pageIncrement = 1; + else + pageIncrement = range; + + if (peer != null) + peer.setPageIncrement(pageIncrement); + } + } + + /** + * Returns the value added or subtracted when the user activates the scrollbar + * scroll by a "unit" amount. + * + * @return The unit increment value. + */ + public int getUnitIncrement() + { + return getLineIncrement(); + } + + /** + * Returns the value added or subtracted when the user selects the scrollbar + * scroll by a "unit" amount control. + * + * @return The unit increment value. + * + * @deprecated This method is deprecated in favor of + * <code>getUnitIncrement()</code>. + */ + public int getLineIncrement() + { + return lineIncrement; + } + + /** + * Sets the value added or subtracted to the scrollbar value when the + * user selects the scroll by a "unit" amount control. + * + * @param unitIncrement The new unit increment amount. + */ + public synchronized void setUnitIncrement(int unitIncrement) + { + setLineIncrement(unitIncrement); + } + + /** + * Sets the value added or subtracted to the scrollbar value when the + * user selects the scroll by a "unit" amount control. + * + * @param lineIncrement The new unit increment amount. + * + * @deprecated This method is deprecated in favor of + * <code>setUnitIncrement()</code>. + */ + public void setLineIncrement(int lineIncrement) + { + if (lineIncrement < 0) + throw new IllegalArgumentException("Unit increment less than zero."); + + int range = maximum - minimum; + if (lineIncrement > range) + { + if (range == 0) + lineIncrement = 1; + else + lineIncrement = range; + } + + if (lineIncrement == this.lineIncrement) + return; + + this.lineIncrement = lineIncrement; + + ScrollbarPeer peer = (ScrollbarPeer) getPeer(); + if (peer != null) + peer.setLineIncrement(this.lineIncrement); + } + + /** + * Returns the value added or subtracted when the user activates the scrollbar + * scroll by a "block" amount. + * + * @return The block increment value. + */ + public int getBlockIncrement() + { + return getPageIncrement(); + } + + /** + * Returns the value added or subtracted when the user selects the scrollbar + * scroll by a "block" amount control. + * + * @return The block increment value. + * + * @deprecated This method is deprecated in favor of + * <code>getBlockIncrement()</code>. + */ + public int getPageIncrement() + { + return pageIncrement; + } + + /** + * Sets the value added or subtracted to the scrollbar value when the + * user selects the scroll by a "block" amount control. + * + * @param blockIncrement The new block increment amount. + */ + public synchronized void setBlockIncrement(int blockIncrement) + { + setPageIncrement(blockIncrement); + } + + /** + * Sets the value added or subtracted to the scrollbar value when the + * user selects the scroll by a "block" amount control. + * + * @param pageIncrement The new block increment amount. + * + * @deprecated This method is deprecated in favor of + * <code>setBlockIncrement()</code>. + */ + public void setPageIncrement(int pageIncrement) + { + if (pageIncrement < 0) + throw new IllegalArgumentException("Block increment less than zero."); + + int range = maximum - minimum; + if (pageIncrement > range) + { + if (range == 0) + pageIncrement = 1; + else + pageIncrement = range; + } + + if (pageIncrement == this.pageIncrement) + return; + + this.pageIncrement = pageIncrement; + + ScrollbarPeer peer = (ScrollbarPeer) getPeer(); + if (peer != null) + peer.setPageIncrement(this.pageIncrement); + } + + /** + * Notifies this object to create its native peer. + */ + public synchronized void addNotify() + { + if (peer == null) + peer = getToolkit().createScrollbar(this); + super.addNotify(); + } + + /** + * Adds a new adjustment listener to the list of registered listeners + * for this object. + * + * @param listener The listener to add. + */ + public synchronized void addAdjustmentListener(AdjustmentListener listener) + { + adjustment_listeners = AWTEventMulticaster.add(adjustment_listeners, + listener); + enableEvents(AWTEvent.ADJUSTMENT_EVENT_MASK); + } + + /** + * Removes the specified listener from the list of registered listeners + * for this object. + * + * @param listener The listener to remove. + */ + public synchronized void removeAdjustmentListener(AdjustmentListener listener) + { + adjustment_listeners = AWTEventMulticaster.remove(adjustment_listeners, + listener); + } + + /** + * Processes events for this scrollbar. It does this by calling + * <code>processAdjustmentEvent()</code> if the event is an instance of + * <code>AdjustmentEvent</code>, otherwise it calls the superclass to + * process the event. + * + * @param event The event to process. + */ + protected void processEvent(AWTEvent event) + { + if (event instanceof AdjustmentEvent) + processAdjustmentEvent((AdjustmentEvent) event); + else + super.processEvent(event); + } + + /** + * Processes adjustment events for this object by dispatching them to + * any registered listeners. Note that this method will only be called + * if adjustment events are enabled. This will happen automatically if + * any listeners are registered. Otherwise, it can be enabled by a + * call to <code>enableEvents()</code>. + * + * @param event The event to process. + */ + protected void processAdjustmentEvent(AdjustmentEvent event) + { + value = event.getValue(); + if (adjustment_listeners != null) + adjustment_listeners.adjustmentValueChanged(event); + } + + void dispatchEventImpl(AWTEvent e) + { + if (e.id <= AdjustmentEvent.ADJUSTMENT_LAST + && e.id >= AdjustmentEvent.ADJUSTMENT_FIRST + && (adjustment_listeners != null + || (eventMask & AWTEvent.ADJUSTMENT_EVENT_MASK) != 0)) + processEvent(e); + else + super.dispatchEventImpl(e); + } + + /** + * Returns a debugging string for this object. + * + * @return A debugging string for this object. + */ + protected String paramString() + { + return ("value=" + getValue() + ",visibleAmount=" + getVisibleAmount() + + ",minimum=" + getMinimum() + ",maximum=" + getMaximum() + + ",pageIncrement=" + pageIncrement + ",lineIncrement=" + + lineIncrement + ",orientation=" + + (orientation == HORIZONTAL ? "HORIZONTAL" : "VERTICAL") + + super.paramString()); + } + + /** + * Returns an array of all the objects currently registered as FooListeners + * upon this <code>Scrollbar</code>. FooListeners are registered using the + * addFooListener method. + * + * @exception ClassCastException If listenerType doesn't specify a class or + * interface that implements java.util.EventListener. + */ + public EventListener[] getListeners(Class listenerType) + { + if (listenerType == AdjustmentListener.class) + return AWTEventMulticaster.getListeners(adjustment_listeners, + listenerType); + + return super.getListeners(listenerType); + } + + /** + * Returns an array of all registered adjustment listeners. + */ + public AdjustmentListener[] getAdjustmentListeners() + { + return (AdjustmentListener[]) getListeners(AdjustmentListener.class); + } + + /** + * Returns true if the value is in the process of changing. + * + * @since 1.4 + */ + public boolean getValueIsAdjusting() + { + return valueIsAdjusting; + } + + /** + * Sets the value of valueIsAdjusting. + * + * @since 1.4 + */ + public void setValueIsAdjusting(boolean valueIsAdjusting) + { + this.valueIsAdjusting = valueIsAdjusting; + } + + /** + * Generate a unique name for this scroll bar. + * + * @return A unique name for this scroll bar. + */ + String generateName() + { + return "scrollbar" + getUniqueLong(); + } + + private static synchronized long getUniqueLong() + { + return next_scrollbar_number++; + } + + /** + * This class provides accessibility support for the + * scrollbar. + * + * @author Jerry Quinn (jlquinn@optonline.net) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ + protected class AccessibleAWTScrollBar extends AccessibleAWTComponent + implements AccessibleValue + { + /** + * Serialization constant to match JDK 1.5 + */ + private static final long serialVersionUID = -344337268523697807L; + + /** + * Returns the role of this accessible object. + * + * @return the instance of <code>AccessibleRole</code>, + * which describes this object. + * + * @see javax.accessibility.AccessibleRole + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.SCROLL_BAR; + } + + /** + * Returns the state set of this accessible object. + * + * @return a set of <code>AccessibleState</code>s which + * represent the current state of the accessible object. + * + * @see javax.accessibility.AccessibleState + * @see javax.accessibility.AccessibleStateSet + */ + public AccessibleStateSet getAccessibleStateSet() + { + AccessibleStateSet states = super.getAccessibleStateSet(); + if (getOrientation() == HORIZONTAL) + states.add(AccessibleState.HORIZONTAL); + else + states.add(AccessibleState.VERTICAL); + if (getValueIsAdjusting()) + states.add(AccessibleState.BUSY); + return states; + } + + /** + * Returns an implementation of the <code>AccessibleValue</code> + * interface for this accessible object. In this case, the + * current instance is simply returned (with a more appropriate + * type), as it also implements the accessible value as well as + * the context. + * + * @return the accessible value associated with this context. + * + * @see javax.accessibility.AccessibleValue + */ + public AccessibleValue getAccessibleValue() + { + return this; + } + + /** + * Returns the current value of this accessible object. + * In this case, this is the same as the value for + * the scrollbar, wrapped in an <code>Integer</code> + * object. + * + * @return the numeric value of this scrollbar. + * + * @see javax.accessibility.AccessibleValue#getCurrentAccessibleValue() + */ + public Number getCurrentAccessibleValue() + { + return new Integer(getValue()); + } + + /** + * Sets the current value of this accessible object + * to that supplied. In this case, the value of the + * scrollbar is set, and this method always returns + * true. + * + * @param number the new accessible value. + * + * @return true if the value was set. + * + * @see javax.accessibility.AccessibleValue#setCurrentAccessibleValue(java.lang.Number) + */ + public boolean setCurrentAccessibleValue(Number number) + { + setValue(number.intValue()); + return true; + } + + /** + * Returns the minimum acceptable accessible value used + * by this object. In this case, this is the same as + * the minimum value of the scrollbar, wrapped in an + * object. + * + * @return the minimum value of this scrollbar. + * + * @see javax.accessibility.AccessibleValue#getMinimumAccessibleValue() + */ + public Number getMinimumAccessibleValue() + { + return new Integer(getMinimum()); + } + + /** + * Returns the maximum acceptable accessible value used + * by this object. In this case, this is the same as + * the maximum value of the scrollbar, wrapped in an + * object. + * + * @return the maximum value of this scrollbar. + * + * @see javax.accessibility.AccessibleValue#getMaximumAccessibleValue() + */ + public Number getMaximumAccessibleValue() + { + return new Integer(getMaximum()); + } + } + + /** + * Gets the AccessibleContext associated with this <code>Scrollbar</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTScrollBar(); + + return accessibleContext; + } +} diff --git a/libjava/classpath/java/awt/Shape.java b/libjava/classpath/java/awt/Shape.java new file mode 100644 index 0000000..bd8a434 --- /dev/null +++ b/libjava/classpath/java/awt/Shape.java @@ -0,0 +1,203 @@ +/* Shape.java -- the classic Object-Oriented shape interface + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.geom.AffineTransform; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +/** + * This interface represents an abstract shape. The shape is described by + * a {@link PathIterator}, and has callbacks for determining bounding box, + * where points and rectangles lie in relation to the shape, and tracing + * the trajectory. + * + * <p>A point is inside if it is completely inside, or on the boundary and + * adjacent points in the increasing x or y direction are completely inside. + * Unclosed shapes are considered as implicitly closed when performing + * <code>contains</code> or <code>intersects</code>. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see PathIterator + * @see AffineTransform + * @see java.awt.geom.FlatteningPathIterator + * @see java.awt.geom.GeneralPath + * @since 1.0 + * @status updated to 1.4 + */ +public interface Shape +{ + /** + * Returns a <code>Rectange</code> that bounds the shape. There is no + * guarantee that this is the minimum bounding box, particularly if + * the shape overflows the finite integer range of a bound. Generally, + * <code>getBounds2D</code> returns a tighter bound. + * + * @return the shape's bounding box + * @see #getBounds2D() + */ + Rectangle getBounds(); + + /** + * Returns a high precision bounding box of the shape. There is no guarantee + * that this is the minimum bounding box, but at least it never overflows. + * + * @return the shape's bounding box + * @see #getBounds() + * @since 1.2 + */ + Rectangle2D getBounds2D(); + + /** + * Test if the coordinates lie in the shape. + * + * @param x the x coordinate + * @param y the y coordinate + * @return true if (x,y) lies inside the shape + * @since 1.2 + */ + boolean contains(double x, double y); + + /** + * Test if the point lie in the shape. + * + * @param p the high-precision point + * @return true if p lies inside the shape + * @throws NullPointerException if p is null + * @since 1.2 + */ + boolean contains(Point2D p); + + /** + * Test if a high-precision rectangle intersects the shape. This is true + * if any point in the rectangle is in the shape, with the caveat that the + * operation may include high probability estimates when the actual + * calculation is prohibitively expensive. The {@link java.awt.geom.Area} + * class can be used for more precise answers. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle, undefined results if negative + * @param h the height of the rectangle, undefined results if negative + * @return true if the rectangle intersects this shape + * @see java.awt.geom.Area + * @since 1.2 + */ + boolean intersects(double x, double y, double w, double h); + + /** + * Test if a high-precision rectangle intersects the shape. This is true + * if any point in the rectangle is in the shape, with the caveat that the + * operation may include high probability estimates when the actual + * calculation is prohibitively expensive. The {@link java.awt.geom.Area} + * class can be used for more precise answers. + * + * @param r the rectangle + * @return true if the rectangle intersects this shape + * @throws NullPointerException if r is null + * @see #intersects(double, double, double, double) + * @since 1.2 + */ + boolean intersects(Rectangle2D r); + + /** + * Test if a high-precision rectangle lies completely in the shape. This is + * true if all points in the rectangle are in the shape, with the caveat + * that the operation may include high probability estimates when the actual + * calculation is prohibitively expensive. The {@link java.awt.geom.Area} + * class can be used for more precise answers. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle, undefined results if negative + * @param h the height of the rectangle, undefined results if negative + * @return true if the rectangle is contained in this shape + * @see java.awt.geom.Area + * @since 1.2 + */ + boolean contains(double x, double y, double w, double h); + + /** + * Test if a high-precision rectangle lies completely in the shape. This is + * true if all points in the rectangle are in the shape, with the caveat + * that the operation may include high probability estimates when the actual + * calculation is prohibitively expensive. The {@link java.awt.geom.Area} + * class can be used for more precise answers. + * + * @param r the rectangle + * @return true if the rectangle is contained in this shape + * @throws NullPointerException if r is null + * @see #contains(double, double, double, double) + * @since 1.2 + */ + boolean contains(Rectangle2D r); + + /** + * Return an iterator along the shape boundary. If the optional transform + * is provided, the iterator is transformed accordingly. Each call returns + * a new object, independent from others in use. It is recommended, but + * not required, that the Shape isolate iterations from future changes to + * the boundary, and document this fact. + * + * @param transform an optional transform to apply to the iterator + * @return a new iterator over the boundary + * @since 1.2 + */ + PathIterator getPathIterator(AffineTransform transform); + + /** + * Return an iterator along the flattened version of the shape boundary. + * Only SEG_MOVETO, SEG_LINETO, and SEG_CLOSE points are returned in the + * iterator. The flatness paramter controls how far points are allowed to + * differ from the real curve; although a limit on accuracy may cause this + * parameter to be enlarged if needed. + * + * <p>If the optional transform is provided, the iterator is transformed + * accordingly. Each call returns a new object, independent from others in + * use. It is recommended, but not required, that the Shape isolate + * iterations from future changes to the boundary, and document this fact. + * + * @param transform an optional transform to apply to the iterator + * @param flatness the maximum distance for deviation from the real boundary + * @return a new iterator over the boundary + * @since 1.2 + */ + PathIterator getPathIterator(AffineTransform transform, double flatness); +} // interface Shape diff --git a/libjava/classpath/java/awt/Stroke.java b/libjava/classpath/java/awt/Stroke.java new file mode 100644 index 0000000..1a4c61c --- /dev/null +++ b/libjava/classpath/java/awt/Stroke.java @@ -0,0 +1,65 @@ +/* Stroke.java -- a stroked outline of a shape + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +/** + * This interface allows a Graphics2D to grab the outline of a shape, as if + * stroked by a marking pen of appropriate size and shape. The area inked + * by the pen is the area of this stroke. Anything in the graphic which + * traces an outline will use this stroke, such as <code>drawLine</code>. + * Strokes must be immutable, because the graphics object does not clone + * them. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see BasicStroke + * @see Graphics2D#setStroke(Stroke) + * @since 1.1 + * @status updated to 1.4 + */ +public interface Stroke +{ + /** + * Returns a shape which outlines the boundary of the given shape, in + * effect converting the infinitely thin line into a new shape. + * + * @param s the shape to stroke + * @return the stroked outline shape + */ + Shape createStrokedShape(Shape s); +} // interface Stroke diff --git a/libjava/classpath/java/awt/SystemColor.java b/libjava/classpath/java/awt/SystemColor.java new file mode 100644 index 0000000..2ead74a --- /dev/null +++ b/libjava/classpath/java/awt/SystemColor.java @@ -0,0 +1,462 @@ +/* SystemColor.java -- access dynamic system color values + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.ColorModel; +import java.io.Serializable; + +/** + * This class contains the various "system colors" in use by the native + * windowing system. The <code>getRGB()</code> method is dynamic on systems + * which support dynamic system color changes, and most methods in the + * superclass are written to use this dynamic value when reporting colors. + * However, the <code>equals()</code> method is not dynamic, and does not + * track the actual color of instances in this class. This means that equals + * may give surprising results; you are better off relying on getRGB. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.1 + * @status updated to 1.4 + */ +public final class SystemColor extends Color implements Serializable +{ + // Implementation note: To be serial compatible with JDK, this class must + // violate the semantic meaning of super.value to be one of the + // NUM_COLORS constants instead of the actual RGB value. Hence there are + // a lot of ugly workarounds in Color and in this class. I would have + // designed it MUCH differently, making a separate id field in this class. + + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = 4503142729533789064L; + + /** + * Array index of the desktop color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #desktop + */ + public static final int DESKTOP = 0; + + /** + * Array index of the active caption color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #activeCaption + */ + public static final int ACTIVE_CAPTION = 1; + + /** + * Array index of the active caption text color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #activeCaptionText + */ + public static final int ACTIVE_CAPTION_TEXT = 2; + + /** + * Array index of the active caption border color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #activeCaptionBorder + */ + public static final int ACTIVE_CAPTION_BORDER = 3; + + /** + * Array index of the inactive caption color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #inactiveCaption + */ + public static final int INACTIVE_CAPTION = 4; + + /** + * Array index of the inactive caption text color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #inactiveCaptionText + */ + public static final int INACTIVE_CAPTION_TEXT = 5; + + /** + * Array index of the inactive caption border color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #inactiveCaptionBorder + */ + public static final int INACTIVE_CAPTION_BORDER = 6; + + /** + * Array index of the window background color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #window + */ + public static final int WINDOW = 7; + + /** + * Array index of the window border color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #windowBorder + */ + public static final int WINDOW_BORDER = 8; + + /** + * Array index of the window text color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #windowText + */ + public static final int WINDOW_TEXT = 9; + + /** + * Array index of the menu background color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #menu + */ + public static final int MENU = 10; + + /** + * Array index of the menu text color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #menuText + */ + public static final int MENU_TEXT = 11; + + /** + * Array index of the text background color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #text + */ + public static final int TEXT = 12; + + /** + * Array index of the text foreground color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #textText + */ + public static final int TEXT_TEXT = 13; + + /** + * Array index of the highlighted text background color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #textHighlight + */ + public static final int TEXT_HIGHLIGHT = 14; + + /** + * Array index of the highlighted text foreground color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #textHighlightText + */ + public static final int TEXT_HIGHLIGHT_TEXT = 15; + + /** + * Array index of the inactive text foreground color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #textInactiveText + */ + public static final int TEXT_INACTIVE_TEXT = 16; + + /** + * Array index of the control background color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #control + */ + public static final int CONTROL = 17; + + /** + * Array index of the control text color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #controlText + */ + public static final int CONTROL_TEXT = 18; + + /** + * Array index of the highlighted control background color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #controlHighlight + */ + public static final int CONTROL_HIGHLIGHT = 19; + + /** + * Array index of the lightly highlighted control background color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #controlLtHighlight + */ + public static final int CONTROL_LT_HIGHLIGHT = 20; + + /** + * Array index of the shadowed control background color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #controlShadow + */ + public static final int CONTROL_SHADOW = 21; + + /** + * Array index of the darkly shadowed control background color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #controlDkShadow + */ + public static final int CONTROL_DK_SHADOW = 22; + + /** + * Array index of the scrollbar background color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #scrollbar + */ + public static final int SCROLLBAR = 23; + + /** + * Array index of the info background color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #info + */ + public static final int INFO = 24; + + /** + * Array index of the info text color. Used by + * {@link Toolkit#loadSystemColors(int[])}. + * + * @see #infoText + */ + public static final int INFO_TEXT = 25; + + /** + * The number of system colors. Used by + * {@link Toolkit#loadSystemColors(int[])}. + */ + public static final int NUM_COLORS = 26; + + /** + * The internal array used to dynamically update <code>getRGB()</code>. + */ + private static final int[] colors = new int[NUM_COLORS]; + + /** The desktop color. */ + public static final SystemColor desktop + = new SystemColor(DESKTOP); + + /** The active caption background color. */ + public static final SystemColor activeCaption + = new SystemColor(ACTIVE_CAPTION); + + /** The active caption text color. */ + public static final SystemColor activeCaptionText + = new SystemColor(ACTIVE_CAPTION_TEXT); + + /** The active caption border color. */ + public static final SystemColor activeCaptionBorder + = new SystemColor(ACTIVE_CAPTION_BORDER); + + /** The inactive caption background color. */ + public static final SystemColor inactiveCaption + = new SystemColor(INACTIVE_CAPTION); + + /** The inactive caption text color. */ + public static final SystemColor inactiveCaptionText + = new SystemColor(INACTIVE_CAPTION_TEXT); + + /** The inactive caption border color. */ + public static final SystemColor inactiveCaptionBorder + = new SystemColor(INACTIVE_CAPTION_BORDER); + + /** The window background color. */ + public static final SystemColor window + = new SystemColor(WINDOW); + + /** The window border color. */ + public static final SystemColor windowBorder + = new SystemColor(WINDOW_BORDER); + + /** The window text color. */ + public static final SystemColor windowText + = new SystemColor(WINDOW_TEXT); + + /** The menu background color. */ + public static final SystemColor menu + = new SystemColor(MENU); + + /** The menu text color. */ + public static final SystemColor menuText + = new SystemColor(MENU_TEXT); + + /** The text background color. */ + public static final SystemColor text + = new SystemColor(TEXT); + + /** The text foreground color. */ + public static final SystemColor textText + = new SystemColor(TEXT_TEXT); + + /** The highlighted text background color. */ + public static final SystemColor textHighlight + = new SystemColor(TEXT_HIGHLIGHT); + + /** The highlighted text foreground color. */ + public static final SystemColor textHighlightText + = new SystemColor(TEXT_HIGHLIGHT_TEXT); + + /** The inactive text color. */ + public static final SystemColor textInactiveText + = new SystemColor(TEXT_INACTIVE_TEXT); + + /** The control background color. */ + public static final SystemColor control + = new SystemColor(CONTROL); + + /** The control text color. */ + public static final SystemColor controlText + = new SystemColor(CONTROL_TEXT); + + /** The control highlight color. */ + public static final SystemColor controlHighlight + = new SystemColor(CONTROL_HIGHLIGHT); + + /** The control light highlight color. */ + public static final SystemColor controlLtHighlight + = new SystemColor(CONTROL_LT_HIGHLIGHT); + + /** The control shadow color. */ + public static final SystemColor controlShadow + = new SystemColor(CONTROL_SHADOW); + + /** The control dark shadow color. */ + public static final SystemColor controlDkShadow + = new SystemColor(CONTROL_DK_SHADOW); + + /** The scrollbar color. */ + public static final SystemColor scrollbar + = new SystemColor(SCROLLBAR); + + /** The info text background color. */ + public static final SystemColor info + = new SystemColor(INFO); + + /** The info text foreground color. */ + public static final SystemColor infoText + = new SystemColor(INFO_TEXT); + + /** + * Construct a system color which is dynamically updated. + * + * @param id the color id + */ + private SystemColor(int id) + { + // Note: See Color#Color(int, boolean) to explain why we use this + // particular constructor. + super(id, true); + } + + /** + * Returns the RGB value for this color, in the sRGB color space. The blue + * value will be in bits 0-7, green in 8-15, red in 6-23, and the alpha + * value (bits 24-31) is 0xff. This is dynamically updated, so it may not + * match the results of <code>getRed()</code>, <code>getGreen()</code>, or + * <code>getBlue()</code>. + * + * @return the current RGB value + */ + public int getRGB() + { + Toolkit.getDefaultToolkit().loadSystemColors(colors); + return colors[value] | ALPHA_MASK; + } + + /** + * Returns a paint context, used for filling areas of a raster scan with + * the current value of this system color. Since the system colors may be + * dynamically updated, the returned value may not always be the same; but + * as the system color is solid, the context does not need any of the + * passed parameters to do its job. + * + * @param cm the requested color model + * @param deviceBounds the bounding box in device coordinates, ignored + * @param userBounds the bounding box in user coordinates, ignored + * @param xform the bounds transformation, ignored + * @param hints any rendering hints, ignored + * @return a context for painting this solid color + */ + public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, + Rectangle2D userBounds, + AffineTransform xform, + RenderingHints hints) + { + Toolkit.getDefaultToolkit().loadSystemColors(colors); + int color = colors[value] | ALPHA_MASK; + if (context == null || color != context.color || !context.getColorModel().equals(cm)) + context = new ColorPaintContext(cm,color); + return context; + } + + /** + * Returns a string describing this color. This is in the format + * "java.awt.SystemColor[i=" + index + ']', where index is one of the + * integer constants of this class. Unfortunately, this description + * does not describe the current value of the color; for that you should + * use <code>new Color(syscolor.getRGB()).toString()</code>. + * + * @return a string describing this color + */ + public String toString() + { + return "java.awt.SystemColor[i=" + value + ']'; + } +} // class SystemColor diff --git a/libjava/classpath/java/awt/TextArea.java b/libjava/classpath/java/awt/TextArea.java new file mode 100644 index 0000000..d422d33 --- /dev/null +++ b/libjava/classpath/java/awt/TextArea.java @@ -0,0 +1,629 @@ +/* TextArea.java -- A multi-line text entry component + Copyright (C) 1999, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.KeyEvent; +import java.awt.peer.ComponentPeer; +import java.awt.peer.TextAreaPeer; +import java.util.HashSet; +import java.util.Set; + +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleStateSet; + + +/** + * A TextArea is a text component capable of displaying multiple lines + * of user-editable text. A TextArea handles its own scrolling and + * can display vertical and horizontal scrollbars as navigation aids. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class TextArea extends TextComponent implements java.io.Serializable +{ + /** + * Display both horiztonal and vertical scroll bars. + */ + public static final int SCROLLBARS_BOTH = 0; + + /** + * Display vertical scroll bar only. + */ + public static final int SCROLLBARS_VERTICAL_ONLY = 1; + + /** + * Display horizatonal scroll bar only. + */ + public static final int SCROLLBARS_HORIZONTAL_ONLY = 2; + + /** + * Do not display scrollbars. + */ + public static final int SCROLLBARS_NONE = 3; + + /** + * Serialization constant. + */ + private static final long serialVersionUID = 3692302836626095722L; + + /** + * @serial The number of columns used in this text area's preferred + * and minimum size calculations. + */ + private int columns; + + /** + * @serial The number of rows used in this text area's preferred and + * minimum size calculations. + */ + private int rows; + + /** + * @serial The scrollbar display policy. One of SCROLLBARS_BOTH, + * SCROLLBARS_VERTICAL_ONLY, SCROLLBARS_HORIZONTAL_ONLY, + * SCROLLBARS_NONE. + */ + private int scrollbarVisibility; + + /* + * The number used to generate the name returned by getName. + */ + private static transient long next_text_number; + + /** + * Initialize a new instance of <code>TextArea</code> that is empty. + * Conceptually the <code>TextArea</code> has 0 rows and 0 columns + * but its initial bounds are defined by its peer or by the + * container in which it is packed. Both horizontal and vertical + * scrollbars will be displayed. + * + * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true + */ + public TextArea () + { + this ("", 0, 0, SCROLLBARS_BOTH); + } + + /** + * Initialize a new instance of <code>TextArea</code> that contains + * the specified text. Conceptually the <code>TextArea</code> has 0 + * rows and 0 columns but its initial bounds are defined by its peer + * or by the container in which it is packed. Both horizontal and + * veritcal scrollbars will be displayed. + * + * @param text The text to display in this text area. + * + * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true + */ + public TextArea (String text) + { + this (text, 0, 0, SCROLLBARS_BOTH); + } + + /** + * Initialize a new instance of <code>TextArea</code> that is empty + * and can display the specified number of rows and columns of text, + * without the need to scroll. Both horizontal and vertical + * scrollbars will be displayed. + * + * @param rows The number of rows in this text area. + * @param columns The number of columns in this text area. + * + * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true + */ + public TextArea (int rows, int columns) + { + this ("", rows, columns, SCROLLBARS_BOTH); + } + + /** + * Initialize a new instance of <code>TextArea</code> that can + * display the specified number of rows and columns of text, without + * the need to scroll. The TextArea initially contains the + * specified text. + * + * @param text The text to display in this text area. + * @param rows The number of rows in this text area. + * @param columns The number of columns in this text area. + * + * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true + */ + public TextArea (String text, int rows, int columns) + { + this (text, rows, columns, SCROLLBARS_BOTH); + } + + /** + * Initialize a new instance of <code>TextArea</code> that initially + * contains the specified text. The TextArea can display the + * specified number of rows and columns of text, without the need to + * scroll. This constructor allows specification of the scroll bar + * display policy. + * + * @param text The text to display in this text area. + * @param rows The number of rows in this text area. + * @param columns The number of columns in this text area. + * @param scrollbarVisibility The scroll bar display policy. One of + * SCROLLBARS_BOTH, SCROLLBARS_VERTICAL_ONLY, + * SCROLLBARS_HORIZONTAL_ONLY, SCROLLBARS_NONE. + * + * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true + */ + public TextArea (String text, int rows, int columns, int scrollbarVisibility) + { + super (text); + + if (GraphicsEnvironment.isHeadless ()) + throw new HeadlessException (); + + if (rows < 0 || columns < 0) + throw new IllegalArgumentException ("Bad row or column value"); + + if (scrollbarVisibility != SCROLLBARS_BOTH + && scrollbarVisibility != SCROLLBARS_VERTICAL_ONLY + && scrollbarVisibility != SCROLLBARS_HORIZONTAL_ONLY + && scrollbarVisibility != SCROLLBARS_NONE) + throw new IllegalArgumentException ("Bad scrollbar visibility value"); + + this.rows = rows; + this.columns = columns; + this.scrollbarVisibility = scrollbarVisibility; + + // TextAreas need to receive tab key events so we override the + // default forward and backward traversal key sets. + Set s = new HashSet (); + s.add (AWTKeyStroke.getAWTKeyStroke (KeyEvent.VK_TAB, + KeyEvent.CTRL_DOWN_MASK)); + setFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, s); + s = new HashSet (); + s.add (AWTKeyStroke.getAWTKeyStroke (KeyEvent.VK_TAB, + KeyEvent.SHIFT_DOWN_MASK + | KeyEvent.CTRL_DOWN_MASK)); + setFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, s); + } + + /** + * Retrieve the number of columns that this text area would prefer + * to display. This value may or may not correspond to the number + * of columns that are actually displayed. + * + * @return The preferred number of columns. + */ + public int getColumns () + { + return columns; + } + + /** + * Set the preferred number of columns for this text area. This + * method does not cause the number of columns displayed by the text + * area to be updated, if the text area is currently visible. + * + * @param columns The preferred number of columns. + * + * @exception IllegalArgumentException If columns is less than zero. + */ + public synchronized void setColumns (int columns) + { + if (columns < 0) + throw new IllegalArgumentException ("Value is less than zero: " + + columns); + + this.columns = columns; + } + + /** + * Retrieve the number of rows that this text area would prefer to + * display. This value may or may not correspond to the number of + * rows that are actually displayed. + * + * @return The preferred number of rows. + */ + public int getRows () + { + return rows; + } + + /** + * Set the preferred number of rows for this text area. This method + * does not cause the number of columns displayed by the text area + * to be updated, if the text area is currently visible. + * + * @param rows The preferred number of rows. + * + * @exception IllegalArgumentException If rows is less than zero. + */ + public synchronized void setRows (int rows) + { + if (rows < 1) + throw new IllegalArgumentException ("Value is less than one: " + rows); + + this.rows = rows; + } + + /** + * Retrieve the minimum size for this text area, considering the + * text area's current row and column values. A text area's minimum + * size depends on the number of rows and columns of text it would + * prefer to display, and on the size of the font in which the text + * would be displayed. + * + * @return The minimum size for this text field. + */ + public Dimension getMinimumSize () + { + return getMinimumSize (getRows (), getColumns ()); + } + + /** + * Retrieve the minimum size that this text area would have if its + * row and column values were equal to those specified. A text + * area's minimum size depends on the number of rows and columns of + * text it would prefer to display, and on the size of the font in + * which the text would be displayed. + * + * @param rows The number of rows to use in the minimum size + * calculation. + * @param columns The number of columns to use in the minimum size + * calculation. + * + * @return The minimum size for this text area. + */ + public Dimension getMinimumSize (int rows, int columns) + { + return minimumSize (rows, columns); + } + + /** + * Retrieve the minimum size for this text area, considering the + * text area's current row and column values. A text area's minimum + * size depends on the number of rows and columns of text it would + * prefer to display, and on the size of the font in which the text + * would be displayed. + * + * @return The minimum size for this text area. + * + * @deprecated This method is deprecated in favor of + * <code>getMinimumSize ()</code>. + */ + public Dimension minimumSize () + { + return minimumSize (getRows (), getColumns ()); + } + + /** + * Retrieve the minimum size that this text area would have if its + * row and column values were equal to those specified. A text + * area's minimum size depends on the number of rows and columns of + * text it would prefer to display, and on the size of the font in + * which the text would be displayed. + * + * @param rows The number of rows to use in the minimum size + * calculation. + * @param columns The number of columns to use in the minimum size + * calculation. + * + * @return The minimum size for this text area. + * + * @deprecated This method is deprecated in favor of + * <code>getMinimumSize (int, int)</code>. + */ + public Dimension minimumSize (int rows, int columns) + { + TextAreaPeer peer = (TextAreaPeer) getPeer (); + + // Sun returns Dimension (0,0) in this case. + if (peer == null) + return new Dimension (0, 0); + + return peer.getMinimumSize (rows, columns); + } + + /** + * Retrieve the preferred size for this text area, considering the + * text area's current row and column values. A text area's preferred + * size depends on the number of rows and columns of text it would + * prefer to display, and on the size of the font in which the text + * would be displayed. + * + * @return The preferred size for this text field. + */ + public Dimension getPreferredSize () + { + return getPreferredSize (getRows (), getColumns ()); + } + + /** + * Retrieve the preferred size that this text area would have if its + * row and column values were equal to those specified. A text + * area's preferred size depends on the number of rows and columns + * of text it would prefer to display, and on the size of the font + * in which the text would be displayed. + * + * @param rows The number of rows to use in the preferred size + * calculation. + * @param columns The number of columns to use in the preferred size + * calculation. + * + * @return The preferred size for this text area. + */ + public Dimension getPreferredSize (int rows, int columns) + { + return preferredSize (rows, columns); + } + + /** + * Retrieve the preferred size for this text area, considering the + * text area's current row and column values. A text area's preferred + * size depends on the number of rows and columns of text it would + * prefer to display, and on the size of the font in which the text + * would be displayed. + * + * @return The preferred size for this text field. + * + * @deprecated This method is deprecated in favor of + * <code>getPreferredSize ()</code>. + */ + public Dimension preferredSize () + { + return preferredSize (getRows (), getColumns ()); + } + + /** + * Retrieve the preferred size that this text area would have if its + * row and column values were equal to those specified. A text + * area's preferred size depends on the number of rows and columns + * of text it would prefer to display, and on the size of the font + * in which the text would be displayed. + * + * @param rows The number of rows to use in the preferred size + * calculation. + * @param columns The number of columns to use in the preferred size + * calculation. + * + * @return The preferred size for this text area. + * + * @deprecated This method is deprecated in favor of + * <code>getPreferredSize (int, int)</code>. + */ + public Dimension preferredSize (int rows, int columns) + { + TextAreaPeer peer = (TextAreaPeer) getPeer (); + + // Sun returns Dimension (0,0) in this case. + if (peer == null) + return new Dimension (0, 0); + + return peer.getPreferredSize (rows, columns); + } + + /** + * Retrieve the scroll bar display policy -- one of SCROLLBARS_BOTH, + * SCROLLBARS_VERTICAL_ONLY, SCROLLBARS_HORIZONTAL_ONLY, + * SCROLLBARS_NONE. + * + * @return The current scroll bar display policy. + */ + public int getScrollbarVisibility () + { + return scrollbarVisibility; + } + + /** + * Notify this object that it should create its native peer. + */ + public void addNotify () + { + if (getPeer () == null) + setPeer ((ComponentPeer) getToolkit().createTextArea (this)); + } + + /** + * Append the specified text to the end of the current text. + * + * @param str The text to append. + */ + public void append (String str) + { + appendText (str); + } + + /** + * Append the specified text to the end of the current text. + * + * @param str The text to append. + * + * @deprecated This method is deprecated in favor of + * <code>append ()</code>. + */ + public void appendText (String str) + { + TextAreaPeer peer = (TextAreaPeer) getPeer (); + + if (peer != null) + peer.insert (str, peer.getText().length ()); + } + + /** + * Insert the specified text at the specified position. The first + * character in the text area is at position zero. + * + * @param str The text to insert. + * @param pos The position at which to insert text. + */ + public void insert (String str, int pos) + { + insertText (str, pos); + } + + /** + * Insert the specified text at the specified position. The first + * character in the text area is at position zero. + * + * @param str The text to insert. + * @param pos The position at which to insert text. + * + * @deprecated This method is deprecated in favor of + * <code>insert ()</code>. + */ + public void insertText (String str, int pos) + { + TextAreaPeer peer = (TextAreaPeer) getPeer (); + + if (peer != null) + peer.insert (str, pos); + } + + /** + * Replace a range of characters with the specified text. The + * character at the start position will be replaced, unless start == + * end. The character at the end posistion will not be replaced. + * The first character in the text area is at position zero. The + * length of the replacement text may differ from the length of the + * text that is replaced. + * + * @param str The new text for the range. + * @param start The start position of the replacement range. + * @param end The end position of the replacement range. + */ + public void replaceRange (String str, int start, int end) + { + replaceText (str, start, end); + } + + /** + * Replace a range of characters with the specified text. The + * character at the start position will be replaced, unless start == + * end. The character at the end posistion will not be replaced. + * The first character in the text area is at position zero. The + * length of the replacement text may differ from the length of the + * text that is replaced. + * + * @param str The new text for the range. + * @param start The start position of the replacement range. + * @param end The end position of the replacement range. + * + * @deprecated This method is deprecated in favor of + * <code>replaceRange ()</code>. + */ + public void replaceText (String str, int start, int end) + { + TextAreaPeer peer = (TextAreaPeer) getPeer (); + + if (peer != null) + peer.replaceRange (str, start, end); + } + + /** + * Retrieve a debugging string for this text area. + * + * @return A debugging string for this text area. + */ + protected String paramString () + { + String sbVisibility = ""; + + switch (scrollbarVisibility) + { + case SCROLLBARS_BOTH: + sbVisibility = "both"; + break; + case SCROLLBARS_VERTICAL_ONLY: + sbVisibility = "vertical-only"; + break; + case SCROLLBARS_HORIZONTAL_ONLY: + sbVisibility = "horizontal-only"; + break; + case SCROLLBARS_NONE: + sbVisibility = "none"; + break; + } + + String editable = ""; + if (isEditable ()) + editable = "editable,"; + + return getName () + "," + getX () + "," + getY () + "," + getWidth () + + "x" + getHeight () + "," + "text=" + getText () + "," + editable + + "selection=" + getSelectionStart () + "-" + getSelectionEnd () + + ",rows=" + rows + ",columns=" + columns + ",scrollbarVisibility=" + + sbVisibility; + } + + /** + * Generate a unique name for this text area. + * + * @return A unique name for this text area. + */ + String generateName () + { + return "text" + getUniqueLong (); + } + + private static synchronized long getUniqueLong () + { + return next_text_number++; + } + + protected class AccessibleAWTTextArea extends AccessibleAWTTextComponent + { + protected AccessibleAWTTextArea() + { + } + + public AccessibleStateSet getAccessibleStateSet() + { + return super.getAccessibleStateSet(); + } + } + + /** + * Gets the AccessibleContext associated with this <code>TextArea</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTTextArea(); + return accessibleContext; + } +} diff --git a/libjava/classpath/java/awt/TextComponent.java b/libjava/classpath/java/awt/TextComponent.java new file mode 100644 index 0000000..9edbd88 --- /dev/null +++ b/libjava/classpath/java/awt/TextComponent.java @@ -0,0 +1,739 @@ +/* TextComponent.java -- Widgets for entering text + Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.TextEvent; +import java.awt.event.TextListener; +import java.awt.peer.TextComponentPeer; +import java.io.Serializable; +import java.text.BreakIterator; +import java.util.EventListener; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleText; +import javax.swing.text.AttributeSet; + +/** + * This class provides common functionality for widgets than + * contain text. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class TextComponent extends Component + implements Serializable, Accessible +{ + +/* + * Static Variables + */ + +// Constant for serialization +private static final long serialVersionUID = -2214773872412987419L; + +/* + * Instance Variables + */ + +/** + * @serial Indicates whether or not this component is editable. + * This is package-private to avoid an accessor method. + */ +boolean editable; + +/** + * @serial The starting position of the selected text region. + * This is package-private to avoid an accessor method. + */ +int selectionStart; + +/** + * @serial The ending position of the selected text region. + * This is package-private to avoid an accessor method. + */ +int selectionEnd; + +/** + * @serial The text in the component + * This is package-private to avoid an accessor method. + */ +String text; + +/** + * A list of listeners that will receive events from this object. + */ +protected transient TextListener textListener; + + protected class AccessibleAWTTextComponent + extends AccessibleAWTComponent + implements AccessibleText, TextListener + { + // Constructor + // Adds a listener for tracking caret changes + public AccessibleAWTTextComponent() + { + TextComponent.this.addTextListener(this); + } + + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.TEXT; + } + + public AccessibleStateSet getAccessibleStateSet() + { + // TODO: Docs say PropertyChangeEvent will fire if this state changes. + // That means that the event has to fire when editable changes. + AccessibleStateSet ss = super.getAccessibleStateSet(); + if (editable) + ss.add(AccessibleState.EDITABLE); + return ss; + } + + public AccessibleText getAccessibleText() + { + return this; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleText#getIndexAtPoint(java.awt.Point) + */ + public int getIndexAtPoint(Point point) + { + return TextComponent.this.getIndexAtPoint(point); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleText#getCharacterBounds(int) + */ + public Rectangle getCharacterBounds(int index) + { + return TextComponent.this.getCharacterBounds(index); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleText#getCharCount() + */ + public int getCharCount() + { + return text.length(); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleText#getCaretPosition() + */ + public int getCaretPosition() + { + return TextComponent.this.getCaretPosition(); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleText#getAtIndex(int, int) + */ + public String getAtIndex(int part, int index) + { + if (index < 0 || index >= text.length()) + return null; + BreakIterator it = null; + switch (part) + { + case CHARACTER: + return text.substring(index, index + 1); + case WORD: + it = BreakIterator.getWordInstance(); + break; + case SENTENCE: + it = BreakIterator.getSentenceInstance(); + break; + default: + return null; + } + it.setText(text); + int start = index; + if (!it.isBoundary(index)) + start = it.preceding(index); + int end = it.following(index); + if (end == -1) + return text.substring(index); + else + return text.substring(index, end); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleText#getAfterIndex(int, int) + */ + public String getAfterIndex(int part, int index) { + if (index < 0 || index >= text.length()) + return null; + BreakIterator it = null; + switch (part) + { + case CHARACTER: + return text.substring(index, index + 1); + case WORD: + it = BreakIterator.getWordInstance(); + break; + case SENTENCE: + it = BreakIterator.getSentenceInstance(); + break; + default: + return null; + } + it.setText(text); + int start = index; + if (!it.isBoundary(index)) + start = it.following(index); + // Make sure there was a complete unit. I.e. if index is in the middle + // of a word, return null if there is no word after the that one. + if (start == -1) + return null; + int end = it.following(start); + if (end == -1) + return text.substring(index); + else + return text.substring(index, end); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleText#getBeforeIndex(int, int) + */ + public String getBeforeIndex(int part, int index) + { + if (index < 1 || index >= text.length()) + return null; + BreakIterator it = null; + switch (part) + { + case CHARACTER: + return text.substring(index - 1, index); + case WORD: + it = BreakIterator.getWordInstance(); + break; + case SENTENCE: + it = BreakIterator.getSentenceInstance(); + break; + default: + return null; + } + it.setText(text); + int end = index; + if (!it.isBoundary(index)) + end = it.preceding(index); + // Make sure there was a complete unit. I.e. if index is in the middle + // of a word, return null if there is no word before that one. + if (end == -1) + return null; + int start = it.preceding(end); + if (start == -1) + return text.substring(0, end); + else + return text.substring(start, end); + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleText#getCharacterAttribute(int) + */ + public AttributeSet getCharacterAttribute(int index) + { + // FIXME: I suspect this really gets filled in by subclasses. + return null; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleText#getSelectionStart() + */ + public int getSelectionStart() { + // TODO Auto-generated method stub + return selectionStart; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleText#getSelectionEnd() + */ + public int getSelectionEnd() + { + return selectionEnd; + } + + /* (non-Javadoc) + * @see javax.accessibility.AccessibleText#getSelectedText() + */ + public String getSelectedText() + { + if (selectionEnd - selectionStart > 0) + return text.substring(selectionStart, selectionEnd); + else + return null; + } + + /* (non-Javadoc) + * @see java.awt.event.TextListener#textValueChanged(java.awt.event.TextEvent) + */ + public void textValueChanged(TextEvent event) + { + // TODO Auto-generated method stub + + } + + } + +/*************************************************************************/ + +/* + * Constructors + */ + +TextComponent(String text) +{ + this.text = text; + this.editable = true; +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns the text in this component + * + * @return The text in this component. + */ +public synchronized String +getText() +{ + TextComponentPeer tcp = (TextComponentPeer)getPeer(); + if (tcp != null) + text = tcp.getText(); + + return(text); +} + +/*************************************************************************/ + +/** + * Sets the text in this component to the specified string. + * + * @param text The new text for this component. + */ +public synchronized void +setText(String text) +{ + if (text == null) + text = ""; + + this.text = text; + + TextComponentPeer tcp = (TextComponentPeer)getPeer(); + if (tcp != null) + tcp.setText(text); + setCaretPosition(0); +} + +/*************************************************************************/ + +/** + * Returns a string that contains the text that is currently selected. + * + * @return The currently selected text region. + */ +public synchronized String +getSelectedText() +{ + String alltext = getText(); + int start = getSelectionStart(); + int end = getSelectionEnd(); + + return(alltext.substring(start, end)); +} + +/*************************************************************************/ + +/** + * Returns the starting position of the selected text region. + * If the text is not selected then caret position is returned. + * + * @return The starting position of the selected text region. + */ +public synchronized int +getSelectionStart() +{ + TextComponentPeer tcp = (TextComponentPeer)getPeer(); + if (tcp != null) + selectionStart = tcp.getSelectionStart(); + + return(selectionStart); +} + +/*************************************************************************/ + +/** + * Sets the starting position of the selected region to the + * specified value. If the specified value is out of range, then it + * will be silently changed to the nearest legal value. + * + * @param selectionStart The new start position for selected text. + */ +public synchronized void +setSelectionStart(int selectionStart) +{ + select(selectionStart, getSelectionEnd()); +} + +/*************************************************************************/ + +/** + * Returns the ending position of the selected text region. + * If the text is not selected, then caret position is returned + * + * @return The ending position of the selected text region. + */ +public synchronized int +getSelectionEnd() +{ + TextComponentPeer tcp = (TextComponentPeer)getPeer(); + if (tcp != null) + selectionEnd = tcp.getSelectionEnd(); + + return(selectionEnd); +} + +/*************************************************************************/ + +/** + * Sets the ending position of the selected region to the + * specified value. If the specified value is out of range, then it + * will be silently changed to the nearest legal value. + * + * @param selectionEnd The new start position for selected text. + */ +public synchronized void +setSelectionEnd(int selectionEnd) +{ + select(getSelectionStart(), selectionEnd); +} + +/*************************************************************************/ + +/** + * This method sets the selected text range to the text between the + * specified start and end positions. Illegal values for these + * positions are silently fixed. + * + * @param selectionStart The new start position for the selected text. + * @param selectionEnd The new end position for the selected text. + */ +public synchronized void +select(int selectionStart, int selectionEnd) +{ + if (selectionStart < 0) + selectionStart = 0; + + if (selectionStart > getText().length()) + selectionStart = text.length(); + + if (selectionEnd > text.length()) + selectionEnd = text.length(); + + if (selectionStart > getSelectionEnd()) + selectionStart = selectionEnd; + + this.selectionStart = selectionStart; + this.selectionEnd = selectionEnd; + + TextComponentPeer tcp = (TextComponentPeer)getPeer(); + if (tcp != null) + tcp.select(selectionStart, selectionEnd); +} + +/*************************************************************************/ + +/** + * Selects all of the text in the component. + */ +public synchronized void +selectAll() +{ + select(0, getText().length()); +} + +/*************************************************************************/ + +/** + * Returns the current caret position in the text. + * + * @return The caret position in the text. + */ +public synchronized int +getCaretPosition() +{ + TextComponentPeer tcp = (TextComponentPeer)getPeer(); + if (tcp != null) + return(tcp.getCaretPosition()); + else + return(0); +} + +/*************************************************************************/ + +/** + * Sets the caret position to the specified value. + * + * @param caretPosition The new caret position. + * + * @exception IllegalArgumentException If the value supplied for position + * is less than zero. + * + * @since 1.1 + */ +public synchronized void +setCaretPosition(int caretPosition) +{ + if (caretPosition < 0) + throw new IllegalArgumentException (); + + TextComponentPeer tcp = (TextComponentPeer)getPeer(); + if (tcp != null) + tcp.setCaretPosition(caretPosition); +} + +/*************************************************************************/ + +/** + * Tests whether or not this component's text can be edited. + * + * @return <code>true</code> if the text can be edited, <code>false</code> + * otherwise. + */ +public boolean +isEditable() +{ + return(editable); +} + +/*************************************************************************/ + +/** + * Sets whether or not this component's text can be edited. + * + * @param editable <code>true</code> to enable editing of the text, + * <code>false</code> to disable it. + */ +public synchronized void +setEditable(boolean editable) +{ + this.editable = editable; + + TextComponentPeer tcp = (TextComponentPeer)getPeer(); + if (tcp != null) + tcp.setEditable(editable); +} + +/*************************************************************************/ + +/** + * Notifies the component that it should destroy its native peer. + */ +public void +removeNotify() +{ + super.removeNotify(); +} + +/*************************************************************************/ + +/** + * Adds a new listener to the list of text listeners for this + * component. + * + * @param listener The listener to be added. + */ +public synchronized void +addTextListener(TextListener listener) +{ + textListener = AWTEventMulticaster.add(textListener, listener); + + enableEvents(AWTEvent.TEXT_EVENT_MASK); +} + +/*************************************************************************/ + +/** + * Removes the specified listener from the list of listeners + * for this component. + * + * @param listener The listener to remove. + */ +public synchronized void +removeTextListener(TextListener listener) +{ + textListener = AWTEventMulticaster.remove(textListener, listener); +} + +/*************************************************************************/ + +/** + * Processes the specified event for this component. Text events are + * processed by calling the <code>processTextEvent()</code> method. + * All other events are passed to the superclass method. + * + * @param event The event to process. + */ +protected void +processEvent(AWTEvent event) +{ + if (event instanceof TextEvent) + processTextEvent((TextEvent)event); + else + super.processEvent(event); +} + +/*************************************************************************/ + +/** + * Processes the specified text event by dispatching it to any listeners + * that are registered. Note that this method will only be called + * if text event's are enabled. This will be true if there are any + * registered listeners, or if the event has been specifically + * enabled using <code>enableEvents()</code>. + * + * @param event The text event to process. + */ +protected void +processTextEvent(TextEvent event) +{ + if (textListener != null) + textListener.textValueChanged(event); +} + +void +dispatchEventImpl(AWTEvent e) +{ + if (e.id <= TextEvent.TEXT_LAST + && e.id >= TextEvent.TEXT_FIRST + && (textListener != null + || (eventMask & AWTEvent.TEXT_EVENT_MASK) != 0)) + processEvent(e); + else + super.dispatchEventImpl(e); +} + +/*************************************************************************/ + +/** + * Returns a debugging string. + * + * @return A debugging string. + */ +protected String +paramString() +{ + return(getClass().getName() + "(text=" + getText() + ")"); +} + + /** + * Returns an array of all the objects currently registered as FooListeners + * upon this <code>TextComponent</code>. FooListeners are registered using + * the addFooListener method. + * + * @exception ClassCastException If listenerType doesn't specify a class or + * interface that implements java.util.EventListener. + */ + public EventListener[] getListeners (Class listenerType) + { + if (listenerType == TextListener.class) + return AWTEventMulticaster.getListeners (textListener, listenerType); + + return super.getListeners (listenerType); + } + + /** + * Returns all text listeners registered to this object. + */ + public TextListener[] getTextListeners () + { + return (TextListener[]) getListeners (TextListener.class); + } + + /** + * Gets the AccessibleContext associated with this <code>TextComponent</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTTextComponent(); + return accessibleContext; + } + + + /*******************************/ + // Provide AccessibleAWTTextComponent access to several peer functions that + // aren't publicly exposed. This is package-private to avoid an accessor + // method. + synchronized int + getIndexAtPoint(Point p) + { + TextComponentPeer tcp = (TextComponentPeer)getPeer(); + if (tcp != null) + return tcp.getIndexAtPoint(p.x, p.y); + return -1; + } + + synchronized Rectangle + getCharacterBounds(int i) + { + TextComponentPeer tcp = (TextComponentPeer)getPeer(); + if (tcp != null) + return tcp.getCharacterBounds(i); + return null; + } + + + + +} // class TextComponent + diff --git a/libjava/classpath/java/awt/TextField.java b/libjava/classpath/java/awt/TextField.java new file mode 100644 index 0000000..4d62d02 --- /dev/null +++ b/libjava/classpath/java/awt/TextField.java @@ -0,0 +1,541 @@ +/* TextField.java -- A one line text entry field + Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.peer.ComponentPeer; +import java.awt.peer.TextFieldPeer; +import java.util.EventListener; + +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleStateSet; + +/** + * This class implements a single line text entry field widget + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class TextField extends TextComponent +{ + +/* + * Static Variables + */ + +// Serialization constant +private static final long serialVersionUID = -2966288784432217853L; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * @serial The number of columns in the text entry field. + */ +private int columns; + +/** + * @serial The character that is echoed when doing protected input + */ +private char echoChar; + +// List of registered ActionListener's for this object. +private ActionListener action_listeners; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Initializes a new instance of <code>TextField</code> that is empty + * and has one column. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true, + */ +public +TextField() +{ + this("", 1); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>TextField</code> containing + * the specified text. The number of columns will be equal to the + * length of the text string. + * + * @param text The text to display in the field. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true, + */ +public +TextField(String text) +{ + this(text, text.length()); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>TextField</code> that is empty + * and has the specified number of columns. + * + * @param columns The number of columns in the text field. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true, + */ +public +TextField(int columns) +{ + this("", columns); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>TextField</code> with the + * specified text and number of columns. + * + * @param text The text to display in the field. + * @param columns The number of columns in the field. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true, + */ +public +TextField(String text, int columns) +{ + super(text); + this.columns = columns; + + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException (); +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * Returns the number of columns in the field. + * + * @return The number of columns in the field. + */ +public int +getColumns() +{ + return(columns); +} + +/*************************************************************************/ + +/** + * Sets the number of columns in this field to the specified value. + * + * @param columns The new number of columns in the field. + * + * @exception IllegalArgumentException If columns is less than zero. + */ +public synchronized void +setColumns(int columns) +{ + if (columns < 0) + throw new IllegalArgumentException("Value is less than zero: " + + columns); + + this.columns = columns; + // FIXME: How to we communicate this to our peer? +} + +/*************************************************************************/ + +/** + * Returns the character that is echoed to the screen when a text + * field is protected (such as when a password is being entered). + * + * @return The echo character for this text field. + */ +public char +getEchoChar() +{ + return(echoChar); +} + +/*************************************************************************/ + +/** + * Sets the character that is echoed when protected input such as + * a password is displayed. + * + * @param echoChar The new echo character. + */ +public void +setEchoChar(char echoChar) +{ + setEchoCharacter (echoChar); +} + +/*************************************************************************/ + +/** + * Sets the character that is echoed when protected input such as + * a password is displayed. + * + * @param echoChar The new echo character. + * + * @deprecated This method is deprecated in favor of + * <code>setEchoChar()</code> + */ +public void +setEchoCharacter(char echoChar) +{ + this.echoChar = echoChar; + + TextFieldPeer peer = (TextFieldPeer) getPeer (); + if (peer != null) + peer.setEchoChar (echoChar); +} + +/*************************************************************************/ + +/** + * Tests whether or not this text field has an echo character set + * so that characters the user type are not echoed to the screen. + * + * @return <code>true</code> if an echo character is set, + * <code>false</code> otherwise. + */ +public boolean +echoCharIsSet() +{ + if (echoChar == '\u0000') + return(false); + else + return(true); +} + +/*************************************************************************/ + +/** + * Returns the minimum size for this text field. + * + * @return The minimum size for this text field. + */ +public Dimension +getMinimumSize() +{ + return getMinimumSize (getColumns ()); +} + +/*************************************************************************/ + +/** + * Returns the minimum size of a text field with the specified number + * of columns. + * + * @param columns The number of columns to get the minimum size for. + */ +public Dimension +getMinimumSize(int columns) +{ + return minimumSize (columns); +} + +/*************************************************************************/ + +/** + * Returns the minimum size for this text field. + * + * @return The minimum size for this text field. + * + * @deprecated This method is deprecated in favor of + * <code>getMinimumSize()</code>. + */ +public Dimension +minimumSize() +{ + return minimumSize (getColumns ()); +} + +/*************************************************************************/ + +/** + * Returns the minimum size of a text field with the specified number + * of columns. + * + * @param columns The number of columns to get the minimum size for. + * + * @deprecated This method is deprecated in favor of + * <code>getMinimumSize(int)</code>. + */ +public Dimension +minimumSize(int columns) +{ + TextFieldPeer peer = (TextFieldPeer) getPeer (); + if (peer == null) + return null; // FIXME: What do we do if there is no peer? + + return peer.getMinimumSize (columns); +} + +/*************************************************************************/ + +/** + * Returns the preferred size for this text field. + * + * @return The preferred size for this text field. + */ +public Dimension +getPreferredSize() +{ + return getPreferredSize (getColumns ()); +} + +/*************************************************************************/ + +/** + * Returns the preferred size of a text field with the specified number + * of columns. + * + * @param columns The number of columns to get the preferred size for. + */ +public Dimension +getPreferredSize(int columns) +{ + return preferredSize (columns); +} + +/*************************************************************************/ + +/** + * Returns the preferred size for this text field. + * + * @return The preferred size for this text field. + * + * @deprecated This method is deprecated in favor of + * <code>getPreferredSize()</code>. + */ +public Dimension +preferredSize() +{ + return preferredSize (getColumns ()); +} + +/*************************************************************************/ + +/** + * Returns the preferred size of a text field with the specified number + * of columns. + * + * @param columns The number of columns to get the preferred size for. + * + * @deprecated This method is deprecated in favor of + * <code>getPreferredSize(int)</code>. + */ +public Dimension +preferredSize(int columns) +{ + TextFieldPeer peer = (TextFieldPeer) getPeer (); + if (peer == null) + return new Dimension (0, 0); + + return peer.getPreferredSize (columns); +} + +/*************************************************************************/ + +/** + * Notifies this object that it should create its native peer. + */ +public void +addNotify() +{ + if (getPeer() != null) + return; + + setPeer((ComponentPeer)getToolkit().createTextField(this)); +} + +/*************************************************************************/ + +/** + * Addes a new listener to the list of action listeners for this + * object. + * + * @param listener The listener to add to the list. + */ +public synchronized void +addActionListener(ActionListener listener) +{ + action_listeners = AWTEventMulticaster.add(action_listeners, listener); + + enableEvents(AWTEvent.ACTION_EVENT_MASK); +} + +/*************************************************************************/ + +/** + * Removes the specified listener from the list of action listeners + * for this object. + * + * @param listener The listener to remove from the list. + */ +public synchronized void +removeActionListener(ActionListener listener) +{ + action_listeners = AWTEventMulticaster.remove(action_listeners, listener); +} + +/*************************************************************************/ + +/** + * Processes the specified event. If the event is an instance of + * <code>ActionEvent</code> then <code>processActionEvent()</code> is + * called to process it, otherwise the event is sent to the + * superclass. + * + * @param event The event to process. + */ +protected void +processEvent(AWTEvent event) +{ + if (event instanceof ActionEvent) + processActionEvent((ActionEvent)event); + else + super.processEvent(event); +} + +/*************************************************************************/ + +/** + * Processes an action event by calling any registered listeners. + * Note to subclasses: This method is not called unless action events + * are enabled on this object. This will be true if any listeners + * are registered, or if action events were specifically enabled + * using <code>enableEvents()</code>. + * + * @param event The event to process. + */ +protected void +processActionEvent(ActionEvent event) +{ + if (action_listeners != null) + action_listeners.actionPerformed(event); +} + +void +dispatchEventImpl(AWTEvent e) +{ + if (e.id <= ActionEvent.ACTION_LAST + && e.id >= ActionEvent.ACTION_FIRST + && (action_listeners != null + || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0)) + processEvent(e); + else + super.dispatchEventImpl(e); +} + +/*************************************************************************/ + +/** + * Returns a debug string for this object. + * + * @return A debug string for this object. + */ +protected String +paramString() +{ + return(getClass().getName() + "(columns=" + getColumns() + ",echoChar=" + + getEchoChar()); +} + + /** + * Returns an array of all the objects currently registered as FooListeners + * upon this <code>TextField</code>. FooListeners are registered using the + * addFooListener method. + * + * @exception ClassCastException If listenerType doesn't specify a class or + * interface that implements java.util.EventListener. + * + * @since 1.3 + */ + public EventListener[] getListeners (Class listenerType) + { + if (listenerType == ActionListener.class) + return AWTEventMulticaster.getListeners (action_listeners, listenerType); + + return super.getListeners (listenerType); + } + + /** + * Return all ActionListeners register to this <code>TextField</code> object + * as an array. + * + * @since 1.4 + */ + public ActionListener[] getActionListeners () + { + return (ActionListener[]) getListeners (ActionListener.class); + } + + protected class AccessibleAWTTextField extends AccessibleAWTTextComponent + { + protected AccessibleAWTTextField() + { + } + + public AccessibleStateSet getAccessibleStateSet() + { + return super.getAccessibleStateSet(); + } + } + + public AccessibleContext getAccessibleContext() + { + return new AccessibleAWTTextField(); + } + +} // class TextField diff --git a/libjava/classpath/java/awt/TexturePaint.java b/libjava/classpath/java/awt/TexturePaint.java new file mode 100644 index 0000000..a12e384 --- /dev/null +++ b/libjava/classpath/java/awt/TexturePaint.java @@ -0,0 +1,75 @@ +/* TexturePaint.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; + +/** STUB CLASS ONLY */ +public class TexturePaint implements Paint +{ + private final BufferedImage texture; + private final Rectangle2D anchor; + public TexturePaint(BufferedImage texture, Rectangle2D anchor) + { + this.texture = texture; + this.anchor = anchor; + } + public BufferedImage getImage() + { + return texture; + } + public Rectangle2D getAnchorRect() + { + return anchor; + } + public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, + Rectangle2D userBounds, + AffineTransform xform, + RenderingHints hints) + { + throw new Error("not implemented"); + } + public int getTransparency() + { + throw new Error("not implemented"); + } +} // class TexturePaint diff --git a/libjava/classpath/java/awt/Toolkit.java b/libjava/classpath/java/awt/Toolkit.java new file mode 100644 index 0000000..c7c6f9f --- /dev/null +++ b/libjava/classpath/java/awt/Toolkit.java @@ -0,0 +1,995 @@ +/* Toolkit.java -- AWT Toolkit superclass + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.datatransfer.Clipboard; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragGestureRecognizer; +import java.awt.dnd.DragSource; +import java.awt.dnd.peer.DragSourceContextPeer; +import java.awt.event.AWTEventListener; +import java.awt.event.KeyEvent; +import java.awt.im.InputMethodHighlight; +import java.awt.image.ColorModel; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.awt.peer.ButtonPeer; +import java.awt.peer.CanvasPeer; +import java.awt.peer.CheckboxMenuItemPeer; +import java.awt.peer.CheckboxPeer; +import java.awt.peer.ChoicePeer; +import java.awt.peer.DialogPeer; +import java.awt.peer.FileDialogPeer; +import java.awt.peer.FontPeer; +import java.awt.peer.FramePeer; +import java.awt.peer.LabelPeer; +import java.awt.peer.LightweightPeer; +import java.awt.peer.ListPeer; +import java.awt.peer.MenuBarPeer; +import java.awt.peer.MenuItemPeer; +import java.awt.peer.MenuPeer; +import java.awt.peer.PanelPeer; +import java.awt.peer.PopupMenuPeer; +import java.awt.peer.ScrollPanePeer; +import java.awt.peer.ScrollbarPeer; +import java.awt.peer.TextAreaPeer; +import java.awt.peer.TextFieldPeer; +import java.awt.peer.WindowPeer; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.net.URL; +import java.util.Map; +import java.util.Properties; + +/** + * The AWT system uses a set of native peer objects to implement its + * widgets. These peers are provided by a peer toolkit, that is accessed + * via a subclass of this superclass. The system toolkit is retrieved + * by the static methods <code>getDefaultToolkit</code>. This method + * determines the system toolkit by examining the system property + * <code>awt.toolkit</code>. That property is set to the name of the + * <code>Toolkit</code> subclass for the specified peer set. If the + * <code>awt.toolkit</code> property is not set, then the default + * toolkit <code>gnu.java.awt.peer.gtk.GtkToolkit</code> is used. This + * toolkit creates its peers using the GTK+ toolkit. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public abstract class Toolkit +{ + /** The default toolkit name. */ + private static String default_toolkit_name + = gnu.classpath.Configuration.default_awt_peer_toolkit; + + /** + * The toolkit in use. Once we load it, we don't ever change it + * if the awt.toolkit property is set. + */ + private static Toolkit toolkit; + + /** The toolkit properties. */ + private static Properties props = new Properties(); + + protected final Map desktopProperties = new Properties(); + + protected final PropertyChangeSupport desktopPropsSupport + = new PropertyChangeSupport(this); + + /** + * Default constructor for subclasses. + */ + public Toolkit() + { + } + + /** + * Creates a peer object for the specified <code>Button</code>. + * + * @param target The <code>Button</code> to create the peer for. + * + * @return The peer for the specified <code>Button</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract ButtonPeer createButton(Button target); + + /** + * Creates a peer object for the specified <code>TextField</code>. + * + * @param target The <code>TextField</code> to create the peer for. + * + * @return The peer for the specified <code>TextField</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract TextFieldPeer createTextField(TextField target); + + /** + * Creates a peer object for the specified <code>Label</code>. + * + * @param target The <code>Label</code> to create the peer for. + * + * @return The peer for the specified <code>Label</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract LabelPeer createLabel(Label target); + + /** + * Creates a peer object for the specified <code>List</code>. + * + * @param target The <code>List</code> to create the peer for. + * + * @return The peer for the specified <code>List</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract ListPeer createList(List target); + + /** + * Creates a peer object for the specified <code>Checkbox</code>. + * + * @param target The <code>Checkbox</code> to create the peer for. + * + * @return The peer for the specified <code>Checkbox</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract CheckboxPeer createCheckbox(Checkbox target); + + /** + * Creates a peer object for the specified <code>Scrollbar</code>. + * + * @param target The <code>Scrollbar</code> to create the peer for. + * + * @return The peer for the specified <code>Scrollbar</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract ScrollbarPeer createScrollbar(Scrollbar target); + + /** + * Creates a peer object for the specified <code>ScrollPane</code>. + * + * @param target The <code>ScrollPane</code> to create the peer for. + * + * @return The peer for the specified <code>ScrollPane</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract ScrollPanePeer createScrollPane(ScrollPane target); + + /** + * Creates a peer object for the specified <code>TextArea</code>. + * + * @param target The <code>TextArea</code> to create the peer for. + * + * @return The peer for the specified <code>TextArea</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract TextAreaPeer createTextArea(TextArea target); + + /** + * Creates a peer object for the specified <code>Choice</code>. + * + * @param target The <code>Choice</code> to create the peer for. + * + * @return The peer for the specified <code>Choice</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract ChoicePeer createChoice(Choice target); + + /** + * Creates a peer object for the specified <code>Frame</code>. + * + * @param target The <code>Frame</code> to create the peer for. + * + * @return The peer for the specified <code>Frame</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract FramePeer createFrame(Frame target); + + /** + * Creates a peer object for the specified <code>Canvas</code>. + * + * @param target The <code>Canvas</code> to create the peer for. + * + * @return The peer for the specified <code>Canvas</code> object. + */ + protected abstract CanvasPeer createCanvas(Canvas target); + + /** + * Creates a peer object for the specified <code>Panel</code>. + * + * @param target The <code>Panel</code> to create the peer for. + * + * @return The peer for the specified <code>Panel</code> object. + */ + protected abstract PanelPeer createPanel(Panel target); + + /** + * Creates a peer object for the specified <code>Window</code>. + * + * @param target The <code>Window</code> to create the peer for. + * + * @return The peer for the specified <code>Window</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract WindowPeer createWindow(Window target); + + /** + * Creates a peer object for the specified <code>Dialog</code>. + * + * @param target The dialog to create the peer for + * + * @return The peer for the specified font name. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract DialogPeer createDialog(Dialog target); + + /** + * Creates a peer object for the specified <code>MenuBar</code>. + * + * @param target The <code>MenuBar</code> to create the peer for. + * + * @return The peer for the specified <code>MenuBar</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract MenuBarPeer createMenuBar(MenuBar target); + + /** + * Creates a peer object for the specified <code>Menu</code>. + * + * @param target The <code>Menu</code> to create the peer for. + * + * @return The peer for the specified <code>Menu</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract MenuPeer createMenu(Menu target); + + /** + * Creates a peer object for the specified <code>PopupMenu</code>. + * + * @param target The <code>PopupMenu</code> to create the peer for. + * + * @return The peer for the specified <code>PopupMenu</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract PopupMenuPeer createPopupMenu(PopupMenu target); + + /** + * Creates a peer object for the specified <code>MenuItem</code>. + * + * @param target The <code>MenuItem</code> to create the peer for. + * + * @return The peer for the specified <code>MenuItem</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract MenuItemPeer createMenuItem(MenuItem target); + + /** + * Creates a peer object for the specified <code>FileDialog</code>. + * + * @param target The <code>FileDialog</code> to create the peer for. + * + * @return The peer for the specified <code>FileDialog</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract FileDialogPeer createFileDialog(FileDialog target); + + /** + * Creates a peer object for the specified <code>CheckboxMenuItem</code>. + * + * @param target The <code>CheckboxMenuItem</code> to create the peer for. + * + * @return The peer for the specified <code>CheckboxMenuItem</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected abstract CheckboxMenuItemPeer + createCheckboxMenuItem(CheckboxMenuItem target); + + /** + * Creates a peer object for the specified <code>Component</code>. The + * peer returned by this method is not a native windowing system peer + * with its own native window. Instead, this method allows the component + * to draw on its parent window as a "lightweight" widget. + * + * @param target The <code>Component</code> to create the peer for. + * + * @return The peer for the specified <code>Component</code> object. + */ + protected LightweightPeer createComponent(Component target) + { + return new gnu.java.awt.peer.GLightweightPeer (target); + } + + /** + * Creates a peer object for the specified font name. + * + * @param name The font to create the peer for. + * @param style The font style to create the peer for. + * + * @return The peer for the specified font name. + * + * @deprecated + */ + protected abstract FontPeer getFontPeer(String name, int style); + + /** + * Copies the current system colors into the specified array. This is + * the interface used by the <code>SystemColor</code> class. Although + * this method fills in the array with some default colors a real Toolkit + * should override this method and provide real system colors for the + * native GUI platform. + * + * @param systemColors The array to copy the system colors into. + * It must be at least 26 elements. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + * + * @see java.awt.SystemColor + */ + protected void loadSystemColors(int systemColors[]) + { + systemColors[SystemColor.DESKTOP] = 0xFF005C5C; + systemColors[SystemColor.ACTIVE_CAPTION] = 0xFF000080; + systemColors[SystemColor.ACTIVE_CAPTION_TEXT] = 0xFFFFFFFF; + systemColors[SystemColor.ACTIVE_CAPTION_BORDER] = 0xFFC0C0C0; + systemColors[SystemColor.INACTIVE_CAPTION] = 0xFF808080; + systemColors[SystemColor.INACTIVE_CAPTION_TEXT] = 0xFFC0C0C0; + systemColors[SystemColor.INACTIVE_CAPTION_BORDER] = 0xFFC0C0C0; + systemColors[SystemColor.WINDOW] = 0xFFFFFFFF; + systemColors[SystemColor.WINDOW_BORDER] = 0xFF000000; + systemColors[SystemColor.WINDOW_TEXT] = 0xFF000000; + systemColors[SystemColor.MENU] = 0xFFC0C0C0; + systemColors[SystemColor.MENU_TEXT] = 0xFF000000; + systemColors[SystemColor.TEXT] = 0xFFC0C0C0; + systemColors[SystemColor.TEXT_TEXT] = 0xFF000000; + systemColors[SystemColor.TEXT_HIGHLIGHT] = 0xFF000090; + systemColors[SystemColor.TEXT_HIGHLIGHT_TEXT] = 0xFFFFFFFF; + systemColors[SystemColor.TEXT_INACTIVE_TEXT] = 0xFF808080; + systemColors[SystemColor.CONTROL] = 0xFFC0C0C0; + systemColors[SystemColor.CONTROL_TEXT] = 0xFF000000; + systemColors[SystemColor.CONTROL_HIGHLIGHT] = 0xFFFFFFFF; + systemColors[SystemColor.CONTROL_LT_HIGHLIGHT] = 0xFFE0E0E0; + systemColors[SystemColor.CONTROL_SHADOW] = 0xFF808080; + systemColors[SystemColor.CONTROL_DK_SHADOW] = 0xFF000000; + systemColors[SystemColor.SCROLLBAR] = 0xFFE0E0E0; + systemColors[SystemColor.INFO] = 0xFFE0E000; + systemColors[SystemColor.INFO_TEXT] = 0xFF000000; + } + + /** + * @since 1.4 + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public void setDynamicLayout(boolean dynamic) + { + } + + /** + * @since 1.4 + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + protected boolean isDynamicLayoutSet() + { + return false; + } + + /** + * @since 1.4 + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public boolean isDynamicLayoutActive() + { + return false; + } + + /** + * Returns the dimensions of the screen in pixels. + * + * @return The dimensions of the screen in pixels. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public abstract Dimension getScreenSize(); + + /** + * Returns the screen resolution in dots per square inch. + * + * @return The screen resolution in dots per square inch. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public abstract int getScreenResolution(); + + /** + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + * + * @since 1.4 + */ + public Insets getScreenInsets(GraphicsConfiguration gc) + { + return null; + } + + /** + * Returns the color model of the screen. + * + * @return The color model of the screen. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public abstract ColorModel getColorModel(); + + /** + * Returns the names of the available fonts. + * + * @return The names of the available fonts. + * + * @deprecated + */ + public abstract String[] getFontList(); + + /** + * Return the font metrics for the specified font + * + * @param name The name of the font to return metrics for. + * + * @return The requested font metrics. + * + * @deprecated + */ + public abstract FontMetrics getFontMetrics(Font name); + + /** + * Flushes any buffered data to the screen so that it is in sync with + * what the AWT system has drawn to it. + */ + public abstract void sync(); + + /** + * Returns an instance of the default toolkit. The default toolkit is + * the subclass of <code>Toolkit</code> specified in the system property + * <code>awt.toolkit</code>, or <code>gnu.java.awt.peer.gtk.GtkToolkit</code> + * if the property is not set. + * + * @return An instance of the system default toolkit. + * + * @throws AWTError If the toolkit cannot be loaded. + */ + public static Toolkit getDefaultToolkit() + { + if (toolkit != null) + return toolkit; + String toolkit_name = System.getProperty("awt.toolkit", + default_toolkit_name); + try + { + Class cls = Class.forName(toolkit_name); + Object obj = cls.newInstance(); + if (!(obj instanceof Toolkit)) + throw new AWTError(toolkit_name + " is not a subclass of " + + "java.awt.Toolkit"); + toolkit = (Toolkit) obj; + return toolkit; + } + catch (ThreadDeath death) + { + throw death; + } + catch (Throwable t) + { + AWTError e = new AWTError("Cannot load AWT toolkit: " + toolkit_name); + throw (AWTError) e.initCause(t); + } + } + + /** + * Returns an image from the specified file, which must be in a + * recognized format. Supported formats vary from toolkit to toolkit. + * + * @return name The name of the file to read the image from. + */ + public abstract Image getImage(String name); + + /** + * Returns an image from the specified URL, which must be in a + * recognized format. Supported formats vary from toolkit to toolkit. + * + * @return url The URl to read the image from. + */ + public abstract Image getImage(URL url); + + public abstract Image createImage(String filename); + + public abstract Image createImage(URL url); + + /** + * Readies an image to be rendered on the screen. The width and height + * values can be set to the default sizes for the image by passing -1 + * in those parameters. + * + * @param image The image to prepare for rendering. + * @param width The width of the image. + * @param height The height of the image. + * @param observer The observer to receive events about the preparation + * process. + * + * @return <code>true</code> if the image is already prepared for rendering, + * <code>false</code> otherwise. + */ + public abstract boolean prepareImage(Image image, int width, int height, + ImageObserver observer); + + /** + * Checks the status of specified image as it is being readied for + * rendering. + * + * @param image The image to prepare for rendering. + * @param width The width of the image. + * @param height The height of the image. + * @param observer The observer to receive events about the preparation + * process. + * + * @return A union of the bitmasks from + * <code>java.awt.image.ImageObserver</code> that indicates the current + * state of the imaging readying process. + */ + public abstract int checkImage(Image image, int width, int height, + ImageObserver observer); + + /** + * Creates an image using the specified <code>ImageProducer</code> + * + * @param producer The <code>ImageProducer</code> to create the image from. + * + * @return The created image. + */ + public abstract Image createImage(ImageProducer producer); + + /** + * Creates an image from the specified byte array. The array must be in + * a recognized format. Supported formats vary from toolkit to toolkit. + * + * @param data The raw image data. + * + * @return The created image. + */ + public Image createImage(byte[] data) + { + return createImage(data, 0, data.length); + } + + /** + * Creates an image from the specified portion of the byte array passed. + * The array must be in a recognized format. Supported formats vary from + * toolkit to toolkit. + * + * @param data The raw image data. + * @param offset The offset into the data where the image data starts. + * @param len The length of the image data. + * + * @return The created image. + */ + public abstract Image createImage(byte[] data, int offset, int len); + + /** + * Returns a instance of <code>PrintJob</code> for the specified + * arguments. + * + * @param frame The window initiating the print job. + * @param title The print job title. + * @param props The print job properties. + * + * @return The requested print job, or <code>null</code> if the job + * was cancelled. + * + * @exception NullPointerException If frame is null, + * or GraphicsEnvironment.isHeadless() returns true. + * @exception SecurityException If this thread is not allowed to initiate + * a print job request. + */ + public abstract PrintJob getPrintJob(Frame frame, String title, + Properties props); + + /** + * Returns a instance of <code>PrintJob</code> for the specified + * arguments. + * + * @param frame The window initiating the print job. + * @param title The print job title. + * @param jobAttr A set of job attributes which will control the print job. + * @param pageAttr A set of page attributes which will control the print job. + * + * @exception NullPointerException If frame is null, and either jobAttr is null + * or jobAttr.getDialog() returns JobAttributes.DialogType.NATIVE. + * @exception IllegalArgumentException If pageAttrspecifies differing cross + * feed and feed resolutions, or when GraphicsEnvironment.isHeadless() returns + * true. + * @exception SecurityException If this thread is not allowed to initiate + * a print job request. + * + * @since 1.3 + */ + public PrintJob getPrintJob(Frame frame, String title, + JobAttributes jobAttr, PageAttributes pageAttr) + { + return null; + } + + /** + * Causes a "beep" tone to be generated. + */ + public abstract void beep(); + + /** + * Returns the system clipboard. + * + * @return THe system clipboard. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public abstract Clipboard getSystemClipboard(); + + /** + * Gets the singleton instance of the system selection as a Clipboard object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + * + * @since 1.4 + */ + public Clipboard getSystemSelection() + { + return null; + } + + /** + * Returns the accelerator key mask for menu shortcuts. The default is + * <code>Event.CTRL_MASK</code>. A toolkit must override this method + * to change the default. + * + * @return The key mask for the menu accelerator key. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public int getMenuShortcutKeyMask() + { + return Event.CTRL_MASK; + } + + /** + * Returns whether the given locking key on the keyboard is currently in its + * "on" state. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + * @exception IllegalArgumentException If keyCode is not one of the valid keys. + * @exception UnsupportedOperationException If the host system doesn't allow + * getting the state of this key programmatically, or if the keyboard doesn't + * have this key. + */ + public boolean getLockingKeyState(int keyCode) + { + if (keyCode != KeyEvent.VK_CAPS_LOCK + && keyCode != KeyEvent.VK_NUM_LOCK + && keyCode != KeyEvent.VK_SCROLL_LOCK) + throw new IllegalArgumentException(); + + throw new UnsupportedOperationException(); + } + + /** + * Sets the state of the given locking key on the keyboard. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + * @exception IllegalArgumentException If keyCode is not one of the valid keys. + * @exception UnsupportedOperationException If the host system doesn't allow + * getting the state of this key programmatically, or if the keyboard doesn't + * have this key. + */ + public void setLockingKeyState(int keyCode, boolean on) + { + if (keyCode != KeyEvent.VK_CAPS_LOCK + && keyCode != KeyEvent.VK_NUM_LOCK + && keyCode != KeyEvent.VK_SCROLL_LOCK) + throw new IllegalArgumentException(); + + throw new UnsupportedOperationException(); + } + + /** + * Returns the native container object of the specified component. This + * method is necessary because the parent component might be a lightweight + * component. + * + * @param component The component to fetch the native container for. + * + * @return The native container object for this component. + */ + protected static Container getNativeContainer(Component component) + { + component = component.getParent(); + while (true) + { + if (component == null) + return null; + if (! (component instanceof Container)) + { + component = component.getParent(); + continue; + } + if (component.getPeer() instanceof LightweightPeer) + { + component = component.getParent(); + continue; + } + return (Container) component; + } + } + + /** + * Creates a new custom cursor object. + * + * @exception IndexOutOfBoundsException If the hotSpot values are outside + * the bounds of the cursor. + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public Cursor createCustomCursor(Image cursor, Point hotSpot, String name) + { + // Presumably the only reason this isn't abstract is for backwards + // compatibility? FIXME? + return null; + } + + /** + * Returns the supported cursor dimension which is closest to the + * desired sizes. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) + { + return new Dimension (0,0); + } + + /** + * Returns the maximum number of colors the Toolkit supports in a custom + * cursor palette. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public int getMaximumCursorColors() + { + return 0; + } + + /** + * Returns whether Toolkit supports this state for Frames. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + * + * @since 1.4 + */ + public boolean isFrameStateSupported(int state) + { + return false; + } + + /** + * Returns the value of the property with the specified name, or the + * default value if the property does not exist. + * + * @param key The name of the property to retrieve. + * @param def The default value of the property. + */ + public static String getProperty(String key, String def) + { + return props.getProperty(key, def); + } + + + /** + * Returns the event queue that is suitable for the calling context. + * + * <p>Despite the word “System” in the name of this + * method, a toolkit may provide different event queues for each + * applet. There is no guarantee that the same queue is shared + * system-wide. + * + * <p>The implementation first checks whether a + * SecurityManager has been installed. If so, its {@link + * java.lang.SecurityManager#checkAwtEventQueueAccess()} method gets + * called. The security manager will throw a SecurityException if it + * does not grant the permission to access the event queue. + * + * <p>Next, the call is delegated to {@link + * #getSystemEventQueueImpl()}. + * + * @return The event queue for this applet (or application). + * + * @throws SecurityException if a security manager has been + * installed, and it does not grant the permission to access the + * event queue. + */ + public final EventQueue getSystemEventQueue() + { + SecurityManager sm; + + sm = System.getSecurityManager(); + if (sm != null) + sm.checkAwtEventQueueAccess(); + + return getSystemEventQueueImpl(); + } + + + /** + * Returns the event queue that is suitable for the calling context. + * + * <p>Despite the word “System” in the name of this + * method, a toolkit may provide different event queues for each + * applet. There is no guarantee that the same queue is shared + * system-wide. + * + * <p>No security checks are performed, which is why this method + * may only be called by Toolkits. + * + * @see #getSystemEventQueue() + */ + protected abstract EventQueue getSystemEventQueueImpl(); + + + /** + * @since 1.3 + */ + public abstract DragSourceContextPeer + createDragSourceContextPeer(DragGestureEvent e); + + /** + * @since 1.3 + */ + public DragGestureRecognizer + createDragGestureRecognizer(Class recognizer, DragSource ds, + Component comp, int actions, + DragGestureListener l) + { + return null; + } + + public final Object getDesktopProperty(String propertyName) + { + return desktopProperties.get(propertyName); + } + + protected final void setDesktopProperty(String name, Object newValue) + { + Object oldValue = getDesktopProperty(name); + desktopProperties.put(name, newValue); + desktopPropsSupport.firePropertyChange(name, oldValue, newValue); + } + + protected Object lazilyLoadDesktopProperty(String name) + { + // FIXME - what is this?? + return null; + } + + protected void initializeDesktopProperties() + { + // Overridden by toolkit implementation? + } + + public void addPropertyChangeListener(String name, + PropertyChangeListener pcl) + { + desktopPropsSupport.addPropertyChangeListener(name, pcl); + } + + public void removePropertyChangeListener(String name, + PropertyChangeListener pcl) + { + desktopPropsSupport.removePropertyChangeListener(name, pcl); + } + + /** + * @since 1.4 + */ + public PropertyChangeListener[] getPropertyChangeListeners() + { + return desktopPropsSupport.getPropertyChangeListeners(); + } + + /** + * @since 1.4 + */ + public PropertyChangeListener[] getPropertyChangeListeners(String name) + { + return desktopPropsSupport.getPropertyChangeListeners(name); + } + + public void addAWTEventListener(AWTEventListener listener, long eventMask) + { + // SecurityManager s = System.getSecurityManager(); + // if (s != null) + // s.checkPermission(AWTPermission("listenToAllAWTEvents")); + // FIXME + } + + public void removeAWTEventListener(AWTEventListener listener) + { + // FIXME + } + + /** + * @since 1.4 + */ + public AWTEventListener[] getAWTEventListeners() + { + return null; + } + + /** + * @since 1.4 + */ + public AWTEventListener[] getAWTEventListeners(long mask) + { + return null; + } + + /** + * @since 1.3 + */ + public abstract Map mapInputMethodHighlight(InputMethodHighlight highlight); +} // class Toolkit diff --git a/libjava/classpath/java/awt/Transparency.java b/libjava/classpath/java/awt/Transparency.java new file mode 100644 index 0000000..8885871 --- /dev/null +++ b/libjava/classpath/java/awt/Transparency.java @@ -0,0 +1,67 @@ +/* Transparency.java -- common transparency modes in graphics + Copyright (C) 2000, 2002, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt; + +/** + * A common transparency mode for layering graphics. + * + * @author Warren Levy (warrenl@cygnus.com) + * @since 1.1 + * @status updated to 1.4 + */ +public interface Transparency +{ + /** Image data which is completely opaque, for an alpha value of 1.0. */ + int OPAQUE = 1; + + /** + * Image data which is either completely opaque or transparent, for an + * exact integer alpha value. + */ + int BITMASK = 2; + + /** Image data which is translucent, for a non-integer alpha value. */ + int TRANSLUCENT = 3; + + /** + * Return the transparency type. + * + * @return One of {@link #OPAQUE}, {@link #BITMASK}, or {@link #TRANSLUCENT}. + */ + int getTransparency(); +} // interface Transparency diff --git a/libjava/classpath/java/awt/Window.java b/libjava/classpath/java/awt/Window.java new file mode 100644 index 0000000..e26c4e3 --- /dev/null +++ b/libjava/classpath/java/awt/Window.java @@ -0,0 +1,1125 @@ +/* Window.java -- + Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.awt.event.ComponentEvent; +import java.awt.event.FocusEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.awt.event.WindowListener; +import java.awt.event.WindowStateListener; +import java.awt.image.BufferStrategy; +import java.awt.peer.WindowPeer; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.util.EventListener; +import java.util.Iterator; +import java.util.Locale; +import java.util.ResourceBundle; +import java.util.Vector; + +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; + +/** + * This class represents a top-level window with no decorations. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Warren Levy (warrenl@cygnus.com) + */ +public class Window extends Container implements Accessible +{ + private static final long serialVersionUID = 4497834738069338734L; + + // Serialized fields, from Sun's serialization spec. + private String warningString = null; + private int windowSerializedDataVersion = 0; // FIXME + /** @since 1.2 */ + // private FocusManager focusMgr; // FIXME: what is this? + /** @since 1.2 */ + private int state = 0; + /** @since 1.4 */ + private boolean focusableWindowState = true; + + // A list of other top-level windows owned by this window. + private transient Vector ownedWindows = new Vector(); + + private transient WindowListener windowListener; + private transient WindowFocusListener windowFocusListener; + private transient WindowStateListener windowStateListener; + private transient GraphicsConfiguration graphicsConfiguration; + + private transient boolean shown; + + // This is package-private to avoid an accessor method. + transient Component windowFocusOwner; + + /* + * The number used to generate the name returned by getName. + */ + private static transient long next_window_number; + + protected class AccessibleAWTWindow extends AccessibleAWTContainer + { + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.WINDOW; + } + + public AccessibleStateSet getAccessibleStateSet() + { + AccessibleStateSet states = super.getAccessibleStateSet(); + if (isActive()) + states.add(AccessibleState.ACTIVE); + return states; + } + } + + /** + * This (package access) constructor is used by subclasses that want + * to build windows that do not have parents. Eg. toplevel + * application frames. Subclasses cannot call super(null), since + * null is an illegal argument. + */ + Window() + { + visible = false; + // Windows are the only Containers that default to being focus + // cycle roots. + focusCycleRoot = true; + setLayout(new BorderLayout()); + + addWindowFocusListener (new WindowAdapter () + { + public void windowGainedFocus (WindowEvent event) + { + if (windowFocusOwner != null) + { + // FIXME: move this section and the other similar + // sections in Component into a separate method. + EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue (); + synchronized (eq) + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + Component currentFocusOwner = manager.getGlobalPermanentFocusOwner (); + if (currentFocusOwner != null) + { + eq.postEvent (new FocusEvent (currentFocusOwner, FocusEvent.FOCUS_LOST, + false, windowFocusOwner)); + eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED, + false, currentFocusOwner)); + } + else + eq.postEvent (new FocusEvent (windowFocusOwner, FocusEvent.FOCUS_GAINED, false)); + } + } + } + }); + } + + Window(GraphicsConfiguration gc) + { + this(); + graphicsConfiguration = gc; + } + + /** + * Initializes a new instance of <code>Window</code> with the specified + * parent. The window will initially be invisible. + * + * @param owner The owning <code>Frame</code> of this window. + * + * @exception IllegalArgumentException If the owner's GraphicsConfiguration + * is not from a screen device, or if owner is null; this exception is always + * thrown when GraphicsEnvironment.isHeadless returns true. + */ + public Window(Frame owner) + { + this (owner, owner.getGraphicsConfiguration ()); + } + + /** + * Initializes a new instance of <code>Window</code> with the specified + * parent. The window will initially be invisible. + * + * @exception IllegalArgumentException If the owner's GraphicsConfiguration + * is not from a screen device, or if owner is null; this exception is always + * thrown when GraphicsEnvironment.isHeadless returns true. + * + * @since 1.2 + */ + public Window(Window owner) + { + this (owner, owner.getGraphicsConfiguration ()); + } + + /** + * Initializes a new instance of <code>Window</code> with the specified + * parent. The window will initially be invisible. + * + * @exception IllegalArgumentException If owner is null or if gc is not from a + * screen device; this exception is always thrown when + * GraphicsEnvironment.isHeadless returns true. + * + * @since 1.3 + */ + public Window(Window owner, GraphicsConfiguration gc) + { + this (); + + synchronized (getTreeLock()) + { + if (owner == null) + throw new IllegalArgumentException ("owner must not be null"); + + parent = owner; + owner.ownedWindows.add(new WeakReference(this)); + } + + // FIXME: make this text visible in the window. + SecurityManager s = System.getSecurityManager(); + if (s != null && ! s.checkTopLevelWindow(this)) + warningString = System.getProperty("awt.appletWarning"); + + if (gc != null + && gc.getDevice().getType() != GraphicsDevice.TYPE_RASTER_SCREEN) + throw new IllegalArgumentException ("gc must be from a screen device"); + + if (gc == null) + graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice() + .getDefaultConfiguration(); + else + graphicsConfiguration = gc; + } + + GraphicsConfiguration getGraphicsConfigurationImpl() + { + if (graphicsConfiguration != null) + return graphicsConfiguration; + + return super.getGraphicsConfigurationImpl(); + } + + /** + * Creates the native peer for this window. + */ + public void addNotify() + { + if (peer == null) + peer = getToolkit().createWindow(this); + super.addNotify(); + } + + /** + * Relays out this window's child components at their preferred size. + * + * @specnote pack() doesn't appear to be called internally by show(), so + * we duplicate some of the functionality. + */ + public void pack() + { + if (parent != null && !parent.isDisplayable()) + parent.addNotify(); + if (peer == null) + addNotify(); + + setSize(getPreferredSize()); + + validate(); + } + + /** + * Shows on-screen this window and any of its owned windows for whom + * isVisible returns true. + */ + public void show() + { + if (parent != null && !parent.isDisplayable()) + parent.addNotify(); + if (peer == null) + addNotify(); + + // Show visible owned windows. + synchronized (getTreeLock()) + { + Iterator e = ownedWindows.iterator(); + while(e.hasNext()) + { + Window w = (Window)(((Reference) e.next()).get()); + if (w != null) + { + if (w.isVisible()) + w.getPeer().setVisible(true); + } + else + // Remove null weak reference from ownedWindows. + // Unfortunately this can't be done in the Window's + // finalize method because there is no way to guarantee + // synchronous access to ownedWindows there. + e.remove(); + } + } + validate(); + super.show(); + toFront(); + + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + manager.setGlobalFocusedWindow (this); + + if (!shown) + { + FocusTraversalPolicy policy = getFocusTraversalPolicy (); + Component initialFocusOwner = null; + + if (policy != null) + initialFocusOwner = policy.getInitialComponent (this); + + if (initialFocusOwner != null) + initialFocusOwner.requestFocusInWindow (); + + shown = true; + } + } + + public void hide() + { + // Hide visible owned windows. + synchronized (getTreeLock ()) + { + Iterator e = ownedWindows.iterator(); + while(e.hasNext()) + { + Window w = (Window)(((Reference) e.next()).get()); + if (w != null) + { + if (w.isVisible() && w.getPeer() != null) + w.getPeer().setVisible(false); + } + else + e.remove(); + } + } + super.hide(); + } + + public boolean isDisplayable() + { + if (super.isDisplayable()) + return true; + return peer != null; + } + + /** + * Destroys any resources associated with this window. This includes + * all components in the window and all owned top-level windows. + */ + public void dispose() + { + hide(); + + synchronized (getTreeLock ()) + { + Iterator e = ownedWindows.iterator(); + while(e.hasNext()) + { + Window w = (Window)(((Reference) e.next()).get()); + if (w != null) + w.dispose(); + else + // Remove null weak reference from ownedWindows. + e.remove(); + } + + for (int i = 0; i < ncomponents; ++i) + component[i].removeNotify(); + this.removeNotify(); + + // Post a WINDOW_CLOSED event. + WindowEvent we = new WindowEvent(this, WindowEvent.WINDOW_CLOSED); + getToolkit().getSystemEventQueue().postEvent(we); + } + } + + /** + * Sends this window to the back so that all other windows display in + * front of it. + */ + public void toBack() + { + if (peer != null) + { + WindowPeer wp = (WindowPeer) peer; + wp.toBack(); + } + } + + /** + * Brings this window to the front so that it displays in front of + * any other windows. + */ + public void toFront() + { + if (peer != null) + { + WindowPeer wp = (WindowPeer) peer; + wp.toFront(); + } + } + + /** + * Returns the toolkit used to create this window. + * + * @return The toolkit used to create this window. + * + * @specnote Unlike Component.getToolkit, this implementation always + * returns the value of Toolkit.getDefaultToolkit(). + */ + public Toolkit getToolkit() + { + return Toolkit.getDefaultToolkit(); + } + + /** + * Returns the warning string that will be displayed if this window is + * popped up by an unsecure applet or application. + * + * @return The unsecure window warning message. + */ + public final String getWarningString() + { + return warningString; + } + + /** + * Returns the locale that this window is configured for. + * + * @return The locale this window is configured for. + */ + public Locale getLocale() + { + return locale == null ? Locale.getDefault() : locale; + } + + /* + /** @since 1.2 + public InputContext getInputContext() + { + // FIXME + } + */ + + /** + * Sets the cursor for this window to the specifiec cursor. + * + * @param cursor The new cursor for this window. + */ + public void setCursor(Cursor cursor) + { + super.setCursor(cursor); + } + + public Window getOwner() + { + return (Window) parent; + } + + /** @since 1.2 */ + public Window[] getOwnedWindows() + { + Window [] trimmedList; + synchronized (getTreeLock ()) + { + // Windows with non-null weak references in ownedWindows. + Window [] validList = new Window [ownedWindows.size()]; + + Iterator e = ownedWindows.iterator(); + int numValid = 0; + while (e.hasNext()) + { + Window w = (Window)(((Reference) e.next()).get()); + if (w != null) + validList[numValid++] = w; + else + // Remove null weak reference from ownedWindows. + e.remove(); + } + + if (numValid != validList.length) + { + trimmedList = new Window [numValid]; + System.arraycopy (validList, 0, trimmedList, 0, numValid); + } + else + trimmedList = validList; + } + return trimmedList; + } + + /** + * Adds the specified listener to the list of <code>WindowListeners</code> + * that will receive events for this window. + * + * @param listener The <code>WindowListener</code> to add. + */ + public synchronized void addWindowListener(WindowListener listener) + { + windowListener = AWTEventMulticaster.add(windowListener, listener); + } + + /** + * Removes the specified listener from the list of + * <code>WindowListeners</code> that will receive events for this window. + * + * @param listener The <code>WindowListener</code> to remove. + */ + public synchronized void removeWindowListener(WindowListener listener) + { + windowListener = AWTEventMulticaster.remove(windowListener, listener); + } + + /** + * Returns an array of all the window listeners registered on this window. + * + * @since 1.4 + */ + public synchronized WindowListener[] getWindowListeners() + { + return (WindowListener[]) + AWTEventMulticaster.getListeners(windowListener, + WindowListener.class); + } + + /** + * Returns an array of all the window focus listeners registered on this + * window. + * + * @since 1.4 + */ + public synchronized WindowFocusListener[] getWindowFocusListeners() + { + return (WindowFocusListener[]) + AWTEventMulticaster.getListeners(windowFocusListener, + WindowFocusListener.class); + } + + /** + * Returns an array of all the window state listeners registered on this + * window. + * + * @since 1.4 + */ + public synchronized WindowStateListener[] getWindowStateListeners() + { + return (WindowStateListener[]) + AWTEventMulticaster.getListeners(windowStateListener, + WindowStateListener.class); + } + + /** + * Adds the specified listener to this window. + */ + public void addWindowFocusListener (WindowFocusListener wfl) + { + windowFocusListener = AWTEventMulticaster.add (windowFocusListener, wfl); + } + + /** + * Adds the specified listener to this window. + * + * @since 1.4 + */ + public void addWindowStateListener (WindowStateListener wsl) + { + windowStateListener = AWTEventMulticaster.add (windowStateListener, wsl); + } + + /** + * Removes the specified listener from this window. + */ + public void removeWindowFocusListener (WindowFocusListener wfl) + { + windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl); + } + + /** + * Removes the specified listener from this window. + * + * @since 1.4 + */ + public void removeWindowStateListener (WindowStateListener wsl) + { + windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl); + } + + /** + * Returns an array of all the objects currently registered as FooListeners + * upon this Window. FooListeners are registered using the addFooListener + * method. + * + * @exception ClassCastException If listenerType doesn't specify a class or + * interface that implements java.util.EventListener. + * + * @since 1.3 + */ + public EventListener[] getListeners(Class listenerType) + { + if (listenerType == WindowListener.class) + return getWindowListeners(); + return super.getListeners(listenerType); + } + + void dispatchEventImpl(AWTEvent e) + { + // Make use of event id's in order to avoid multiple instanceof tests. + if (e.id <= WindowEvent.WINDOW_LAST + && e.id >= WindowEvent.WINDOW_FIRST + && (windowListener != null + || windowFocusListener != null + || windowStateListener != null + || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)) + processEvent(e); + else + super.dispatchEventImpl(e); + } + + /** + * Processes the specified event for this window. If the event is an + * instance of <code>WindowEvent</code>, then + * <code>processWindowEvent()</code> is called to process the event, + * otherwise the superclass version of this method is invoked. + * + * @param evt The event to process. + */ + protected void processEvent(AWTEvent evt) + { + if (evt instanceof WindowEvent) + processWindowEvent((WindowEvent) evt); + else + super.processEvent(evt); + } + + /** + * Dispatches this event to any listeners that are listening for + * <code>WindowEvents</code> on this window. This method only gets + * invoked if it is enabled via <code>enableEvents()</code> or if + * a listener has been added. + * + * @param evt The event to process. + */ + protected void processWindowEvent(WindowEvent evt) + { + int id = evt.getID(); + + if (id == WindowEvent.WINDOW_GAINED_FOCUS + || id == WindowEvent.WINDOW_LOST_FOCUS) + processWindowFocusEvent (evt); + else if (id == WindowEvent.WINDOW_STATE_CHANGED) + processWindowStateEvent (evt); + else + { + if (windowListener != null) + { + switch (evt.getID()) + { + case WindowEvent.WINDOW_ACTIVATED: + windowListener.windowActivated(evt); + break; + + case WindowEvent.WINDOW_CLOSED: + windowListener.windowClosed(evt); + break; + + case WindowEvent.WINDOW_CLOSING: + windowListener.windowClosing(evt); + break; + + case WindowEvent.WINDOW_DEACTIVATED: + windowListener.windowDeactivated(evt); + break; + + case WindowEvent.WINDOW_DEICONIFIED: + windowListener.windowDeiconified(evt); + break; + + case WindowEvent.WINDOW_ICONIFIED: + windowListener.windowIconified(evt); + break; + + case WindowEvent.WINDOW_OPENED: + windowListener.windowOpened(evt); + break; + + default: + break; + } + } + } + } + + /** + * Identifies if this window is active. The active window is a Frame or + * Dialog that has focus or owns the active window. + * + * @return true if active, else false. + * @since 1.4 + */ + public boolean isActive() + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + return manager.getActiveWindow() == this; + } + + /** + * Identifies if this window is focused. A window is focused if it is the + * focus owner or it contains the focus owner. + * + * @return true if focused, else false. + * @since 1.4 + */ + public boolean isFocused() + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + return manager.getFocusedWindow() == this; + } + + /** + * Returns the child window that has focus if this window is active. + * This method returns <code>null</code> if this window is not active + * or no children have focus. + * + * @return The component that has focus, or <code>null</code> if no + * component has focus. + */ + public Component getFocusOwner () + { + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); + + Window activeWindow = manager.getActiveWindow (); + + // The currently-focused Component belongs to the active Window. + if (activeWindow == this) + return manager.getFocusOwner (); + else + return windowFocusOwner; + } + + /** + * Set the focus owner for this window. This method is used to + * remember which component was focused when this window lost + * top-level focus, so that when it regains top-level focus the same + * child component can be refocused. + * + * @param windowFocusOwner the component in this window that owns + * the focus. + */ + void setFocusOwner (Component windowFocusOwner) + { + this.windowFocusOwner = windowFocusOwner; + } + + /** + * Post a Java 1.0 event to the event queue. + * + * @param e The event to post. + * + * @deprecated + */ + public boolean postEvent(Event e) + { + return handleEvent (e); + } + + /** + * Tests whether or not this window is visible on the screen. + * + * In contrast to the normal behaviour of Container, which is that + * a container is showing if its parent is visible and showing, a Window + * is even showing, if its parent (i.e. an invisible Frame) is not showing. + * + * @return <code>true</code> if this window is visible, <code>false</code> + * otherwise. + */ + public boolean isShowing() + { + return isVisible(); + } + + public void setLocationRelativeTo (Component c) + { + if (c == null || !c.isShowing ()) + { + int x = 0; + int y = 0; + + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment (); + Point center = ge.getCenterPoint (); + x = center.x - (width / 2); + y = center.y - (height / 2); + setLocation (x, y); + } + // FIXME: handle case where component is non-null. + } + + /** + * A BltBufferStrategy for windows. + */ + private class WindowBltBufferStrategy extends BltBufferStrategy + { + /** + * Creates a block transfer strategy for this window. + * + * @param numBuffers the number of buffers in this strategy + * @param accelerated true if the buffer should be accelerated, + * false otherwise + */ + WindowBltBufferStrategy(int numBuffers, boolean accelerated) + { + super(numBuffers, + new BufferCapabilities(new ImageCapabilities(accelerated), + new ImageCapabilities(accelerated), + BufferCapabilities.FlipContents.COPIED)); + } + } + + /** + * A FlipBufferStrategy for windows. + */ + private class WindowFlipBufferStrategy extends FlipBufferStrategy + { + /** + * Creates a flip buffer strategy for this window. + * + * @param numBuffers the number of buffers in this strategy + * + * @throws AWTException if the requested number of buffers is not + * supported + */ + WindowFlipBufferStrategy(int numBuffers) + throws AWTException + { + super(numBuffers, + new BufferCapabilities(new ImageCapabilities(true), + new ImageCapabilities(true), + BufferCapabilities.FlipContents.COPIED)); + } + } + + /** + * Creates a buffering strategy that manages how this window is + * repainted. This method attempts to create the optimum strategy + * based on the desired number of buffers. Hardware or software + * acceleration may be used. + * + * createBufferStrategy attempts different levels of optimization, + * but guarantees that some strategy with the requested number of + * buffers will be created even if it is not optimal. First it + * attempts to create a page flipping strategy, then an accelerated + * blitting strategy, then an unaccelerated blitting strategy. + * + * Calling this method causes any existing buffer strategy to be + * destroyed. + * + * @param numBuffers the number of buffers in this strategy + * + * @throws IllegalArgumentException if requested number of buffers + * is less than one + * @throws IllegalStateException if this window is not displayable + * + * @since 1.4 + */ + public void createBufferStrategy(int numBuffers) + { + if (numBuffers < 1) + throw new IllegalArgumentException("Window.createBufferStrategy: number" + + " of buffers is less than one"); + + if (!isDisplayable()) + throw new IllegalStateException("Window.createBufferStrategy: window is" + + " not displayable"); + + BufferStrategy newStrategy = null; + + // try a flipping strategy + try + { + newStrategy = new WindowFlipBufferStrategy(numBuffers); + } + catch (AWTException e) + { + } + + // fall back to an accelerated blitting strategy + if (newStrategy == null) + newStrategy = new WindowBltBufferStrategy(numBuffers, true); + + bufferStrategy = newStrategy; + } + + /** + * Creates a buffering strategy that manages how this window is + * repainted. This method attempts to create a strategy based on + * the specified capabilities and throws an exception if the + * requested strategy is not supported. + * + * Calling this method causes any existing buffer strategy to be + * destroyed. + * + * @param numBuffers the number of buffers in this strategy + * @param caps the requested buffering capabilities + * + * @throws AWTException if the requested capabilities are not + * supported + * @throws IllegalArgumentException if requested number of buffers + * is less than one or if caps is null + * + * @since 1.4 + */ + public void createBufferStrategy(int numBuffers, + BufferCapabilities caps) + { + if (numBuffers < 1) + throw new IllegalArgumentException("Window.createBufferStrategy: number" + + " of buffers is less than one"); + + if (caps == null) + throw new IllegalArgumentException("Window.createBufferStrategy:" + + " capabilities object is null"); + + // a flipping strategy was requested + if (caps.isPageFlipping()) + { + try + { + bufferStrategy = new WindowFlipBufferStrategy(numBuffers); + } + catch (AWTException e) + { + } + } + else + bufferStrategy = new WindowBltBufferStrategy(numBuffers, true); + } + + /** + * Returns the buffer strategy used by the window. + * + * @return the buffer strategy. + * @since 1.4 + */ + public BufferStrategy getBufferStrategy() + { + return bufferStrategy; + } + + /** + * @since 1.2 + * + * @deprecated + */ + public void applyResourceBundle(ResourceBundle rb) + { + throw new Error ("Not implemented"); + } + + /** + * @since 1.2 + * + * @deprecated + */ + public void applyResourceBundle(String rbName) + { + ResourceBundle rb = ResourceBundle.getBundle(rbName, Locale.getDefault(), + ClassLoader.getSystemClassLoader()); + if (rb != null) + applyResourceBundle(rb); + } + + /** + * Gets the AccessibleContext associated with this <code>Window</code>. + * The context is created, if necessary. + * + * @return the associated context + */ + public AccessibleContext getAccessibleContext() + { + /* Create the context if this is the first request */ + if (accessibleContext == null) + accessibleContext = new AccessibleAWTWindow(); + return accessibleContext; + } + + /** + * Get graphics configuration. The implementation for Window will + * not ask any parent containers, since Window is a toplevel + * window and not actually embedded in the parent component. + */ + public GraphicsConfiguration getGraphicsConfiguration() + { + if (graphicsConfiguration != null) return graphicsConfiguration; + if (peer != null) return peer.getGraphicsConfiguration(); + return null; + } + + protected void processWindowFocusEvent(WindowEvent event) + { + if (windowFocusListener != null) + { + switch (event.getID ()) + { + case WindowEvent.WINDOW_GAINED_FOCUS: + windowFocusListener.windowGainedFocus (event); + break; + + case WindowEvent.WINDOW_LOST_FOCUS: + windowFocusListener.windowLostFocus (event); + break; + + default: + break; + } + } + } + + /** + * @since 1.4 + */ + protected void processWindowStateEvent(WindowEvent event) + { + if (windowStateListener != null + && event.getID () == WindowEvent.WINDOW_STATE_CHANGED) + windowStateListener.windowStateChanged (event); + } + + /** + * Returns whether this <code>Window</code> can get the focus or not. + * + * @since 1.4 + */ + public final boolean isFocusableWindow () + { + if (getFocusableWindowState () == false) + return false; + + if (this instanceof Dialog + || this instanceof Frame) + return true; + + // FIXME: Implement more possible cases for returning true. + + return false; + } + + /** + * Returns the value of the focusableWindowState property. + * + * @since 1.4 + */ + public boolean getFocusableWindowState () + { + return focusableWindowState; + } + + /** + * Sets the value of the focusableWindowState property. + * + * @since 1.4 + */ + public void setFocusableWindowState (boolean focusableWindowState) + { + this.focusableWindowState = focusableWindowState; + } + + // setBoundsCallback is needed so that when a user moves a window, + // the Window's location can be updated without calling the peer's + // setBounds method. When a user moves a window the peer window's + // location is updated automatically and the windowing system sends + // a message back to the application informing it of its updated + // dimensions. We must update the AWT Window class with these new + // dimensions. But we don't want to call the peer's setBounds + // method, because the peer's dimensions have already been updated. + // (Under X, having this method prevents Configure event loops when + // moving windows: Component.setBounds -> peer.setBounds -> + // postConfigureEvent -> Component.setBounds -> ... In some cases + // Configure event loops cause windows to jitter back and forth + // continuously). + void setBoundsCallback (int x, int y, int w, int h) + { + if (this.x == x && this.y == y && width == w && height == h) + return; + invalidate(); + boolean resized = width != w || height != h; + boolean moved = this.x != x || this.y != y; + this.x = x; + this.y = y; + width = w; + height = h; + if (resized && isShowing ()) + { + ComponentEvent ce = + new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED); + getToolkit().getSystemEventQueue().postEvent(ce); + } + if (moved && isShowing ()) + { + ComponentEvent ce = + new ComponentEvent(this, ComponentEvent.COMPONENT_MOVED); + getToolkit().getSystemEventQueue().postEvent(ce); + } + } + + /** + * Generate a unique name for this window. + * + * @return A unique name for this window. + */ + String generateName() + { + return "win" + getUniqueLong(); + } + + private static synchronized long getUniqueLong() + { + return next_window_number++; + } +} diff --git a/libjava/classpath/java/awt/color/CMMException.java b/libjava/classpath/java/awt/color/CMMException.java new file mode 100644 index 0000000..ab328ec --- /dev/null +++ b/libjava/classpath/java/awt/color/CMMException.java @@ -0,0 +1,63 @@ +/* CMMException.java -- error in the native CMM + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.color; + +/** + * Thrown when there is an error in the native CMM. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @status updated to 1.4 + */ +public class CMMException extends RuntimeException +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 5775558044142994965L; + + /** + * Create a new instance with a specified detailed error message. + * + * @param message the message + */ + public CMMException(String message) + { + super(message); + } +} // class CMMException diff --git a/libjava/classpath/java/awt/color/ColorSpace.java b/libjava/classpath/java/awt/color/ColorSpace.java new file mode 100644 index 0000000..79369da --- /dev/null +++ b/libjava/classpath/java/awt/color/ColorSpace.java @@ -0,0 +1,183 @@ +/* ColorSpace.java -- transforms between color spaces + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.color; + +import java.io.Serializable; + +/** + * NEEDS DOCUMENTATION + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + * @since 1.2 + */ +public abstract class ColorSpace implements Serializable +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = -409452704308689724L; + + public static final int TYPE_XYZ = 0; + public static final int TYPE_Lab = 1; + public static final int TYPE_Luv = 2; + public static final int TYPE_YCbCr = 3; + public static final int TYPE_Yxy = 4; + public static final int TYPE_RGB = 5; + public static final int TYPE_GRAY = 6; + public static final int TYPE_HSV = 7; + public static final int TYPE_HLS = 8; + public static final int TYPE_CMYK = 9; + // mysterious gap in the enumeration sequenece + public static final int TYPE_CMY = 11; + public static final int TYPE_2CLR = 12; + public static final int TYPE_3CLR = 13; + public static final int TYPE_4CLR = 14; + public static final int TYPE_5CLR = 15; + public static final int TYPE_6CLR = 16; + public static final int TYPE_7CLR = 17; + public static final int TYPE_8CLR = 18; + public static final int TYPE_9CLR = 19; + public static final int TYPE_ACLR = 20; + public static final int TYPE_BCLR = 21; + public static final int TYPE_CCLR = 22; + public static final int TYPE_DCLR = 23; + public static final int TYPE_ECLR = 24; + public static final int TYPE_FCLR = 25; + + public static final int CS_sRGB = 1000; + public static final int CS_LINEAR_RGB = 1004; + public static final int CS_CIEXYZ = 1001; + public static final int CS_PYCC = 1002; + public static final int CS_GRAY = 1003; + + private static final int CS_BASE = CS_sRGB; + private static final int CS_END = CS_LINEAR_RGB + 1; + private static final int CS_COUNT = CS_END - CS_BASE; + + // Instances are lazily instantiated + private static final ColorSpace[] INSTANCES = new ColorSpace[CS_COUNT]; + + /** + * @serial + */ + // Visible in subclass. + final int type; + + /** + * @serial + */ + // Visible in subclass. + final int numComponents; + + protected ColorSpace(int type, int numcomponents) + { + this.type = type; + numComponents = numcomponents; + } + + public static ColorSpace getInstance(int colorspace) + { + if ((colorspace >= CS_BASE) && (colorspace < CS_END)) + { + int instanceIndex = colorspace - CS_BASE; + if (INSTANCES[instanceIndex] == null) + { + ICC_Profile profile = new ICC_Profile(colorspace); + INSTANCES[instanceIndex] = new ICC_ColorSpace(profile); + } + return INSTANCES[instanceIndex]; + } + throw new IllegalArgumentException("unknown/unsupported colorspace"); + } + + public boolean isCS_sRGB() + { + return type == CS_sRGB; + } + + /** + * Transforms a color value assumed to be in this ColorSpace into a value in + * the default CS_sRGB color space. + * + * @exception ArrayIndexOutOfBoundsException If array length is not at least + * the number of components in this ColorSpace. + */ + public abstract float[] toRGB(float[] colorvalue); + + public abstract float[] fromRGB(float[] rgbvalue); + + public abstract float[] toCIEXYZ(float[] colorvalue); + + public abstract float[] fromCIEXYZ(float[] colorvalue); + + public int getType() + { + return type; + } + + public int getNumComponents() + { + return numComponents; + } + + public String getName(int idx) + { + return "type " + type; + } + + /** + * @since 1.4 + */ + public float getMinValue(int idx) + { + if (idx < 0 || idx >= numComponents) + throw new IllegalArgumentException(); + return 0; + } + + /** + * @since 1.4 + */ + public float getMaxValue(int idx) + { + if (idx < 0 || idx >= numComponents) + throw new IllegalArgumentException(); + return 1; + } +} // class ColorSpace diff --git a/libjava/classpath/java/awt/color/ICC_ColorSpace.java b/libjava/classpath/java/awt/color/ICC_ColorSpace.java new file mode 100644 index 0000000..b50048c --- /dev/null +++ b/libjava/classpath/java/awt/color/ICC_ColorSpace.java @@ -0,0 +1,314 @@ +/* ICC_ColorSpace.java -- the canonical color space implementation + Copyright (C) 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.color; + +import gnu.java.awt.color.CieXyzConverter; +import gnu.java.awt.color.ClutProfileConverter; +import gnu.java.awt.color.ColorSpaceConverter; +import gnu.java.awt.color.GrayProfileConverter; +import gnu.java.awt.color.GrayScaleConverter; +import gnu.java.awt.color.LinearRGBConverter; +import gnu.java.awt.color.PyccConverter; +import gnu.java.awt.color.RgbProfileConverter; +import gnu.java.awt.color.SrgbConverter; + +import java.io.IOException; +import java.io.ObjectInputStream; + +/** + * ICC_ColorSpace - an implementation of ColorSpace + * + * While an ICC_Profile class abstracts the data in an ICC profile file + * an ICC_ColorSpace performs the color space conversions defined by + * an ICC_Profile instance. + * + * Typically, an ICC_Profile will either be created using getInstance, + * either from the built-in colorspaces, or from an ICC profile file. + * Then a ICC_Colorspace will be used to perform transforms from the + * device colorspace to and from the profile color space. + * + * The PCS used by ColorSpace is CIE XYZ relative a D50 white point. + * (Profiles using a CIE Lab PCS will have their input and output converted + * to D50 CIE XYZ accordingly. + * + * Note that a valid profile may not contain transforms in both directions, + * in which case the output may be undefined. + * All built-in colorspaces have bidirectional transforms, but developers + * using an ICC profile file may want to check the profile class using + * the ICC_Profile.getProfileClass() method. Input class profiles are + * guaranteed to have transforms to the PCS, output class profiles are + * guaranteed to have transforms from the PCS to device space. + * + * @author Sven de Marothy + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + * @since 1.2 + */ +public class ICC_ColorSpace extends ColorSpace +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 3455889114070431483L; + + /** + * @serial + */ + private ICC_Profile thisProfile; + + /** + * @serial + */ + private float[] minVal; + + /** + * @serial + */ + private float[] maxVal; + + /** + * @serial + */ + private float[] diffMinMax; + + /** + * @serial + */ + private float[] invDiffMinMax; + + /** + * @serial + */ + private boolean needScaleInit; + + /** + * Tells us if the PCS is CIE LAB (must be CIEXYZ otherwise) + */ + private transient int type; + private transient int nComponents; + private transient ColorSpaceConverter converter; + + /** + * Constructs a new ICC_ColorSpace from an ICC_Profile object. + * + * @exception IllegalArgumentException If profile is inappropriate for + * representing a ColorSpace. + */ + public ICC_ColorSpace(ICC_Profile profile) + { + super(profile.getColorSpaceType(), profile.getNumComponents()); + + converter = getConverter(profile); + thisProfile = profile; + nComponents = profile.getNumComponents(); + type = profile.getColorSpaceType(); + makeArrays(); + } + + /** + * Return the profile + */ + public ICC_Profile getProfile() + { + return thisProfile; + } + + /** + * Transforms a color value assumed to be in this ColorSpace into a value in + * the default CS_sRGB color space. + * + * @exception ArrayIndexOutOfBoundsException If array length is not at least + * the number of components in this ColorSpace. + */ + public float[] toRGB(float[] colorvalue) + { + return converter.toRGB(colorvalue); + } + + /** + * Transforms a color value assumed to be in the default CS_sRGB color space + * into this ColorSpace. + * + * @exception ArrayIndexOutOfBoundsException If array length is not at + * least 3. + */ + public float[] fromRGB(float[] rgbvalue) + { + return converter.fromRGB(rgbvalue); + } + + /** + * Transforms a color value assumed to be in this ColorSpace into the + * CS_CIEXYZ conversion color space. + * + * @exception ArrayIndexOutOfBoundsException If array length is not at + * least the number of components in this ColorSpace. + */ + public float[] toCIEXYZ(float[] colorvalue) + { + return converter.toCIEXYZ(colorvalue); + } + + /** + * Transforms a color value assumed to be in the CS_CIEXYZ conversion color + * space into this ColorSpace. + * + * @exception ArrayIndexOutOfBoundsException If array length is not at + * least 3. + */ + public float[] fromCIEXYZ(float[] colorvalue) + { + return converter.fromCIEXYZ(colorvalue); + } + + public boolean isCS_sRGB() + { + return converter instanceof SrgbConverter; + } + + /** + * Returns the minimum normalized color component value for the specified + * component. + * + * @exception IllegalArgumentException If component is less than 0 or greater + * than numComponents - 1. + * + * @since 1.4 + */ + public float getMinValue(int idx) + { + // FIXME: Not 100% certain of this. + if (type == ColorSpace.TYPE_Lab && (idx == 1 || idx == 2)) + return -128f; + + if (idx < 0 || idx >= nComponents) + throw new IllegalArgumentException(); + return 0; + } + + /** + * Returns the maximum normalized color component value for the specified + * component. + * + * @exception IllegalArgumentException If component is less than 0 or greater + * than numComponents - 1. + * + * @since 1.4 + */ + public float getMaxValue(int idx) + { + if (type == ColorSpace.TYPE_XYZ && idx >= 0 && idx <= 2) + return 1 + 32767 / 32768f; + else if (type == ColorSpace.TYPE_Lab) + { + if (idx == 0) + return 100; + if (idx == 1 || idx == 2) + return 127; + } + if (idx < 0 || idx >= nComponents) + throw new IllegalArgumentException(); + return 1; + } + + /** + * Returns a colorspace converter suitable for a given profile + */ + private ColorSpaceConverter getConverter(ICC_Profile profile) + { + ColorSpaceConverter converter; + switch (profile.isPredefined()) + { + case CS_sRGB: + converter = new SrgbConverter(); + break; + case CS_CIEXYZ: + converter = new CieXyzConverter(); + break; + case CS_GRAY: + converter = new GrayScaleConverter(); + break; + case CS_LINEAR_RGB: + converter = new LinearRGBConverter(); + break; + case CS_PYCC: + converter = new PyccConverter(); + break; + default: + if (profile instanceof ICC_ProfileRGB) + converter = new RgbProfileConverter((ICC_ProfileRGB) profile); + else if (profile instanceof ICC_ProfileGray) + converter = new GrayProfileConverter((ICC_ProfileGray) profile); + else + converter = new ClutProfileConverter(profile); + break; + } + return converter; + } + + /** + * Serialization compatibility requires these variable to be set, + * although we don't use them. Perhaps we should? + */ + private void makeArrays() + { + minVal = new float[nComponents]; + maxVal = new float[nComponents]; + + invDiffMinMax = diffMinMax = null; + for (int i = 0; i < nComponents; i++) + { + minVal[i] = getMinValue(i); + maxVal[i] = getMaxValue(i); + } + needScaleInit = true; + } + + /** + * Deserializes the object + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + // set up objects + converter = getConverter(thisProfile); + nComponents = thisProfile.getNumComponents(); + type = thisProfile.getColorSpaceType(); + } +} // class ICC_ColorSpace diff --git a/libjava/classpath/java/awt/color/ICC_Profile.java b/libjava/classpath/java/awt/color/ICC_Profile.java new file mode 100644 index 0000000..75f55a1 --- /dev/null +++ b/libjava/classpath/java/awt/color/ICC_Profile.java @@ -0,0 +1,1244 @@ +/* ICC_Profile.java -- color space profiling + Copyright (C) 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.color; + +import gnu.java.awt.color.ProfileHeader; +import gnu.java.awt.color.TagEntry; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamException; +import java.io.OutputStream; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * ICC Profile - represents an ICC Color profile. + * The ICC profile format is a standard file format which maps the transform + * from a device color space to a standard Profile Color Space (PCS), which + * can either be CIE L*a*b or CIE XYZ. + * (With the exception of device link profiles which map from one device space + * to another) + * + * ICC profiles calibrated to specific input/output devices are used when color + * fidelity is of importance. + * + * An instance of ICC_Profile can be created using the getInstance() methods, + * either using one of the predefined color spaces enumerated in ColorSpace, + * or from an ICC profile file, or from an input stream. + * + * An ICC_ColorSpace object can then be created to transform color values + * through the profile. + * + * The ICC_Profile class implements the version 2 format specified by + * International Color Consortium Specification ICC.1:1998-09, + * and its addendum ICC.1A:1999-04, April 1999 + * (available at www.color.org) + * + * @author Sven de Marothy + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + * @since 1.2 + */ +public class ICC_Profile implements Serializable +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = -3938515861990936766L; + + /** + * ICC Profile classes + */ + public static final int CLASS_INPUT = 0; + public static final int CLASS_DISPLAY = 1; + public static final int CLASS_OUTPUT = 2; + public static final int CLASS_DEVICELINK = 3; + public static final int CLASS_COLORSPACECONVERSION = 4; + public static final int CLASS_ABSTRACT = 5; + public static final int CLASS_NAMEDCOLOR = 6; + + /** + * ICC Profile class signatures + */ + public static final int icSigInputClass = 0x73636e72; // 'scnr' + public static final int icSigDisplayClass = 0x6d6e7472; // 'mntr' + public static final int icSigOutputClass = 0x70727472; // 'prtr' + public static final int icSigLinkClass = 0x6c696e6b; // 'link' + public static final int icSigColorSpaceClass = 0x73706163; // 'spac' + public static final int icSigAbstractClass = 0x61627374; // 'abst' + public static final int icSigNamedColorClass = 0x6e6d636c; // 'nmcl' + + /** + * Color space signatures + */ + public static final int icSigXYZData = 0x58595A20; // 'XYZ ' + public static final int icSigLabData = 0x4C616220; // 'Lab ' + public static final int icSigLuvData = 0x4C757620; // 'Luv ' + public static final int icSigYCbCrData = 0x59436272; // 'YCbr' + public static final int icSigYxyData = 0x59787920; // 'Yxy ' + public static final int icSigRgbData = 0x52474220; // 'RGB ' + public static final int icSigGrayData = 0x47524159; // 'GRAY' + public static final int icSigHsvData = 0x48535620; // 'HSV ' + public static final int icSigHlsData = 0x484C5320; // 'HLS ' + public static final int icSigCmykData = 0x434D594B; // 'CMYK' + public static final int icSigCmyData = 0x434D5920; // 'CMY ' + public static final int icSigSpace2CLR = 0x32434C52; // '2CLR' + public static final int icSigSpace3CLR = 0x33434C52; // '3CLR' + public static final int icSigSpace4CLR = 0x34434C52; // '4CLR' + public static final int icSigSpace5CLR = 0x35434C52; // '5CLR' + public static final int icSigSpace6CLR = 0x36434C52; // '6CLR' + public static final int icSigSpace7CLR = 0x37434C52; // '7CLR' + public static final int icSigSpace8CLR = 0x38434C52; // '8CLR' + public static final int icSigSpace9CLR = 0x39434C52; // '9CLR' + public static final int icSigSpaceACLR = 0x41434C52; // 'ACLR' + public static final int icSigSpaceBCLR = 0x42434C52; // 'BCLR' + public static final int icSigSpaceCCLR = 0x43434C52; // 'CCLR' + public static final int icSigSpaceDCLR = 0x44434C52; // 'DCLR' + public static final int icSigSpaceECLR = 0x45434C52; // 'ECLR' + public static final int icSigSpaceFCLR = 0x46434C52; // 'FCLR' + + /** + * Rendering intents + */ + public static final int icPerceptual = 0; + public static final int icRelativeColorimetric = 1; + public static final int icSaturation = 2; + public static final int icAbsoluteColorimetric = 3; + + /** + * Tag signatures + */ + public static final int icSigAToB0Tag = 0x41324230; // 'A2B0' + public static final int icSigAToB1Tag = 0x41324231; // 'A2B1' + public static final int icSigAToB2Tag = 0x41324232; // 'A2B2' + public static final int icSigBlueColorantTag = 0x6258595A; // 'bXYZ' + public static final int icSigBlueTRCTag = 0x62545243; // 'bTRC' + public static final int icSigBToA0Tag = 0x42324130; // 'B2A0' + public static final int icSigBToA1Tag = 0x42324131; // 'B2A1' + public static final int icSigBToA2Tag = 0x42324132; // 'B2A2' + public static final int icSigCalibrationDateTimeTag = 0x63616C74; // 'calt' + public static final int icSigCharTargetTag = 0x74617267; // 'targ' + public static final int icSigCopyrightTag = 0x63707274; // 'cprt' + public static final int icSigCrdInfoTag = 0x63726469; // 'crdi' + public static final int icSigDeviceMfgDescTag = 0x646D6E64; // 'dmnd' + public static final int icSigDeviceModelDescTag = 0x646D6464; // 'dmdd' + public static final int icSigDeviceSettingsTag = 0x64657673; // 'devs' + public static final int icSigGamutTag = 0x67616D74; // 'gamt' + public static final int icSigGrayTRCTag = 0x6b545243; // 'kTRC' + public static final int icSigGreenColorantTag = 0x6758595A; // 'gXYZ' + public static final int icSigGreenTRCTag = 0x67545243; // 'gTRC' + public static final int icSigLuminanceTag = 0x6C756d69; // 'lumi' + public static final int icSigMeasurementTag = 0x6D656173; // 'meas' + public static final int icSigMediaBlackPointTag = 0x626B7074; // 'bkpt' + public static final int icSigMediaWhitePointTag = 0x77747074; // 'wtpt' + public static final int icSigNamedColor2Tag = 0x6E636C32; // 'ncl2' + public static final int icSigOutputResponseTag = 0x72657370; // 'resp' + public static final int icSigPreview0Tag = 0x70726530; // 'pre0' + public static final int icSigPreview1Tag = 0x70726531; // 'pre1' + public static final int icSigPreview2Tag = 0x70726532; // 'pre2' + public static final int icSigProfileDescriptionTag = 0x64657363; // 'desc' + public static final int icSigProfileSequenceDescTag = 0x70736571; // 'pseq' + public static final int icSigPs2CRD0Tag = 0x70736430; // 'psd0' + public static final int icSigPs2CRD1Tag = 0x70736431; // 'psd1' + public static final int icSigPs2CRD2Tag = 0x70736432; // 'psd2' + public static final int icSigPs2CRD3Tag = 0x70736433; // 'psd3' + public static final int icSigPs2CSATag = 0x70733273; // 'ps2s' + public static final int icSigPs2RenderingIntentTag = 0x70733269; // 'ps2i' + public static final int icSigRedColorantTag = 0x7258595A; // 'rXYZ' + public static final int icSigRedTRCTag = 0x72545243; // 'rTRC' + public static final int icSigScreeningDescTag = 0x73637264; // 'scrd' + public static final int icSigScreeningTag = 0x7363726E; // 'scrn' + public static final int icSigTechnologyTag = 0x74656368; // 'tech' + public static final int icSigUcrBgTag = 0x62666420; // 'bfd ' + public static final int icSigViewingCondDescTag = 0x76756564; // 'vued' + public static final int icSigViewingConditionsTag = 0x76696577; // 'view' + public static final int icSigChromaticityTag = 0x6368726D; // 'chrm' + + /** + * Non-ICC tag 'head' for use in retrieving the header with getData() + */ + public static final int icSigHead = 0x68656164; + + /** + * Header offsets + */ + public static final int icHdrSize = 0; + public static final int icHdrCmmId = 4; + public static final int icHdrVersion = 8; + public static final int icHdrDeviceClass = 12; + public static final int icHdrColorSpace = 16; + public static final int icHdrPcs = 20; + public static final int icHdrDate = 24; + public static final int icHdrMagic = 36; + public static final int icHdrPlatform = 40; + public static final int icHdrFlags = 44; + public static final int icHdrManufacturer = 48; + public static final int icHdrModel = 52; + public static final int icHdrAttributes = 56; + public static final int icHdrRenderingIntent = 64; + public static final int icHdrIlluminant = 68; + public static final int icHdrCreator = 80; + + /** + * + */ + public static final int icTagType = 0; + public static final int icTagReserved = 4; + public static final int icCurveCount = 8; + public static final int icCurveData = 12; + public static final int icXYZNumberX = 8; + + /** + * offset of the Tag table + */ + private static final int tagTableOffset = 128; + + /** + * @serial + */ + private static final int iccProfileSerializedDataVersion = 1; + + /** + * Constants related to generating profiles for + * built-in colorspace profiles + */ + /** + * Copyright notice to stick into built-in-profile files. + */ + private static final String copyrightNotice = "Generated by GNU Classpath."; + + /** + * Resolution of the TRC to use for predefined profiles. + * 1024 should suffice. + */ + private static final int TRC_POINTS = 1024; + + /** + * CIE 1931 D50 white point (in Lab coordinates) + */ + private static final float[] D50 = { 0.96422f, 1.00f, 0.82521f }; + + /** + * Color space profile ID + * Set to the predefined profile class (e.g. CS_sRGB) if a predefined + * color space is used, set to -1 otherwise. + * (or if the profile has been modified) + */ + private transient int profileID; + + /** + * The profile header data + */ + private transient ProfileHeader header; + + /** + * A hashtable containing the profile tags as TagEntry objects + */ + private transient Hashtable tagTable; + + /** + * Contructor for predefined colorspaces + */ + ICC_Profile(int profileID) + { + header = null; + tagTable = null; + createProfile(profileID); + } + + /** + * Constructs an ICC_Profile from a header and a table of loaded tags. + */ + ICC_Profile(ProfileHeader h, Hashtable tags) throws IllegalArgumentException + { + header = h; + tagTable = tags; + profileID = -1; // Not a predefined color space + } + + /** + * Constructs an ICC_Profile from a byte array of data. + */ + ICC_Profile(byte[] data) throws IllegalArgumentException + { + // get header and verify it + header = new ProfileHeader(data); + header.verifyHeader(data.length); + tagTable = createTagTable(data); + profileID = -1; // Not a predefined color space + } + + /** + * Free up the used memory. + */ + protected void finalize() + { + } + + /** + * Returns an ICC_Profile instance from a byte array of profile data. + * + * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray + * may be returned if appropriate. + * + * @throws IllegalArgumentException if the profile data is an invalid + * v2 profile. + * + * @param data - the profile data + * @return An ICC_Profile object + */ + public static ICC_Profile getInstance(byte[] data) + { + ProfileHeader header = new ProfileHeader(data); + + // verify it as a correct ICC header, including size + header.verifyHeader(data.length); + + Hashtable tags = createTagTable(data); + + if (isRGBProfile(header, tags)) + return new ICC_ProfileRGB(data); + if (isGrayProfile(header, tags)) + return new ICC_ProfileGray(data); + + return new ICC_Profile(header, tags); + } + + /** + * Returns an predefined ICC_Profile instance. + * + * This will construct an ICC_Profile instance from one of the predefined + * color spaces in the ColorSpace class. (e.g. CS_sRGB, CS_GRAY, etc) + * + * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray + * may be returned if appropriate. + * + * @return An ICC_Profile object + */ + public static ICC_Profile getInstance(int cspace) + { + if (cspace == ColorSpace.CS_sRGB || cspace == ColorSpace.CS_LINEAR_RGB) + return new ICC_ProfileRGB(cspace); + if (cspace == ColorSpace.CS_GRAY) + return new ICC_ProfileGray(cspace); + return new ICC_Profile(cspace); + } + + /** + * Returns an ICC_Profile instance from an ICC Profile file. + * + * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray + * may be returned if appropriate. + * + * @throws IllegalArgumentException if the profile data is an invalid + * v2 profile. + * @throws IOException if the file could not be read. + * + * @param filename - the file name of the profile file. + * @return An ICC_Profile object + */ + public static ICC_Profile getInstance(String filename) + throws IOException + { + return getInstance(new FileInputStream(filename)); + } + + /** + * Returns an ICC_Profile instance from an InputStream. + * + * This method can be used for reading ICC profiles embedded in files + * which support this. (JPEG and SVG for instance). + * + * The stream is treated in the following way: The profile header + * (128 bytes) is read first, and the header is validated. If the profile + * header is valid, it will then attempt to read the rest of the profile + * from the stream. The stream is not closed after reading. + * + * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray + * may be returned if appropriate. + * + * @throws IllegalArgumentException if the profile data is an invalid + * v2 profile. + * @throws IOException if the stream could not be read. + * + * @param in - the input stream to read the profile from. + * @return An ICC_Profile object + */ + public static ICC_Profile getInstance(InputStream in) + throws IOException + { + // read the header + byte[] headerData = new byte[ProfileHeader.HEADERSIZE]; + if (in.read(headerData) != ProfileHeader.HEADERSIZE) + throw new IllegalArgumentException("Invalid profile header"); + + ProfileHeader header = new ProfileHeader(headerData); + + // verify it as a correct ICC header, but do not verify the + // size as we are reading from a stream. + header.verifyHeader(-1); + + // get the size + byte[] data = new byte[header.getSize()]; + System.arraycopy(headerData, 0, data, 0, ProfileHeader.HEADERSIZE); + + // read the rest + if (in.read(data, ProfileHeader.HEADERSIZE, + header.getSize() - ProfileHeader.HEADERSIZE) != header.getSize() + - ProfileHeader.HEADERSIZE) + throw new IOException("Incorrect profile size"); + + return getInstance(data); + } + + /** + * Returns the major version number + */ + public int getMajorVersion() + { + return header.getMajorVersion(); + } + + /** + * Returns the minor version number. + * + * Only the least-significant byte contains data, in BCD form: + * the least-significant nibble is the BCD bug fix revision, + * the most-significant nibble is the BCD minor revision number. + * + * (E.g. For a v2.1.0 profile this will return <code>0x10</code>) + */ + public int getMinorVersion() + { + return header.getMinorVersion(); + } + + /** + * Returns the device class of this profile, + * + * (E.g. CLASS_INPUT for a scanner profile, + * CLASS_OUTPUT for a printer) + */ + public int getProfileClass() + { + return header.getProfileClass(); + } + + /** + * Returns the color space of this profile, in terms + * of the color space constants defined in ColorSpace. + * (For example, it may be a ColorSpace.TYPE_RGB) + */ + public int getColorSpaceType() + { + return header.getColorSpace(); + } + + /** + * Returns the color space of this profile's Profile Connection Space (OCS) + * + * In terms of the color space constants defined in ColorSpace. + * This may be TYPE_XYZ or TYPE_Lab + */ + public int getPCSType() + { + return header.getProfileColorSpace(); + } + + /** + * Writes the profile data to an ICC profile file. + * @param filename - The name of the file to write + * @throws IOException if the write failed. + */ + public void write(String filename) throws IOException + { + FileOutputStream out = new FileOutputStream(filename); + write(out); + out.flush(); + out.close(); + } + + /** + * Writes the profile data in ICC profile file-format to a stream. + * This is useful for embedding ICC profiles in file formats which + * support this (such as JPEG and SVG). + * + * The stream is not closed after writing. + * @param out - The outputstream to which the profile data should be written + * @throws IOException if the write failed. + */ + public void write(OutputStream out) throws IOException + { + out.write(getData()); + } + + /** + * Returns the data corresponding to this ICC_Profile as a byte array. + * + * @return The data in a byte array, + * where the first element corresponds to first byte of the profile file. + */ + public byte[] getData() + { + int size = getSize(); + byte[] data = new byte[size]; + + // Header + System.arraycopy(header.getData(size), 0, data, 0, ProfileHeader.HEADERSIZE); + // # of tags + byte[] tt = getTagTable(); + System.arraycopy(tt, 0, data, ProfileHeader.HEADERSIZE, tt.length); + + Enumeration e = tagTable.elements(); + while (e.hasMoreElements()) + { + TagEntry tag = (TagEntry) e.nextElement(); + System.arraycopy(tag.getData(), 0, + data, tag.getOffset(), tag.getSize()); + } + return data; + } + + /** + * Returns the ICC profile tag data + * The non ICC-tag icSigHead is also permitted to request the header data. + * + * @param tagSignature The ICC signature of the requested tag + * @return A byte array containing the tag data + */ + public byte[] getData(int tagSignature) + { + if (tagSignature == icSigHead) + return header.getData(getSize()); + + TagEntry t = (TagEntry) tagTable.get(TagEntry.tagHashKey(tagSignature)); + if (t == null) + return null; + return t.getData(); + } + + /** + * Sets the ICC profile tag data. + * + * Note that an ICC profile can only contain one tag of each type, if + * a tag already exists with the given signature, it is replaced. + * + * @param tagSignature - The signature of the tag to set + * @param data - A byte array containing the tag data + */ + public void setData(int tagSignature, byte[] data) + { + profileID = -1; // Not a predefined color space if modified. + + if (tagSignature == icSigHead) + header = new ProfileHeader(data); + else + { + TagEntry t = new TagEntry(tagSignature, data); + tagTable.put(t.hashKey(), t); + } + } + + /** + * Get the number of components in the profile's device color space. + */ + public int getNumComponents() + { + int[] lookup = + { + ColorSpace.TYPE_RGB, 3, ColorSpace.TYPE_CMY, 3, + ColorSpace.TYPE_CMYK, 4, ColorSpace.TYPE_GRAY, 1, + ColorSpace.TYPE_YCbCr, 3, ColorSpace.TYPE_XYZ, 3, + ColorSpace.TYPE_Lab, 3, ColorSpace.TYPE_HSV, 3, + ColorSpace.TYPE_2CLR, 2, ColorSpace.TYPE_Luv, 3, + ColorSpace.TYPE_Yxy, 3, ColorSpace.TYPE_HLS, 3, + ColorSpace.TYPE_3CLR, 3, ColorSpace.TYPE_4CLR, 4, + ColorSpace.TYPE_5CLR, 5, ColorSpace.TYPE_6CLR, 6, + ColorSpace.TYPE_7CLR, 7, ColorSpace.TYPE_8CLR, 8, + ColorSpace.TYPE_9CLR, 9, ColorSpace.TYPE_ACLR, 10, + ColorSpace.TYPE_BCLR, 11, ColorSpace.TYPE_CCLR, 12, + ColorSpace.TYPE_DCLR, 13, ColorSpace.TYPE_ECLR, 14, + ColorSpace.TYPE_FCLR, 15 + }; + for (int i = 0; i < lookup.length; i += 2) + if (header.getColorSpace() == lookup[i]) + return lookup[i + 1]; + return 3; // should never happen. + } + + /** + * After deserializing we must determine if the class we want + * is really one of the more specialized ICC_ProfileRGB or + * ICC_ProfileGray classes. + */ + protected Object readResolve() throws ObjectStreamException + { + if (isRGBProfile(header, tagTable)) + return new ICC_ProfileRGB(getData()); + if (isGrayProfile(header, tagTable)) + return new ICC_ProfileGray(getData()); + return this; + } + + /** + * Deserializes an instance + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + String predef = (String) s.readObject(); + byte[] data = (byte[]) s.readObject(); + + if (data != null) + { + header = new ProfileHeader(data); + tagTable = createTagTable(data); + profileID = -1; // Not a predefined color space + } + + if (predef != null) + { + predef = predef.intern(); + if (predef.equals("CS_sRGB")) + createProfile(ColorSpace.CS_sRGB); + if (predef.equals("CS_LINEAR_RGB")) + createProfile(ColorSpace.CS_LINEAR_RGB); + if (predef.equals("CS_CIEXYZ")) + createProfile(ColorSpace.CS_CIEXYZ); + if (predef.equals("CS_GRAY")) + createProfile(ColorSpace.CS_GRAY); + if (predef.equals("CS_PYCC")) + createProfile(ColorSpace.CS_PYCC); + } + } + + /** + * Serializes an instance + * The format is a String and a byte array, + * The string is non-null if the instance is one of the built-in profiles. + * Otherwise the byte array is non-null and represents the profile data. + */ + private void writeObject(ObjectOutputStream s) throws IOException + { + s.defaultWriteObject(); + if (profileID == ColorSpace.CS_sRGB) + s.writeObject("CS_sRGB"); + else if (profileID == ColorSpace.CS_LINEAR_RGB) + s.writeObject("CS_LINEAR_RGB"); + else if (profileID == ColorSpace.CS_CIEXYZ) + s.writeObject("CS_CIEXYZ"); + else if (profileID == ColorSpace.CS_GRAY) + s.writeObject("CS_GRAY"); + else if (profileID == ColorSpace.CS_PYCC) + s.writeObject("CS_PYCC"); + else + { + s.writeObject(null); // null string + s.writeObject(getData()); // data + return; + } + s.writeObject(null); // null data + } + + /** + * Sorts a ICC profile byte array into TagEntry objects stored in + * a hash table. + */ + private static Hashtable createTagTable(byte[] data) + throws IllegalArgumentException + { + ByteBuffer buf = ByteBuffer.wrap(data); + int nTags = buf.getInt(tagTableOffset); + + Hashtable tagTable = new Hashtable(); + for (int i = 0; i < nTags; i++) + { + TagEntry te = new TagEntry(buf.getInt(tagTableOffset + + i * TagEntry.entrySize + 4), + buf.getInt(tagTableOffset + + i * TagEntry.entrySize + 8), + buf.getInt(tagTableOffset + + i * TagEntry.entrySize + 12), + data); + + if (tagTable.put(te.hashKey(), te) != null) + throw new IllegalArgumentException("Duplicate tag in profile:" + te); + } + return tagTable; + } + + /** + * Returns the total size of the padded, stored data + * Note: Tags must be stored on 4-byte aligned offsets. + */ + private int getSize() + { + int totalSize = ProfileHeader.HEADERSIZE; // size of header + + int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize; // size of tag table + if ((tagTableSize & 0x0003) != 0) + tagTableSize += 4 - (tagTableSize & 0x0003); // pad + totalSize += tagTableSize; + + Enumeration e = tagTable.elements(); + while (e.hasMoreElements()) + { // tag data + int tagSize = ((TagEntry) e.nextElement()).getSize(); + if ((tagSize & 0x0003) != 0) + tagSize += 4 - (tagSize & 0x0003); // pad + totalSize += tagSize; + } + return totalSize; + } + + /** + * Generates the tag index table + */ + private byte[] getTagTable() + { + int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize; + if ((tagTableSize & 0x0003) != 0) + tagTableSize += 4 - (tagTableSize & 0x0003); // pad + + int offset = 4; + int tagOffset = ProfileHeader.HEADERSIZE + tagTableSize; + ByteBuffer buf = ByteBuffer.allocate(tagTableSize); + buf.putInt(tagTable.size()); // number of tags + + Enumeration e = tagTable.elements(); + while (e.hasMoreElements()) + { + TagEntry tag = (TagEntry) e.nextElement(); + buf.putInt(offset, tag.getSignature()); + buf.putInt(offset + 4, tagOffset); + buf.putInt(offset + 8, tag.getSize()); + tag.setOffset(tagOffset); + int tagSize = tag.getSize(); + if ((tagSize & 0x0003) != 0) + tagSize += 4 - (tagSize & 0x0003); // pad + tagOffset += tagSize; + offset += 12; + } + return buf.array(); + } + + /** + * Returns if the criteria for an ICC_ProfileRGB are met. + * This means: + * Color space is TYPE_RGB + * (r,g,b)ColorantTags included + * (r,g,b)TRCTags included + * mediaWhitePointTag included + */ + private static boolean isRGBProfile(ProfileHeader header, Hashtable tags) + { + if (header.getColorSpace() != ColorSpace.TYPE_RGB) + return false; + if (tags.get(TagEntry.tagHashKey(icSigRedColorantTag)) == null) + return false; + if (tags.get(TagEntry.tagHashKey(icSigGreenColorantTag)) == null) + return false; + if (tags.get(TagEntry.tagHashKey(icSigBlueColorantTag)) == null) + return false; + if (tags.get(TagEntry.tagHashKey(icSigRedTRCTag)) == null) + return false; + if (tags.get(TagEntry.tagHashKey(icSigGreenTRCTag)) == null) + return false; + if (tags.get(TagEntry.tagHashKey(icSigBlueTRCTag)) == null) + return false; + return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null); + } + + /** + * Returns if the criteria for an ICC_ProfileGray are met. + * This means: + * Colorspace is TYPE_GRAY + * grayTRCTag included + * mediaWhitePointTag included + */ + private static boolean isGrayProfile(ProfileHeader header, Hashtable tags) + { + if (header.getColorSpace() != ColorSpace.TYPE_GRAY) + return false; + if (tags.get(TagEntry.tagHashKey(icSigGrayTRCTag)) == null) + return false; + return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null); + } + + /** + * Returns curve data for a 'curv'-type tag + * If it's a gamma curve, a single entry will be returned with the + * gamma value (including 1.0 for linear response) + * Otherwise the TRC table is returned. + * + * (Package private - used by ICC_ProfileRGB and ICC_ProfileGray) + */ + short[] getCurve(int signature) + { + byte[] data = getData(signature); + short[] curve; + + // can't find tag? + if (data == null) + return null; + + // not an curve type tag? + ByteBuffer buf = ByteBuffer.wrap(data); + if (buf.getInt(0) != 0x63757276) // 'curv' type + return null; + int count = buf.getInt(8); + if (count == 0) + { + curve = new short[1]; + curve[0] = 0x0100; // 1.00 in u8fixed8 + return curve; + } + if (count == 1) + { + curve = new short[1]; + curve[0] = buf.getShort(12); // other u8fixed8 gamma + return curve; + } + curve = new short[count]; + for (int i = 0; i < count; i++) + curve[i] = buf.getShort(12 + i * 2); + return curve; + } + + /** + * Returns XYZ tristimulus values for an 'XYZ ' type tag + * @return the XYZ values, or null if the tag was not an 'XYZ ' type tag. + * + * (Package private - used by ICC_ProfileXYZ and ICC_ProfileGray) + */ + float[] getXYZData(int signature) + { + byte[] data = getData(signature); + + // can't find tag? + if (data == null) + return null; + + // not an XYZData type tag? + ByteBuffer buf = ByteBuffer.wrap(data); + if (buf.getInt(0) != icSigXYZData) // 'XYZ ' type + return null; + + float[] point = new float[3]; + + // get the X,Y,Z tristimulus values + point[0] = ((float) buf.getInt(8)) / 65536f; + point[1] = ((float) buf.getInt(12)) / 65536f; + point[2] = ((float) buf.getInt(16)) / 65536f; + return point; + } + + /** + * Returns the profile ID if it's a predefined profile + * Or -1 for a profile loaded from an ICC profile + * + * (Package private - used by ICC_ColorSpace) + */ + int isPredefined() + { + return profileID; + } + + /** + * Creates a tag of XYZ-value type. + */ + private byte[] makeXYZData(float[] values) + { + ByteBuffer buf = ByteBuffer.allocate(20); + buf.putInt(0, icSigXYZData); // 'XYZ ' + buf.putInt(4, 0); + buf.putInt(8, (int) (values[0] * 65536.0)); + buf.putInt(12, (int) (values[1] * 65536.0)); + buf.putInt(16, (int) (values[2] * 65536.0)); + return buf.array(); + } + + /** + * Creates a tag of text type + */ + private byte[] makeTextTag(String text) + { + int length = text.length(); + ByteBuffer buf = ByteBuffer.allocate(8 + length + 1); + byte[] data; + try + { + data = text.getBytes("US-ASCII"); + } + catch (UnsupportedEncodingException e) + { + data = new byte[length]; // shouldn't happen + } + + buf.putInt(0, (int) 0x74657874); // 'text' + buf.putInt(4, 0); + for (int i = 0; i < length; i++) + buf.put(8 + i, data[i]); + buf.put(8 + length, (byte) 0); // null-terminate + return buf.array(); + } + + /** + * Creates a tag of textDescriptionType + */ + private byte[] makeDescTag(String text) + { + int length = text.length(); + ByteBuffer buf = ByteBuffer.allocate(90 + length + 1); + buf.putInt(0, (int) 0x64657363); // 'desc' + buf.putInt(4, 0); // reserved + buf.putInt(8, length + 1); // ASCII length, including null termination + byte[] data; + + try + { + data = text.getBytes("US-ASCII"); + } + catch (UnsupportedEncodingException e) + { + data = new byte[length]; // shouldn't happen + } + + for (int i = 0; i < length; i++) + buf.put(12 + i, data[i]); + buf.put(12 + length, (byte) 0); // null-terminate + + for (int i = 0; i < 39; i++) + buf.putShort(13 + length + (i * 2), (short) 0); // 78 bytes we can ignore + + return buf.array(); + } + + /** + * Creates a tag of TRC type (linear curve) + */ + private byte[] makeTRC() + { + ByteBuffer buf = ByteBuffer.allocate(12); + buf.putInt(0, 0x63757276); // 'curv' type + buf.putInt(4, 0); // reserved + buf.putInt(8, 0); + return buf.array(); + } + + /** + * Creates a tag of TRC type (single gamma value) + */ + private byte[] makeTRC(float gamma) + { + short gammaValue = (short) (gamma * 256f); + ByteBuffer buf = ByteBuffer.allocate(14); + buf.putInt(0, 0x63757276); // 'curv' type + buf.putInt(4, 0); // reserved + buf.putInt(8, 1); + buf.putShort(12, gammaValue); // 1.00 in u8fixed8 + return buf.array(); + } + + /** + * Creates a tag of TRC type (TRC curve points) + */ + private byte[] makeTRC(float[] trc) + { + ByteBuffer buf = ByteBuffer.allocate(12 + 2 * trc.length); + buf.putInt(0, 0x63757276); // 'curv' type + buf.putInt(4, 0); // reserved + buf.putInt(8, trc.length); // number of points + + // put the curve values + for (int i = 0; i < trc.length; i++) + buf.putShort(12 + i * 2, (short) (trc[i] * 65535f)); + + return buf.array(); + } + + /** + * Creates an identity color lookup table. + */ + private byte[] makeIdentityClut() + { + final int nIn = 3; + final int nOut = 3; + final int nInEntries = 256; + final int nOutEntries = 256; + final int gridpoints = 16; + + // gridpoints**nIn + final int clutSize = 2 * nOut * gridpoints * gridpoints * gridpoints; + final int totalSize = clutSize + 2 * nInEntries * nIn + + 2 * nOutEntries * nOut + 52; + + ByteBuffer buf = ByteBuffer.allocate(totalSize); + buf.putInt(0, 0x6D667432); // 'mft2' + buf.putInt(4, 0); // reserved + buf.put(8, (byte) nIn); // number input channels + buf.put(9, (byte) nOut); // number output channels + buf.put(10, (byte) gridpoints); // number gridpoints + buf.put(11, (byte) 0); // padding + + // identity matrix + buf.putInt(12, 65536); // = 1 in s15.16 fixed point + buf.putInt(16, 0); + buf.putInt(20, 0); + buf.putInt(24, 0); + buf.putInt(28, 65536); + buf.putInt(32, 0); + buf.putInt(36, 0); + buf.putInt(40, 0); + buf.putInt(44, 65536); + + buf.putShort(48, (short) nInEntries); // input table entries + buf.putShort(50, (short) nOutEntries); // output table entries + + // write the linear input channels, unsigned 16.16 fixed point, + // from 0.0 to FF.FF + for (int channel = 0; channel < 3; channel++) + for (int i = 0; i < nInEntries; i++) + { + short n = (short) ((i << 8) | i); // assumes 256 entries + buf.putShort(52 + (channel * nInEntries + i) * 2, n); + } + int clutOffset = 52 + nInEntries * nIn * 2; + + for (int x = 0; x < gridpoints; x++) + for (int y = 0; y < gridpoints; y++) + for (int z = 0; z < gridpoints; z++) + { + int offset = clutOffset + z * 2 * nOut + y * gridpoints * 2 * nOut + + x * gridpoints * gridpoints * 2 * nOut; + double xf = ((double) x) / ((double) gridpoints - 1.0); + double yf = ((double) y) / ((double) gridpoints - 1.0); + double zf = ((double) z) / ((double) gridpoints - 1.0); + buf.putShort(offset, (short) (xf * 65535.0)); + buf.putShort(offset + 2, (short) (yf * 65535.0)); + buf.putShort(offset + 4, (short) (zf * 65535.0)); + } + + for (int channel = 0; channel < 3; channel++) + for (int i = 0; i < nOutEntries; i++) + { + short n = (short) ((i << 8) | i); // assumes 256 entries + buf.putShort(clutOffset + clutSize + (channel * nOutEntries + i) * 2, + n); + } + + return buf.array(); + } + + /** + * Creates profile data corresponding to the built-in colorspaces. + */ + private void createProfile(int colorSpace) throws IllegalArgumentException + { + this.profileID = colorSpace; + header = new ProfileHeader(); + tagTable = new Hashtable(); + + switch (colorSpace) + { + case ColorSpace.CS_sRGB: + createRGBProfile(); + return; + case ColorSpace.CS_LINEAR_RGB: + createLinearRGBProfile(); + return; + case ColorSpace.CS_CIEXYZ: + createCIEProfile(); + return; + case ColorSpace.CS_GRAY: + createGrayProfile(); + return; + case ColorSpace.CS_PYCC: + createPyccProfile(); + return; + default: + throw new IllegalArgumentException("Not a predefined color space!"); + } + } + + /** + * Creates an ICC_Profile representing the sRGB color space + */ + private void createRGBProfile() + { + header.setColorSpace( ColorSpace.TYPE_RGB ); + header.setProfileColorSpace( ColorSpace.TYPE_XYZ ); + ICC_ColorSpace cs = new ICC_ColorSpace(this); + + float[] r = { 1f, 0f, 0f }; + float[] g = { 0f, 1f, 0f }; + float[] b = { 0f, 0f, 1f }; + float[] black = { 0f, 0f, 0f }; + + // CIE 1931 D50 white point (in Lab coordinates) + float[] white = D50; + + // Get tristimulus values (matrix elements) + r = cs.toCIEXYZ(r); + g = cs.toCIEXYZ(g); + b = cs.toCIEXYZ(b); + + // Generate the sRGB TRC curve, this is the linear->nonlinear + // RGB transform. + cs = new ICC_ColorSpace(getInstance(ICC_ColorSpace.CS_LINEAR_RGB)); + float[] points = new float[TRC_POINTS]; + float[] in = new float[3]; + for (int i = 0; i < TRC_POINTS; i++) + { + in[0] = in[1] = in[2] = ((float) i) / ((float) TRC_POINTS - 1); + in = cs.fromRGB(in); + // Note this value is the same for all components. + points[i] = in[0]; + } + + setData(icSigRedColorantTag, makeXYZData(r)); + setData(icSigGreenColorantTag, makeXYZData(g)); + setData(icSigBlueColorantTag, makeXYZData(b)); + setData(icSigMediaWhitePointTag, makeXYZData(white)); + setData(icSigMediaBlackPointTag, makeXYZData(black)); + setData(icSigRedTRCTag, makeTRC(points)); + setData(icSigGreenTRCTag, makeTRC(points)); + setData(icSigBlueTRCTag, makeTRC(points)); + setData(icSigCopyrightTag, makeTextTag(copyrightNotice)); + setData(icSigProfileDescriptionTag, makeDescTag("Generic sRGB")); + this.profileID = ColorSpace.CS_sRGB; + } + + /** + * Creates an linear sRGB profile + */ + private void createLinearRGBProfile() + { + header.setColorSpace(ColorSpace.TYPE_RGB); + header.setProfileColorSpace(ColorSpace.TYPE_XYZ); + ICC_ColorSpace cs = new ICC_ColorSpace(this); + + float[] r = { 1f, 0f, 0f }; + float[] g = { 0f, 1f, 0f }; + float[] b = { 0f, 0f, 1f }; + float[] black = { 0f, 0f, 0f }; + + float[] white = D50; + + // Get tristimulus values (matrix elements) + r = cs.toCIEXYZ(r); + g = cs.toCIEXYZ(g); + b = cs.toCIEXYZ(b); + + setData(icSigRedColorantTag, makeXYZData(r)); + setData(icSigGreenColorantTag, makeXYZData(g)); + setData(icSigBlueColorantTag, makeXYZData(b)); + + setData(icSigMediaWhitePointTag, makeXYZData(white)); + setData(icSigMediaBlackPointTag, makeXYZData(black)); + + setData(icSigRedTRCTag, makeTRC()); + setData(icSigGreenTRCTag, makeTRC()); + setData(icSigBlueTRCTag, makeTRC()); + setData(icSigCopyrightTag, makeTextTag(copyrightNotice)); + setData(icSigProfileDescriptionTag, makeDescTag("Linear RGB")); + this.profileID = ColorSpace.CS_LINEAR_RGB; + } + + /** + * Creates an CIE XYZ identity profile + */ + private void createCIEProfile() + { + header.setColorSpace( ColorSpace.TYPE_XYZ ); + header.setProfileColorSpace( ColorSpace.TYPE_XYZ ); + header.setProfileClass( CLASS_COLORSPACECONVERSION ); + ICC_ColorSpace cs = new ICC_ColorSpace(this); + + float[] white = D50; + + setData(icSigMediaWhitePointTag, makeXYZData(white)); + setData(icSigAToB0Tag, makeIdentityClut()); + setData(icSigBToA0Tag, makeIdentityClut()); + setData(icSigCopyrightTag, makeTextTag(copyrightNotice)); + setData(icSigProfileDescriptionTag, makeDescTag("CIE XYZ identity profile")); + this.profileID = ColorSpace.CS_CIEXYZ; + } + + /** + * Creates a linear gray ICC_Profile + */ + private void createGrayProfile() + { + header.setColorSpace(ColorSpace.TYPE_GRAY); + header.setProfileColorSpace(ColorSpace.TYPE_XYZ); + + // CIE 1931 D50 white point (in Lab coordinates) + float[] white = D50; + + setData(icSigMediaWhitePointTag, makeXYZData(white)); + setData(icSigGrayTRCTag, makeTRC(1.0f)); + setData(icSigCopyrightTag, makeTextTag(copyrightNotice)); + setData(icSigProfileDescriptionTag, makeDescTag("Linear grayscale")); + this.profileID = ColorSpace.CS_GRAY; + } + + /** + * XXX Implement me + */ + private void createPyccProfile() + { + header.setColorSpace(ColorSpace.TYPE_3CLR); + header.setProfileColorSpace(ColorSpace.TYPE_XYZ); + + // Create CLUTs here. :-) + + setData(icSigCopyrightTag, makeTextTag(copyrightNotice)); + setData(icSigProfileDescriptionTag, makeDescTag("Photo YCC")); + this.profileID = ColorSpace.CS_PYCC; + } +} // class ICC_Profile diff --git a/libjava/classpath/java/awt/color/ICC_ProfileGray.java b/libjava/classpath/java/awt/color/ICC_ProfileGray.java new file mode 100644 index 0000000..3b5948d --- /dev/null +++ b/libjava/classpath/java/awt/color/ICC_ProfileGray.java @@ -0,0 +1,133 @@ +/* ICC_ProfileGray.java -- the ICC profile for a Gray colorspace + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.color; + +/** + * ICC_ProfileGray - a special case of ICC_Profiles. + * + * The ICC_Profile.getInstance() method will return an instance of the + * ICC_ProfileGray subclass when all the following conditions are met: + * The device color space of the profile is TYPE_GRAY. + * The profile contains a gray TRCTag. + * The profile contains a mediaWhitePointTag. + * + * As per the ICC specification, the color space conversion can then + * be done through the following method: + * linearGray = grayTRC[deviceGray] + * + * Note that if the profile contains a CLUT for the color space conversion, + * it should be used instead, and the TRC information ignored. + * + * @author Sven de Marothy + * @since 1.2 + */ +public class ICC_ProfileGray extends ICC_Profile +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = -1124721290732002649L; + private transient float[] whitePoint; + + /** + * Package-private constructor used by ICC_ColorSpace for creating an + * ICC_ProfileGray from a predefined ColorSpace (CS_GRAY) + */ + ICC_ProfileGray(int cspace) + { + super(cspace); + whitePoint = getXYZData(icSigMediaWhitePointTag); + } + + /** + * Package-private constructor used by ICC_ColorSpace for creating an + * ICC_ProfileGray from profile data. + */ + ICC_ProfileGray(byte[] data) + { + super(data); + whitePoint = getXYZData(icSigMediaWhitePointTag); + } + + + /** + * Returns the media white point of the profile. + */ + public float[] getMediaWhitePoint() + { + float[] wp = new float[3]; + wp[0] = whitePoint[0]; + wp[1] = whitePoint[1]; + wp[2] = whitePoint[2]; + return wp; + } + + /** + * Returns the TRC gamma value. + * @throws ProfileDataException if the TRC is described by a lookup + * table and not a gamma value. + */ + public float getGamma() + { + short[] data = getCurve(icSigGrayTRCTag); + if (data == null) + throw new IllegalArgumentException("Couldn't read Gray TRC data."); + if (data.length != 1) + throw new ProfileDataException("TRC is a table, not a gamma value."); + + // convert the unsigned 7.8 fixed-point gamma to a float. + double gamma = (double) (data[0] & (0xFFFF)) / 256.0; + return (float) gamma; + } + + /** + * Returns the TRC lookup table. + * @throws ProfileDataException if the TRC is described by a gamma value + * and not a lookup table. + */ + public short[] getTRC() + { + short[] data = getCurve(icSigGrayTRCTag); + if (data == null) + throw new IllegalArgumentException("Couldn't read Gray TRC data."); + if (data.length <= 1) + throw new ProfileDataException("Gamma value, not a TRC table."); + return data; + } +} // class ICC_ProfileGray diff --git a/libjava/classpath/java/awt/color/ICC_ProfileRGB.java b/libjava/classpath/java/awt/color/ICC_ProfileRGB.java new file mode 100644 index 0000000..0039332 --- /dev/null +++ b/libjava/classpath/java/awt/color/ICC_ProfileRGB.java @@ -0,0 +1,227 @@ +/* ICC_ProfileRGB.java -- the ICC profile for a RGB colorspace + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.color; + +/** + * ICC_ProfileRGB - a special case of ICC_Profiles. + * + * The ICC_Profile.getInstance() method will return an instance of the + * ICC_ProfileRGB subclass when all the following conditions are met: + * The device color space of the profile is TYPE_RGB. + * The profile contains red, green and blue ColorantTags. + * The profile contains red, green and blue TRCTags. + * The profile contains a mediaWhitePointTag included. + * + * As per the ICC specification, the color space conversion can then + * be done through the following method: + * linearR = redTRC[deviceR] + * linearG = greenTRC[deviceG] + * linearB = blueTRC[deviceB] + * TRC curves are either a single gamma value, or a 1-dimensional lookup table. + * + * Followed by the matrix transform: + * PCS = M*linear + * + * Where PCS is the vector of profile color space (must be XYZ) coordinates, + * linear is the vector of linear RGB coordinates, and the matrix M is + * constructed from the ColorantTags, where the columns are red, green and + * blue respectively, and the rows are X, Y and Z. + * + * Note that if the profile contains a CLUT for the color space conversion, + * it should be used instead, and the TRC information ignored. + * + * @author Sven de Marothy + * @since 1.2 + */ +public class ICC_ProfileRGB extends ICC_Profile +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 8505067385152579334L; + + public static final int REDCOMPONENT = 0; + + public static final int GREENCOMPONENT = 1; + + public static final int BLUECOMPONENT = 2; + + private transient float[][] matrix; + + private transient float[] gamma; + + private transient float[] whitePoint; + + + /** + * Package-private constructor used by ICC_ColorSpace for creating an + * ICC_ProfileRGB from a predefined ColorSpace (CS_LINEAR_RGB and CS_sRGB) + */ + ICC_ProfileRGB(int cspace) + { + super(cspace); + matrix = createMatrix(); + whitePoint = getXYZData(icSigMediaWhitePointTag); + } + + /** + * Package-private constructor used by ICC_ColorSpace for creating an + * ICC_ProfileRGB from profile data. + */ + ICC_ProfileRGB(byte[] data) + { + super(data); + matrix = createMatrix(); + whitePoint = getXYZData(icSigMediaWhitePointTag); + } + + /** + * Returns the media white point of the profile. + */ + public float[] getMediaWhitePoint() + { + float[] wp = new float[3]; + wp[0] = whitePoint[0]; + wp[1] = whitePoint[1]; + wp[2] = whitePoint[2]; + return wp; + } + + /** + * Returns the colorant matrix of the conversion. + */ + public float[][] getMatrix() + { + float[][] mat = new float[3][3]; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + mat[i][j] = matrix[i][j]; + return mat; + } + + /** + * Returns the gamma value of a component + * @throws ProfileDataException if the TRC is described by a lookup + * table and not a gamma value. + */ + public float getGamma(int component) + { + short[] data; + switch (component) + { + case REDCOMPONENT: + data = getCurve(icSigRedTRCTag); + break; + case GREENCOMPONENT: + data = getCurve(icSigGreenTRCTag); + break; + case BLUECOMPONENT: + data = getCurve(icSigBlueTRCTag); + break; + default: + throw new IllegalArgumentException("Not a valid component"); + } + if (data == null) + throw new IllegalArgumentException("Error reading TRC"); + + if (data.length != 1) + throw new ProfileDataException("Not a single-gamma TRC"); + + // convert the unsigned 7.8 fixed-point gamma to a float. + float gamma = (float) (((int) data[0] & 0xFF00) >> 8); + double fraction = ((int) data[0] & 0x00FF) / 256.0; + gamma += (float) fraction; + return gamma; + } + + /** + * Returns the TRC lookup table for a component + * @throws ProfileDataException if the TRC is described by a gamma + * value and not a lookup table. + */ + public short[] getTRC(int component) + { + short[] data; + switch (component) + { + case REDCOMPONENT: + data = getCurve(icSigRedTRCTag); + break; + case GREENCOMPONENT: + data = getCurve(icSigGreenTRCTag); + break; + case BLUECOMPONENT: + data = getCurve(icSigBlueTRCTag); + break; + default: + throw new IllegalArgumentException("Not a valid component"); + } + if (data == null) + throw new IllegalArgumentException("Error reading TRC"); + + if (data.length <= 1) + throw new ProfileDataException("Gamma value, not a TRC table."); + + return data; + } + + /** + * Creates the colorspace conversion matrix from the RGB tristimulus + * values. + */ + private float[][] createMatrix() throws IllegalArgumentException + { + float[][] mat = new float[3][3]; + float[] r; + float[] g; + float[] b; + r = getXYZData(icSigRedColorantTag); + g = getXYZData(icSigGreenColorantTag); + b = getXYZData(icSigBlueColorantTag); + if (r == null || g == null || b == null) + throw new IllegalArgumentException("Error reading colorant tags!"); + for (int i = 0; i < 3; i++) + { + mat[i][0] = r[i]; + mat[i][1] = g[i]; + mat[i][2] = b[i]; + } + return mat; + } +} // class ICC_ProfileRGB diff --git a/libjava/classpath/java/awt/color/ProfileDataException.java b/libjava/classpath/java/awt/color/ProfileDataException.java new file mode 100644 index 0000000..1af23b1 --- /dev/null +++ b/libjava/classpath/java/awt/color/ProfileDataException.java @@ -0,0 +1,64 @@ +/* ProfileDataException.java -- error in processing an ICC_Profile + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.color; + +/** + * Thrown when there is an error accessing or processing an + * <code>ICC_Profile</code>. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @status updated to 1.4 + */ +public class ProfileDataException extends RuntimeException +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 7286140888240322498L; + + /** + * Create a new instance with a specified detailed error message. + * + * @param message the message + */ + public ProfileDataException(String message) + { + super(message); + } +} // class ProfileDataException diff --git a/libjava/classpath/java/awt/color/package.html b/libjava/classpath/java/awt/color/package.html new file mode 100644 index 0000000..9a08577 --- /dev/null +++ b/libjava/classpath/java/awt/color/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.color package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.color</title></head> + +<body> +<p>Classes to represent color spaces and profiles.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/datatransfer/Clipboard.java b/libjava/classpath/java/awt/datatransfer/Clipboard.java new file mode 100644 index 0000000..9953a72 --- /dev/null +++ b/libjava/classpath/java/awt/datatransfer/Clipboard.java @@ -0,0 +1,114 @@ +/* Clipboard.java -- Class for transferring data via cut and paste. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +/** + * This class allows data to be transferred using a cut and paste type + * mechanism. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class Clipboard +{ + /** + * The data being transferred. + */ + protected Transferable contents; + + /** + * The owner of this clipboard. + */ + protected ClipboardOwner owner; + + // The clipboard name + private String name; + + /** + * Initializes a new instance of <code>Clipboard</code> with the + * specified name. + * + * @param name The clipboard name. + */ + public Clipboard(String name) + { + this.name = name; + } + + /** + * Returns the name of the clipboard. + */ + public String getName() + { + return name; + } + + /** + * Returns the contents of the clipboard. + * + * @param requestor The object requesting the contents. + * + * @exception IllegalStateException If the clipboard is currently unavailable + */ + public synchronized Transferable getContents(Object requestor) + { + return contents; + } + + /** + * Sets the content and owner of this clipboard. + * If the given owner is different from the current owner + * then lostOwnership is called on the current owner. + * XXX - is this called with the old or new contents. + * + * @param contents The new clipboard contents. + * @param owner The new clipboard owner + * + * @exception IllegalStateException If the clipboard is currently unavailable + */ + public synchronized void setContents(Transferable contents, ClipboardOwner owner) + { + if (this.owner != owner) + if (this.owner != null) + this.owner.lostOwnership(this, contents); + + this.owner = owner; + this.contents = contents; + } +} + diff --git a/libjava/classpath/java/awt/datatransfer/ClipboardOwner.java b/libjava/classpath/java/awt/datatransfer/ClipboardOwner.java new file mode 100644 index 0000000..df75825 --- /dev/null +++ b/libjava/classpath/java/awt/datatransfer/ClipboardOwner.java @@ -0,0 +1,57 @@ +/* ClipboardOwner.java -- Interface for clipboard providers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +/** + * This interface is for classes that will own a clipboard object. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public interface ClipboardOwner +{ + /** + * This method is called to notify this object that it no longer + * has ownership of the specified <code>Clipboard</code>. + * + * @param clipboard The clipboard for which ownership was lost. + * @param contents The contents of the clipboard which are no longer owned. + */ + void lostOwnership (Clipboard clipboard, Transferable contents); +} + diff --git a/libjava/classpath/java/awt/datatransfer/DataFlavor.java b/libjava/classpath/java/awt/datatransfer/DataFlavor.java new file mode 100644 index 0000000..e5fbd24 --- /dev/null +++ b/libjava/classpath/java/awt/datatransfer/DataFlavor.java @@ -0,0 +1,1034 @@ +/* DataFlavor.java -- A type of data to transfer via the clipboard. + Copyright (C) 1999, 2001, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.Reader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; + +/** + * This class represents a particular data format used for transferring + * data via the clipboard. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class DataFlavor implements java.io.Externalizable, Cloneable +{ + static final long serialVersionUID = 8367026044764648243L; + + // FIXME: Serialization: Need to write methods for. + +/** + * This is the data flavor used for tranferring plain text. The MIME + * type is "text/plain; charset=unicode". The representation class + * is <code>java.io.InputStream</code>. + * + * @deprecated The charset unicode is platform specific and InputStream + * deals with bytes not chars. Use <code>getRederForText()</code>. + */ +public static final DataFlavor plainTextFlavor; + +/** + * This is the data flavor used for transferring Java strings. The + * MIME type is "application/x-java-serialized-object" and the + * representation class is <code>java.lang.String</code>. + */ +public static final DataFlavor stringFlavor; + +/** + * This is a data flavor used for transferring lists of files. The + * representation type is a <code>java.util.List</code>, with each element of + * the list being a <code>java.io.File</code>. + */ +public static final DataFlavor javaFileListFlavor; + +/** + * This is an image flavor used for transferring images. The + * representation type is a <code>java.awt.Image</code>. + */ +public static final DataFlavor imageFlavor; + +/** + * This is the MIME type used for transferring a serialized object. + * The representation class is the type of object be deserialized. + */ +public static final String javaSerializedObjectMimeType = + "application/x-java-serialized-object"; + +/** + * This is the MIME type used to transfer a Java object reference within + * the same JVM. The representation class is the class of the object + * being transferred. + */ +public static final String javaJVMLocalObjectMimeType = + "application/x-java-jvm-local-objectref"; + +/** + * This is the MIME type used to transfer a link to a remote object. + * The representation class is the type of object being linked to. + */ +public static final String javaRemoteObjectMimeType = + "application/x-java-remote-object"; + +static +{ + plainTextFlavor + = new DataFlavor(java.io.InputStream.class, + "text/plain; charset=unicode", + "plain unicode text"); + + stringFlavor + = new DataFlavor(java.lang.String.class, + "Java Unicode String"); + + javaFileListFlavor + = new DataFlavor(java.util.List.class, + "Java File List"); + + // javaFileListFlavor.mimeType = "application/x-java-file-list"; + + imageFlavor + = new DataFlavor(java.awt.Image.class, + "Java Image"); +} + +/*************************************************************************/ + +/* + * Instance Variables + */ + +// The MIME type for this flavor +private final String mimeType; + +// The representation class for this flavor +private final Class representationClass; + +// The human readable name of this flavor +private String humanPresentableName; + +/*************************************************************************/ + +/* + * Static Methods + */ + +/** + * This method attempts to load the named class. The following class + * loaders are searched in order: the bootstrap class loader, the + * system class loader, the context class loader (if it exists), and + * the specified fallback class loader. + * + * @param className The name of the class to load. + * @param classLoader The class loader to use if all others fail, which + * may be <code>null</code>. + * + * @exception ClassNotFoundException If the class cannot be loaded. + */ +protected static final Class +tryToLoadClass(String className, ClassLoader classLoader) + throws ClassNotFoundException +{ + try + { + return(Class.forName(className)); + } + catch(Exception e) { ; } + // Commented out for Java 1.1 + /* + try + { + return(className.getClass().getClassLoader().findClass(className)); + } + catch(Exception e) { ; } + + try + { + return(ClassLoader.getSystemClassLoader().findClass(className)); + } + catch(Exception e) { ; } + */ + + // FIXME: What is the context class loader? + /* + try + { + } + catch(Exception e) { ; } + */ + + if (classLoader != null) + return(classLoader.loadClass(className)); + else + throw new ClassNotFoundException(className); +} + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * Empty public constructor needed for externalization. + * Should not be used for normal instantiation. + */ +public +DataFlavor() +{ + mimeType = null; + representationClass = null; + humanPresentableName = null; +} + +/*************************************************************************/ + +/** + * Private constructor. + */ +private +DataFlavor(Class representationClass, + String mimeType, + String humanPresentableName) +{ + this.representationClass = representationClass; + this.mimeType = mimeType; + if (humanPresentableName != null) + this.humanPresentableName = humanPresentableName; + else + this.humanPresentableName = mimeType; +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>DataFlavor</code>. The class + * and human readable name are specified, the MIME type will be + * "application/x-java-serialized-object". If the human readable name + * is not specified (<code>null</code>) then the human readable name + * will be the same as the MIME type. + * + * @param representationClass The representation class for this object. + * @param humanPresentableName The display name of the object. + */ +public +DataFlavor(Class representationClass, String humanPresentableName) +{ + this(representationClass, + "application/x-java-serialized-object" + + "; class=" + + representationClass.getName(), + humanPresentableName); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>DataFlavor</code> with the + * specified MIME type and description. If the MIME type has a + * "class=<rep class>" parameter then the representation class will + * be the class name specified. Otherwise the class defaults to + * <code>java.io.InputStream</code>. If the human readable name + * is not specified (<code>null</code>) then the human readable name + * will be the same as the MIME type. + * + * @param mimeType The MIME type for this flavor. + * @param humanPresentableName The display name of this flavor. + * @param classLoader The class loader for finding classes if the default + * class loaders do not work. + * + * @exception IllegalArgumentException If the representation class + * specified cannot be loaded. + * @exception ClassNotFoundException If the class is not loaded. + */ +public +DataFlavor(String mimeType, String humanPresentableName, + ClassLoader classLoader) throws ClassNotFoundException +{ + this(getRepresentationClassFromMime(mimeType, classLoader), + mimeType, humanPresentableName); +} + +private static Class +getRepresentationClassFromMime(String mimeString, ClassLoader classLoader) +{ + String classname = getParameter("class", mimeString); + if (classname != null) + { + try + { + return tryToLoadClass(classname, classLoader); + } + catch(Exception e) + { + throw new IllegalArgumentException("classname: " + e.getMessage()); + } + } + else + { + return java.io.InputStream.class; + } +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>DataFlavor</code> with the + * specified MIME type and description. If the MIME type has a + * "class=<rep class>" parameter then the representation class will + * be the class name specified. Otherwise the class defaults to + * <code>java.io.InputStream</code>. If the human readable name + * is not specified (<code>null</code>) then the human readable name + * will be the same as the MIME type. This is the same as calling + * <code>new DataFlavor(mimeType, humanPresentableName, null)</code>. + * + * @param mimeType The MIME type for this flavor. + * @param humanPresentableName The display name of this flavor. + * + * @exception IllegalArgumentException If the representation class + * specified cannot be loaded. + */ +public +DataFlavor(String mimeType, String humanPresentableName) +{ + this (getRepresentationClassFromMime (mimeType, null), humanPresentableName); +} + +/*************************************************************************/ + +/** + * Initializes a new instance of <code>DataFlavor</code> with the specified + * MIME type. This type can have a "class=" parameter to specify the + * representation class, and then the class must exist or an exception will + * be thrown. If there is no "class=" parameter then the representation class + * will be <code>java.io.InputStream</code>. This is the same as calling + * <code>new DataFlavor(mimeType, null)</code>. + * + * @param mimeType The MIME type for this flavor. + * + * @exception IllegalArgumentException If a class is not specified in + * the MIME type. + * @exception ClassNotFoundException If the class cannot be loaded. + */ +public +DataFlavor(String mimeType) throws ClassNotFoundException +{ + this(mimeType, null); +} + +/*************************************************************************/ + +/** + * Returns the MIME type of this flavor. + * + * @return The MIME type for this flavor. + */ +public String +getMimeType() +{ + return(mimeType); +} + +/*************************************************************************/ + +/** + * Returns the representation class for this flavor. + * + * @return The representation class for this flavor. + */ +public Class +getRepresentationClass() +{ + return(representationClass); +} + +/*************************************************************************/ + +/** + * Returns the human presentable name for this flavor. + * + * @return The human presentable name for this flavor. + */ +public String +getHumanPresentableName() +{ + return(humanPresentableName); +} + +/*************************************************************************/ + +/** + * Returns the primary MIME type for this flavor. + * + * @return The primary MIME type for this flavor. + */ +public String +getPrimaryType() +{ + int idx = mimeType.indexOf("/"); + if (idx == -1) + return(mimeType); + + return(mimeType.substring(0, idx)); +} + +/*************************************************************************/ + +/** + * Returns the MIME subtype for this flavor. + * + * @return The MIME subtype for this flavor. + */ +public String +getSubType() +{ + int idx = mimeType.indexOf("/"); + if (idx == -1) + return(""); + + String subtype = mimeType.substring(idx + 1); + + idx = subtype.indexOf(" "); + if (idx == -1) + return(subtype); + else + return(subtype.substring(0, idx)); +} + +/*************************************************************************/ + +/** + * Returns the value of the named MIME type parameter, or <code>null</code> + * if the parameter does not exist. Given the parameter name and the mime + * string. + * + * @param paramName The name of the parameter. + * @param mimeString The mime string from where the name should be found. + * + * @return The value of the parameter or null. + */ +private static String +getParameter(String paramName, String mimeString) +{ + int idx = mimeString.indexOf(paramName + "="); + if (idx == -1) + return(null); + + String value = mimeString.substring(idx + paramName.length() + 1); + + idx = value.indexOf(" "); + if (idx == -1) + return(value); + else + return(value.substring(0, idx)); +} + +/*************************************************************************/ + +/** + * Returns the value of the named MIME type parameter, or <code>null</code> + * if the parameter does not exist. + * + * @param paramName The name of the paramter. + * + * @return The value of the parameter. + */ +public String +getParameter(String paramName) +{ + return getParameter(paramName, mimeType); +} + +/*************************************************************************/ + +/** + * Sets the human presentable name to the specified value. + * + * @param humanPresentableName The new display name. + */ +public void +setHumanPresentableName(String humanPresentableName) +{ + this.humanPresentableName = humanPresentableName; +} + +/*************************************************************************/ + +/** + * Tests the MIME type of this object for equality against the specified + * MIME type. + * + * @param mimeType The MIME type to test against. + * + * @return <code>true</code> if the MIME type is equal to this object's + * MIME type, <code>false</code> otherwise. + * + * @exception NullPointerException If mimeType is null. + */ +public boolean +isMimeTypeEqual(String mimeType) +{ + // FIXME: Need to handle default attributes and parameters + + return(this.mimeType.equals(mimeType)); +} + +/*************************************************************************/ + +/** + * Tests the MIME type of this object for equality against the specified + * data flavor's MIME type + * + * @param flavor The flavor to test against. + * + * @return <code>true</code> if the flavor's MIME type is equal to this + * object's MIME type, <code>false</code> otherwise. + */ +public final boolean +isMimeTypeEqual(DataFlavor flavor) +{ + return(isMimeTypeEqual(flavor.getMimeType())); +} + +/*************************************************************************/ + +/** + * Tests whether or not this flavor represents a serialized object. + * + * @return <code>true</code> if this flavor represents a serialized + * object, <code>false</code> otherwise. + */ +public boolean +isMimeTypeSerializedObject() +{ + return(mimeType.startsWith(javaSerializedObjectMimeType)); +} + +/*************************************************************************/ + +/** + * Tests whether or not this flavor has a representation class of + * <code>java.io.InputStream</code>. + * + * @return <code>true</code> if the representation class of this flavor + * is <code>java.io.InputStream</code>, <code>false</code> otherwise. + */ +public boolean +isRepresentationClassInputStream() +{ + return(representationClass.getName().equals("java.io.InputStream")); +} + +/*************************************************************************/ + +/** + * Tests whether the representation class for this flavor is + * serializable. + * + * @return <code>true</code> if the representation class is serializable, + * <code>false</code> otherwise. + */ +public boolean +isRepresentationClassSerializable() +{ + Class[] interfaces = representationClass.getInterfaces(); + + int i = 0; + while (i < interfaces.length) + { + if (interfaces[i].getName().equals("java.io.Serializable")) + return(true); + ++i; + } + + return(false); +} + +/*************************************************************************/ + +/** + * Tests whether the representation class for his flavor is remote. + * + * @return <code>true</code> if the representation class is remote, + * <code>false</code> otherwise. + */ +public boolean +isRepresentationClassRemote() +{ + // FIXME: Implement + throw new RuntimeException("Not implemented"); +} + +/*************************************************************************/ + +/** + * Tests whether or not this flavor represents a serialized object. + * + * @return <code>true</code> if this flavor represents a serialized + * object, <code>false</code> otherwise. + */ +public boolean +isFlavorSerializedObjectType() +{ + // FIXME: What is the diff between this and isMimeTypeSerializedObject? + return(mimeType.startsWith(javaSerializedObjectMimeType)); +} + +/*************************************************************************/ + +/** + * Tests whether or not this flavor represents a remote object. + * + * @return <code>true</code> if this flavor represents a remote object, + * <code>false</code> otherwise. + */ +public boolean +isFlavorRemoteObjectType() +{ + return(mimeType.startsWith(javaRemoteObjectMimeType)); +} + +/*************************************************************************/ + +/** + * Tests whether or not this flavor represents a list of files. + * + * @return <code>true</code> if this flavor represents a list of files, + * <code>false</code> otherwise. + */ +public boolean +isFlavorJavaFileListType() +{ + if (this.mimeType.equals(javaFileListFlavor.mimeType) && + this.representationClass.equals(javaFileListFlavor.representationClass)) + return(true); + + return(false); +} + +/*************************************************************************/ + +/** + * Returns a copy of this object. + * + * @return A copy of this object. + * + * @exception CloneNotSupportedException If the object's class does not support + * the Cloneable interface. Subclasses that override the clone method can also + * throw this exception to indicate that an instance cannot be cloned. + */ +public Object clone () throws CloneNotSupportedException +{ + try + { + return(super.clone()); + } + catch(Exception e) + { + return(null); + } +} + +/*************************************************************************/ + +/** + * This method test the specified <code>DataFlavor</code> for equality + * against this object. This will be true if the MIME type and + * representation type are the equal. + * + * @param flavor The <code>DataFlavor</code> to test against. + * + * @return <code>true</code> if the flavor is equal to this object, + * <code>false</code> otherwise. + */ +public boolean +equals(DataFlavor flavor) +{ + if (flavor == null) + return(false); + + if (!this.mimeType.toLowerCase().equals(flavor.mimeType.toLowerCase())) + return(false); + + if (!this.representationClass.equals(flavor.representationClass)) + return(false); + + return(true); +} + +/*************************************************************************/ + +/** + * This method test the specified <code>Object</code> for equality + * against this object. This will be true if the following conditions + * are met: + * <p> + * <ul> + * <li>The object is not <code>null</code>.</li> + * <li>The object is an instance of <code>DataFlavor</code>.</li> + * <li>The object's MIME type and representation class are equal to + * this object's.</li> + * </ul> + * + * @param obj The <code>Object</code> to test against. + * + * @return <code>true</code> if the flavor is equal to this object, + * <code>false</code> otherwise. + */ +public boolean +equals(Object obj) +{ + if (!(obj instanceof DataFlavor)) + return(false); + + return(equals((DataFlavor)obj)); +} + +/*************************************************************************/ + +/** + * Tests whether or not the specified string is equal to the MIME type + * of this object. + * + * @param str The string to test against. + * + * @return <code>true</code> if the string is equal to this object's MIME + * type, <code>false</code> otherwise. + * + * @deprecated Not compatible with <code>hashCode()</code>. + * Use <code>isMimeTypeEqual()</code> + */ +public boolean +equals(String str) +{ + return(isMimeTypeEqual(str)); +} + +/*************************************************************************/ + +/** + * Returns the hash code for this data flavor. + * The hash code is based on the (lower case) mime type and the + * representation class. + */ +public int +hashCode() +{ + return(mimeType.toLowerCase().hashCode()^representationClass.hashCode()); +} + +/*************************************************************************/ + +/** + * Returns <code>true</code> when the given <code>DataFlavor</code> + * matches this one. + */ +public boolean +match(DataFlavor dataFlavor) +{ + // XXX - How is this different from equals? + return(equals(dataFlavor)); +} + +/*************************************************************************/ + +/** + * This method exists for backward compatibility. It simply returns + * the same name/value pair passed in. + * + * @param name The parameter name. + * @param value The parameter value. + * + * @return The name/value pair. + * + * @deprecated + */ +protected String +normalizeMimeTypeParameter(String name, String value) +{ + return(name + "=" + value); +} + +/*************************************************************************/ + +/** + * This method exists for backward compatibility. It simply returns + * the MIME type string unchanged. + * + * @param type The MIME type. + * + * @return The MIME type. + * + * @deprecated + */ +protected String +normalizeMimeType(String type) +{ + return(type); +} + +/*************************************************************************/ + +/** + * Serialize this class. + * + * @param stream The <code>ObjectOutput</code> stream to serialize to. + * + * @exception IOException If an error occurs. + */ +public void +writeExternal(ObjectOutput stream) throws IOException +{ + // FIXME: Implement me +} + +/*************************************************************************/ + +/** + * De-serialize this class. + * + * @param stream The <code>ObjectInput</code> stream to deserialize from. + * + * @exception IOException If an error ocurs. + * @exception ClassNotFoundException If the class for an object being restored + * cannot be found. + */ +public void +readExternal(ObjectInput stream) throws IOException, ClassNotFoundException +{ + // FIXME: Implement me +} + +/*************************************************************************/ + +/** + * Returns a string representation of this DataFlavor. Including the + * representation class name, MIME type and human presentable name. + */ +public String +toString() +{ + return("DataFlavor[representationClass=" + + representationClass.getName() + + ",mimeType=" + + mimeType + + "humanPresentableName=" + + humanPresentableName); +} + +/*************************************************************************/ + +/** + * XXX - Currently returns <code>plainTextFlavor</code>. + */ +public static final DataFlavor +getTextPlainUnicodeFlavor() +{ + return(plainTextFlavor); +} + +/*************************************************************************/ + +/** + * XXX - Currently returns <code>java.io.InputStream</code>. + * + * @since 1.3 + */ +public final Class +getDefaultRepresentationClass() +{ + return(java.io.InputStream.class); +} +/*************************************************************************/ + +/** + * XXX - Currently returns <code>java.io.InputStream</code>. + */ +public final String +getDefaultRepresentationClassAsString() +{ + return(getDefaultRepresentationClass().getName()); +} + +/*************************************************************************/ + +/** + * Selects the best supported text flavor on this implementation. + * Returns <code>null</code> when none of the given flavors is liked. + * + * The <code>DataFlavor</code> returned the first data flavor in the + * array that has either a representation class which is (a subclass of) + * <code>Reader</code> or <code>String</code>, or has a representation + * class which is (a subclass of) <code>InputStream</code> and has a + * primary MIME type of "text" and has an supported encoding. + */ +public static final DataFlavor +selectBestTextFlavor(DataFlavor[] availableFlavors) +{ + for(int i=0; i<availableFlavors.length; i++) + { + DataFlavor df = availableFlavors[i]; + Class c = df.representationClass; + + // A Reader or String is good. + if ((Reader.class.isAssignableFrom(c)) + || (String.class.isAssignableFrom(c))) + { + return df; + } + + // A InputStream is good if the mime primary type is "text" + if ((InputStream.class.isAssignableFrom(c)) + && ("text".equals(df.getPrimaryType()))) + { + String encoding = availableFlavors[i].getParameter("charset"); + if (encoding == null) + encoding = "us-ascii"; + Reader r = null; + try + { + // Try to construct a dummy reader with the found encoding + r = new InputStreamReader + (new ByteArrayInputStream(new byte[0]), encoding); + } + catch(UnsupportedEncodingException uee) { /* ignore */ } + if (r != null) + return df; + } + } + + // Nothing found + return(null); +} + +/*************************************************************************/ + +/** + * Creates a <code>Reader</code> for a given <code>Transferable</code>. + * + * If the representation class is a (subclass of) <code>Reader</code> + * then an instance of the representation class is returned. If the + * representatation class is a <code>String</code> then a + * <code>StringReader</code> is returned. And if the representation class + * is a (subclass of) <code>InputStream</code> and the primary MIME type + * is "text" then a <code>InputStreamReader</code> for the correct charset + * encoding is returned. + * + * @param transferable The <code>Transferable</code> for which a text + * <code>Reader</code> is requested. + * + * @exception IllegalArgumentException If the representation class is not one + * of the seven listed above or the Transferable has null data. + * @exception NullPointerException If the Transferable is null. + * @exception UnsupportedFlavorException when the transferable doesn't + * support this <code>DataFlavor</code>. Or if the representable class + * isn't a (subclass of) <code>Reader</code>, <code>String</code>, + * <code>InputStream</code> and/or the primary MIME type isn't "text". + * @exception IOException when any IOException occurs. + * @exception UnsupportedEncodingException if the "charset" isn't supported + * on this platform. + */ +public Reader getReaderForText(Transferable transferable) + throws UnsupportedFlavorException, IOException +{ + if (!transferable.isDataFlavorSupported(this)) + throw new UnsupportedFlavorException(this); + + if (Reader.class.isAssignableFrom(representationClass)) + return((Reader)transferable.getTransferData(this)); + + if (String.class.isAssignableFrom(representationClass)) + return(new StringReader((String)transferable.getTransferData(this))); + + if (InputStream.class.isAssignableFrom(representationClass) + && "text".equals(getPrimaryType())) + { + InputStream in = (InputStream)transferable.getTransferData(this); + String encoding = getParameter("charset"); + if (encoding == null) + encoding = "us-ascii"; + return(new InputStreamReader(in, encoding)); + } + + throw new UnsupportedFlavorException(this); +} + + /** + * Returns whether the representation class for this DataFlavor is + * @see java.nio.ByteBuffer or a subclass thereof. + * + * @since 1.4 + */ + public boolean isRepresentationClassByteBuffer () + { + return ByteBuffer.class.isAssignableFrom (representationClass); + } + + /** + * Returns whether the representation class for this DataFlavor is + * @see java.nio.CharBuffer or a subclass thereof. + * + * @since 1.4 + */ + public boolean isRepresentationClassCharBuffer () + { + return CharBuffer.class.isAssignableFrom (representationClass); + } + + /** + * Returns whether the representation class for this DataFlavor is + * @see java.io.Reader or a subclass thereof. + * + * @since 1.4 + */ + public boolean isRepresentationClassReader () + { + return Reader.class.isAssignableFrom (representationClass); + } + +} // class DataFlavor + diff --git a/libjava/classpath/java/awt/datatransfer/FlavorMap.java b/libjava/classpath/java/awt/datatransfer/FlavorMap.java new file mode 100644 index 0000000..59718c4 --- /dev/null +++ b/libjava/classpath/java/awt/datatransfer/FlavorMap.java @@ -0,0 +1,75 @@ +/* FlavorMap.java -- Maps between flavor names and MIME types. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +import java.util.Map; + +/** + * This interface maps between native platform type names and DataFlavors. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public interface FlavorMap +{ + /** + * Maps the specified <code>DataFlavor</code> objects to the native + * data type name. The returned <code>Map</code> has keys that are + * the data flavors and values that are strings. The returned map + * may be modified. This can be useful for implementing nested mappings. + * + * @param flavors An array of data flavors to map + * or null for all data flavors. + * + * @return A <code>Map</code> of native data types. + */ + Map getNativesForFlavors (DataFlavor[] flavors); + + /** + * Maps the specified native type names to <code>DataFlavor</code>'s. + * The returned <code>Map</code> has keys that are strings and values + * that are <code>DataFlavor</code>'s. The returned map may be + * modified. This can be useful for implementing nested mappings. + * + * @param natives An array of native types to map + * or null for all native types. + * + * @return A <code>Map</code> of data flavors. + */ + Map getFlavorsForNatives (String[] natives); +} diff --git a/libjava/classpath/java/awt/datatransfer/FlavorTable.java b/libjava/classpath/java/awt/datatransfer/FlavorTable.java new file mode 100644 index 0000000..11cdda0 --- /dev/null +++ b/libjava/classpath/java/awt/datatransfer/FlavorTable.java @@ -0,0 +1,73 @@ +/* FlavorTable.java -- A relaxed mapping between flavors + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +import java.util.List; + +/** + * A FlavorMap which no longer requires a 1-to-1 mapping between flavors. Any + * native can map to multiple flavors, and any flavor can map to multiple + * natives; although the mappings are usually symmetric. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.4 + * @status updated to 1.4 + */ +public interface FlavorTable extends FlavorMap +{ + /** + * Returns a list of String natives corresponding to the given flavor. The + * list should be sorted from best to worst. The list must be modifiable + * without affecting this table. + * + * @param flavor the flavor to look up, or null to return all natives + * @return the sorted list of natives + */ + List getNativesForFlavor(DataFlavor flavor); + + /** + * Returns a list of flavors corresponding to the given String native. The + * list should be sorted from best to worst. The list must be modifiable + * without affecting this table. + * + * @param name the native name to look up, or null to return all flavors + * @return the sorted list of flavors + */ + List getFlavorsForNative(String name); +} diff --git a/libjava/classpath/java/awt/datatransfer/MimeTypeParseException.java b/libjava/classpath/java/awt/datatransfer/MimeTypeParseException.java new file mode 100644 index 0000000..6113ab7 --- /dev/null +++ b/libjava/classpath/java/awt/datatransfer/MimeTypeParseException.java @@ -0,0 +1,70 @@ +/* MimeTypeParseException.java -- thrown when MIME string couldn't be parsed + Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +/** + * MIME string couldn't be parsed correctly. + * + * @author Mark Wielaard (mark@klomp.org) + * @status updated to 1.4 + */ +public class MimeTypeParseException extends Exception +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -5604407764691570741L; + + /** + * Create a new instance without any message. + */ + public MimeTypeParseException() + { + } + + /** + * Create a new instance with a specified detailed error message. + * + * @param message the message + */ + public MimeTypeParseException(String message) + { + super(message); + } +} // class MimeTypeParseException diff --git a/libjava/classpath/java/awt/datatransfer/StringSelection.java b/libjava/classpath/java/awt/datatransfer/StringSelection.java new file mode 100644 index 0000000..b74f2fa --- /dev/null +++ b/libjava/classpath/java/awt/datatransfer/StringSelection.java @@ -0,0 +1,158 @@ +/* StringSelection.java -- Clipboard handler for text. + Copyright (C) 1999, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +import java.io.IOException; +import java.io.StringReader; + +/** + * This class transfers a string as plain text using the clipboard. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class StringSelection implements Transferable, ClipboardOwner +{ + +/* + * Class Variables + */ + +// List of flavors we support +// XXX: DataFlavor.plainTextFlavor is deprecated. +static final DataFlavor[] supported_flavors + = { DataFlavor.stringFlavor, + DataFlavor.plainTextFlavor }; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +// This is the data to transfer +private String data; + + /** + * Transfer the specfied string as text. + * + * @param data the data for the string selection + */ + public StringSelection(String data) + { + this.data = data; + } + +/** + * Returns a list of supported data flavors. + * + * @return A list of supported data flavors. + */ +public DataFlavor[] +getTransferDataFlavors() +{ + return(supported_flavors); +} + +/*************************************************************************/ + +/** + * Tests whether or not the specified data flavor is supported. + * + * @param flavor The data flavor to test. + * + * @return <code>true</code> if the data flavor is supported, + * <code>false</code> otherwise. + */ +public boolean +isDataFlavorSupported(DataFlavor flavor) +{ + for (int i = 0; i < supported_flavors.length; i++) + if (supported_flavors[i].equals(flavor)) + return(true); + + return(false); +} + +/*************************************************************************/ + +/** + * This method returns the data in the requested format. + * + * @param flavor The desired data flavor. + * + * @return The transferred data. + * + * @exception UnsupportedFlavorException If the specified flavor is not + * supported. + * @exception IOException If any other error occurs. + */ +public Object +getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, + IOException +{ + if (!isDataFlavorSupported(flavor)) + throw new UnsupportedFlavorException(flavor); + + if (DataFlavor.plainTextFlavor == flavor) + /* The behavior of this method for DataFlavor.plainTextFlavor and + equivalent DataFlavors is inconsistent with the definition of + DataFlavor.plainTextFlavor. We choose to do like Sun's implementation + and return a Reader instead of an InputString. */ + /* return(new StringBufferInputStream(data)); */ + return(new StringReader(data)); + else // DataFlavor.stringFlavor + return data; +} + +/*************************************************************************/ + +/** + * Called when ownership of the clipboard object is lost. + * + * @param clipboard The affected clipboard. + * @param contents The clipboard contents. + */ +public void +lostOwnership(Clipboard clipboard, Transferable contents) +{ + // FIXME: What does this do? +} + +} // class StringSelection + diff --git a/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java b/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java new file mode 100644 index 0000000..f6530f5 --- /dev/null +++ b/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java @@ -0,0 +1,169 @@ +/* SystemFlavorMap.java -- Maps between native flavor names and MIME types. + Copyright (C) 2001, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class maps between native platform type names and DataFlavors. + * + * XXX - The current implementation does no mapping at all. + * + * @author Mark Wielaard (mark@klomp.org) + * + * @since 1.2 + */ +public final class SystemFlavorMap implements FlavorMap, FlavorTable +{ + /** + * The default (instance) flavor map. + */ + private static FlavorMap defaultFlavorMap; + + /** + * Private constructor. + */ + private SystemFlavorMap () + { + } + + /** + * Maps the specified <code>DataFlavor</code> objects to the native + * data type name. The returned <code>Map</code> has keys that are + * the data flavors and values that are strings. The returned map + * may be modified. This can be useful for implementing nested mappings. + * + * @param flavors An array of data flavors to map + * or null for all data flavors. + * + * @return A <code>Map</code> of native data types to data flavors. + */ + public Map getNativesForFlavors (DataFlavor[] flavors) + { + return new HashMap(); + } + + /** + * Maps the specified native type names to <code>DataFlavor</code>'s. + * The returned <code>Map</code> has keys that are strings and values + * that are <code>DataFlavor</code>'s. The returned map may be + * modified. This can be useful for implementing nested mappings. + * + * @param natives An array of native types to map + * or null for all native types. + * + * @return A <code>Map</code> of data flavors to native type names. + */ + public Map getFlavorsForNatives (String[] natives) + { + return new HashMap(); + } + + /** + * Returns the default (instance) (System)FlavorMap. + */ + public static FlavorMap getDefaultFlavorMap () + { + if (defaultFlavorMap == null) + defaultFlavorMap = new SystemFlavorMap (); + + return defaultFlavorMap; + } + + /** + * Returns the native type name for the given java mime type. + */ + public static String encodeJavaMIMEType (String mime) + { + return null; + } + + /** + * Returns the native type name for the given data flavor. + */ + public static String encodeDataFlavor (DataFlavor df) + { + return null; + } + + /** + * Returns true if the native type name can be represented as + * a java mime type. + */ + public static boolean isJavaMIMEType (String name) + { + return false; + } + + /** + * Returns the java mime type for the given the native type name. + */ + public static String decodeJavaMIMEType (String name) + { + return null; + } + + /** + * Returns the data flavor given the native type name + * or null when no such data flavor exists. + */ + public static DataFlavor decodeDataFlavor (String name) + throws ClassNotFoundException + { + String javaMIMEType = decodeJavaMIMEType (name); + + if (javaMIMEType != null) + return new DataFlavor (javaMIMEType); + else + return null; + } + + public List getFlavorsForNative (String nat) + { + throw new Error ("Not implemented"); + } + + public List getNativesForFlavor (DataFlavor flav) + { + throw new Error ("Not implemented"); + } + +} // class SystemFlavorMap diff --git a/libjava/classpath/java/awt/datatransfer/Transferable.java b/libjava/classpath/java/awt/datatransfer/Transferable.java new file mode 100644 index 0000000..8075392 --- /dev/null +++ b/libjava/classpath/java/awt/datatransfer/Transferable.java @@ -0,0 +1,83 @@ +/* Transferable.java -- Data transfer source + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +import java.io.IOException; + +/** + * This interface is implemented by classes that can transfer data. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @since 1.1 + * @status updated to 1.4 + */ +public interface Transferable +{ + /** + * This method returns a list of available data flavors for the data being + * transferred. The array returned will be sorted from most preferred + * flavor at the beginning to least preferred at the end. + * + * @return adA list of data flavors for this data + */ + DataFlavor[] getTransferDataFlavors(); + + /** + * Tests whether or not this data can be delivered in the specified data + * flavor. + * + * @param flavor the data flavor to test + * @return true if the data flavor is supported + */ + boolean isDataFlavorSupported(DataFlavor flavor); + + /** + * Returns the data in the specified <code>DataFlavor</code>. + * + * @param flavor the data flavor to return + * @return the data in the appropriate flavor + * @throws UnsupportedFlavorException if the flavor is not supported + * @throws IOException if the data is not available + * @see DataFlavor#getRepresentationClass + */ + Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, IOException; + +} // interface Transferable + diff --git a/libjava/classpath/java/awt/datatransfer/UnsupportedFlavorException.java b/libjava/classpath/java/awt/datatransfer/UnsupportedFlavorException.java new file mode 100644 index 0000000..1c1da03 --- /dev/null +++ b/libjava/classpath/java/awt/datatransfer/UnsupportedFlavorException.java @@ -0,0 +1,65 @@ +/* UnsupportedFlavorException.java -- ata flavor is not valid + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +/** + * The data flavor requested is not supported for the transfer data. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see Transferable#getTransferData(DataFlavor) + * @status updated to 1.4 + */ +public class UnsupportedFlavorException extends Exception +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = 5383814944251665601L; + + /** + * Initializes a new instance of <code>UnsupportedDataFlavor</code> + * for the specified data flavor. + * + * @param flavor the data flavor that is not supported + */ + public UnsupportedFlavorException(DataFlavor flavor) + { + super(flavor == null ? null : flavor.getHumanPresentableName()); + } +} // class UnsupportedFlavorException diff --git a/libjava/classpath/java/awt/datatransfer/package.html b/libjava/classpath/java/awt/datatransfer/package.html new file mode 100644 index 0000000..5ab860c --- /dev/null +++ b/libjava/classpath/java/awt/datatransfer/package.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.datatransfer package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.datatransfer</title></head> + +<body> +<p>Classes to represent different flavors of data for transferring native +and system types through for example a clipboard.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/dnd/Autoscroll.java b/libjava/classpath/java/awt/dnd/Autoscroll.java new file mode 100644 index 0000000..ba4d447 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/Autoscroll.java @@ -0,0 +1,70 @@ +/* Autoscroll.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.awt.Insets; +import java.awt.Point; + +/** + * During DnD operations it is possible that a user may wish to drop the + * subject of the operation on a region of a scrollable GUI control that + * is not currently visible to the user. + * + * @author Michael Koch (konqueror@gmx.de) + * @since 1.2 + * @status updated to 1.4 + */ +public interface Autoscroll +{ + /** + * This method returns the Insets describing the autoscrolling region or + * border relative to the geometry of the implementing Component + */ + Insets getAutoscrollInsets (); + + /** + * Notify the Component to autoscroll + * + * @param location A Point indicating the location of the cursor that + * triggered this operation + */ + void autoscroll (Point location); + +} // interface Autoscroll + diff --git a/libjava/classpath/java/awt/dnd/DnDConstants.java b/libjava/classpath/java/awt/dnd/DnDConstants.java new file mode 100644 index 0000000..85c9c05 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DnDConstants.java @@ -0,0 +1,77 @@ +/* DnDConstants.java -- constants for drag-and-drop operations + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +/** + * This class contains various constants used in drag-and-drop operations. + * Why it is not an interface is beyond me. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ +public final class DnDConstants +{ + /** No action takes place. */ + public static final int ACTION_NONE = 0; + + /** The copy action. */ + public static final int ACTION_COPY = 1; + + /** The move action. */ + public static final int ACTION_MOVE = 2; + + /** Either a copy or a move. */ + public static final int ACTION_COPY_OR_MOVE = 3; + + /** + * A link action. This does not copy or move, but creates a reference back + * to the original. However, since platforms differ on how a reference should + * behave, this action is not recommended for common use. + */ + public static final int ACTION_LINK = 1073741824; + + /** A synonym for {@link #ACTION_LINK}. */ + public static final int ACTION_REFERENCE = ACTION_LINK; + + private DnDConstants() + { + // Do nothing here. + } +} diff --git a/libjava/classpath/java/awt/dnd/DnDEventMulticaster.java b/libjava/classpath/java/awt/dnd/DnDEventMulticaster.java new file mode 100644 index 0000000..d9f5ec0 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DnDEventMulticaster.java @@ -0,0 +1,74 @@ +/* DnDEventMulticaster.java -- helper class for listener chains in java.awt.dnd + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.awt.AWTEventMulticaster; +import java.util.EventListener; + +class DnDEventMulticaster extends AWTEventMulticaster +{ + protected DnDEventMulticaster (EventListener a, EventListener b) + { + super (a, b); + } + + public static DragSourceListener add (DragSourceListener a, + DragSourceListener b) + { + return (DragSourceListener) addInternal (a, b); + } + + public static DragSourceMotionListener add (DragSourceMotionListener a, + DragSourceMotionListener b) + { + return (DragSourceMotionListener) addInternal (a, b); + } + + public static DragSourceListener remove (DragSourceListener a, + DragSourceListener b) + { + return (DragSourceListener) removeInternal (a, b); + } + + public static DragSourceMotionListener remove (DragSourceMotionListener a, + DragSourceMotionListener b) + { + return (DragSourceMotionListener) removeInternal (a, b); + } +} diff --git a/libjava/classpath/java/awt/dnd/DragGestureEvent.java b/libjava/classpath/java/awt/dnd/DragGestureEvent.java new file mode 100644 index 0000000..9f2bc7c --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DragGestureEvent.java @@ -0,0 +1,156 @@ +/* DragGestureEvent.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Image; +import java.awt.Point; +import java.awt.datatransfer.Transferable; +import java.awt.event.InputEvent; +import java.util.EventObject; +import java.util.Iterator; +import java.util.List; + +/** + * STUBBED + * @see DragGestureRecognizer + * @see DragGestureListener + * @see DragSource + * @since 1.2 + */ +public class DragGestureEvent extends EventObject +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 9080172649166731306L; + + private DragSource dragSource; + private Component component; + private final Point origin; + private final int action; + + public DragGestureEvent(DragGestureRecognizer dgr, int action, Point origin, + List events) + { + super(dgr); + if (origin == null || events == null) + throw new IllegalArgumentException(); + this.origin = origin; + this.action = action; + } + + public DragGestureRecognizer getSourceAsDragGestureRecognizer() + { + return (DragGestureRecognizer) source; + } + public Component getComponent() + { + return null; + } + public DragSource getDragSource() + { + return null; + } + public Point getDragOrigin() + { + return origin; + } + public Iterator iterator() + { + return null; + } + public Object[] toArray() + { + return null; + } + public Object[] toArray(Object[] array) + { + return array; + } + public int getDragAction() + { + return 0; + } + public InputEvent getTriggerEvent() + { + return null; + } + + /** + * Starts the drag given the initial Cursor to display, the Transferable + * object, and the DragSourceListener to use. + * + * @exception InvalidDnDOperationException If the Drag and Drop system is + * unable to initiate a drag operation, or if the user attempts to start + * a drag while an existing drag operation is still executing. + */ + public void startDrag(Cursor dragCursor, Transferable trans) + { + startDrag(dragCursor, null, null, trans, null); + } + + /** + * Starts the drag given the initial Cursor to display, the Transferable + * object, and the DragSourceListener to use. + * + * @exception InvalidDnDOperationException If the Drag and Drop system is + * unable to initiate a drag operation, or if the user attempts to start + * a drag while an existing drag operation is still executing. + */ + public void startDrag(Cursor dragCursor, Transferable trans, + DragSourceListener l) + { + startDrag(dragCursor, null, null, trans, l); + } + + /** + * Starts the drag given the initial Cursor to display, the Transferable + * object, and the DragSourceListener to use. + * + * @exception InvalidDnDOperationException If the Drag and Drop system is + * unable to initiate a drag operation, or if the user attempts to start + * a drag while an existing drag operation is still executing. + */ + public void startDrag(Cursor dragCursor, Image dragImage, Point imageOffset, + Transferable trans, DragSourceListener l) + { + } +} // class DragGestureEvent diff --git a/libjava/classpath/java/awt/dnd/DragGestureListener.java b/libjava/classpath/java/awt/dnd/DragGestureListener.java new file mode 100644 index 0000000..e8befe8 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DragGestureListener.java @@ -0,0 +1,63 @@ +/* DragGestureListener.java -- + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.util.EventListener; + +/** + * This is a listener for starting a drag-and-drop gesture. Upon receiving + * notification, the implementor then starts the drag operation. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see DragGestureRecognizer + * @see DragGestureEvent + * @see DragSource + * @since 1.2 + * @status updated to 1.4 + */ +public interface DragGestureListener extends EventListener +{ + /** + * Called when the native platform notifies the virtual machine that a + * drag-and-drop has been initiated. + * + * @param e the event + */ + void dragGestureRecognized(DragGestureEvent e); +} // interface DragGestureListener diff --git a/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java b/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java new file mode 100644 index 0000000..07b822e --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java @@ -0,0 +1,179 @@ +/* DragGestureRecognizer.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.awt.Component; +import java.awt.Point; +import java.awt.event.InputEvent; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.TooManyListenersException; + +/** + * STUBBED + * @since 1.2 + */ +public abstract class DragGestureRecognizer implements Serializable +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 8996673345831063337L; + + protected DragSource dragSource; + protected Component component; + protected transient DragGestureListener dragGestureListener; + protected int sourceActions; + protected ArrayList events = new ArrayList(); + + protected DragGestureRecognizer(DragSource ds, Component c, int sa, + DragGestureListener dgl) + { + if (ds == null) + throw new IllegalArgumentException(); + dragSource = ds; + component = c; + sourceActions = sa; + dragGestureListener = dgl; + } + + protected DragGestureRecognizer(DragSource ds, Component c, int sa) + { + this(ds, c, sa, null); + } + + protected DragGestureRecognizer(DragSource ds, Component c) + { + this(ds, c, 0, null); + } + + protected DragGestureRecognizer(DragSource ds) + { + this(ds, null, 0, null); + } + + protected abstract void registerListeners(); + + protected abstract void unregisterListeners(); + + public DragSource getDragSource() + { + return dragSource; + } + + public Component getComponent() + { + return component; + } + + public void setComponent(Component c) + { + component = c; + } + + public int getSourceActions() + { + return sourceActions; + } + + public void setSourceActions(int sa) + { + sourceActions = sa; + } + + public InputEvent getTriggerEvent() + { + return events.size() > 0 ? (InputEvent) events.get(0) : null; + } + + public void resetRecognizer() + { + throw new Error("not implemented"); + } + + /** + * Register a new DragGestureListener. + * + * @exception TooManyListenersException If a DragGestureListener has already + * been added. + */ + public void addDragGestureListener(DragGestureListener dgl) + throws TooManyListenersException + { + if (dragGestureListener != null) + throw new TooManyListenersException(); + dragGestureListener = dgl; + } + + public void removeDragGestureListener(DragGestureListener dgl) + { + if (dragGestureListener != dgl) + throw new IllegalArgumentException(); + dragGestureListener = null; + } + + protected void fireDragGestureRecognized(int dragAction, Point p) + { + throw new Error("not implemented"); + } + + protected void appendEvent(InputEvent e) + { + if (e == null) + return; + events.add(e); + } + + private void readObject(ObjectInputStream s) + throws ClassNotFoundException, IOException + { + s.defaultReadObject(); + dragGestureListener = (DragGestureListener) s.readObject(); + } + + private void writeObject(ObjectOutputStream s) throws IOException + { + s.defaultWriteObject(); + s.writeObject(dragGestureListener instanceof Serializable + ? dragGestureListener : null); + } +} // class DragGestureRecognizer diff --git a/libjava/classpath/java/awt/dnd/DragSource.java b/libjava/classpath/java/awt/dnd/DragSource.java new file mode 100644 index 0000000..13ffc96 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DragSource.java @@ -0,0 +1,257 @@ +/* DragSource.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.GraphicsEnvironment; +import java.awt.HeadlessException; +import java.awt.Image; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.datatransfer.FlavorMap; +import java.awt.datatransfer.SystemFlavorMap; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.peer.DragSourceContextPeer; +import java.io.Serializable; +import java.util.EventListener; + +/** + * @since 1.2 + */ +public class DragSource implements Serializable +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 6236096958971414066L; + + public static final Cursor DefaultCopyDrop = null; + public static final Cursor DefaultMoveDrop = null; + public static final Cursor DefaultLinkDrop = null; + public static final Cursor DefaultCopyNoDrop = null; + public static final Cursor DefaultMoveNoDrop = null; + public static final Cursor DefaultLinkNoDrop = null; + + private transient FlavorMap flavorMap = SystemFlavorMap.getDefaultFlavorMap (); + + private transient DragSourceListener dragSourceListener; + private transient DragSourceMotionListener dragSourceMotionListener; + + /** + * Initializes the drag source. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public DragSource() + { + if (GraphicsEnvironment.isHeadless()) + throw new HeadlessException (); + } + + /** + * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + */ + public static DragSource getDefaultDragSource() + { + return null; + } + + public static boolean isDragImageSupported() + { + return false; + } + + /** + * Start a drag, given the DragGestureEvent that initiated the drag. + * + * @exception InvalidDnDOperationException If the Drag and Drop system is + * unable to initiate a drag operation, or if the user attempts to start + * a drag while an existing drag operation is still executing. + */ + public void startDrag(DragGestureEvent trigger, Cursor dragCursor, + Image dragImage, Point imageOffset, + Transferable trans, DragSourceListener dsl, + FlavorMap map) + { + } + + /** + * Start a drag, given the DragGestureEvent that initiated the drag. + * + * @exception InvalidDnDOperationException If the Drag and Drop system is + * unable to initiate a drag operation, or if the user attempts to start + * a drag while an existing drag operation is still executing. + */ + public void startDrag(DragGestureEvent trigger, Cursor dragCursor, + Transferable trans, DragSourceListener dsl, + FlavorMap map) + { + startDrag(trigger, dragCursor, null, null, trans, dsl, map); + } + + /** + * Start a drag, given the DragGestureEvent that initiated the drag. + * + * @exception InvalidDnDOperationException If the Drag and Drop system is + * unable to initiate a drag operation, or if the user attempts to start + * a drag while an existing drag operation is still executing. + */ + public void startDrag(DragGestureEvent trigger, Cursor dragCursor, + Image dragImage, Point imageOffset, + Transferable trans, DragSourceListener dsl) + { + startDrag(trigger, dragCursor, dragImage, imageOffset, trans, dsl, null); + } + + /** + * Start a drag, given the DragGestureEvent that initiated the drag. + * + * @exception InvalidDnDOperationException If the Drag and Drop system is + * unable to initiate a drag operation, or if the user attempts to start + * a drag while an existing drag operation is still executing. + */ + public void startDrag(DragGestureEvent trigger, Cursor dragCursor, + Transferable trans, DragSourceListener dsl) + { + startDrag(trigger, dragCursor, null, null, trans, dsl, null); + } + + /** + * Creates the DragSourceContext to handle this drag. + * + * @exception IllegalArgumentException FIXME + * @exception NullPointerException If dscp, dgl, dragImage or t is null. + */ + protected DragSourceContext + createDragSourceContext(DragSourceContextPeer peer, DragGestureEvent dge, + Cursor cursor, Image image, Point offset, + Transferable t, DragSourceListener dsl) + { + return null; + } + + public FlavorMap getFlavorMap() + { + return flavorMap; + } + + public DragGestureRecognizer + createDragGestureRecognizer(Class recognizer, Component c, int actions, + DragGestureListener dgl) + { + return Toolkit.getDefaultToolkit () + .createDragGestureRecognizer (recognizer, this, c, actions, + dgl); + } + + public DragGestureRecognizer + createDefaultDragGestureRecognizer(Component c, int actions, + DragGestureListener dgl) + { + return createDragGestureRecognizer (MouseDragGestureRecognizer.class, c, + actions, dgl); + } + + /** + * @since 1.4 + */ + public void addDragSourceListener(DragSourceListener l) + { + DnDEventMulticaster.add (dragSourceListener, l); + } + + /** + * @since 1.4 + */ + public void removeDragSourceListener(DragSourceListener l) + { + DnDEventMulticaster.remove (dragSourceListener, l); + } + + /** + * @since 1.4 + */ + public DragSourceListener[] getDragSourceListeners() + { + return (DragSourceListener[]) getListeners (DragSourceListener.class); + } + + /** + * @since 1.4 + */ + public void addDragSourceMotionListener(DragSourceMotionListener l) + { + DnDEventMulticaster.add (dragSourceMotionListener, l); + } + + /** + * @since 1.4 + */ + public void removeDragSourceMotionListener(DragSourceMotionListener l) + { + DnDEventMulticaster.remove (dragSourceMotionListener, l); + } + + /** + * @since 1.4 + */ + public DragSourceMotionListener[] getDragSourceMotionListeners () + { + return (DragSourceMotionListener[]) getListeners + (DragSourceMotionListener.class); + } + + /** + * @since 1.4 + */ + public EventListener[] getListeners (Class listenerType) + { + if (listenerType == DragSourceListener.class) + return DnDEventMulticaster.getListeners (dragSourceListener, + listenerType); + + if (listenerType == DragSourceMotionListener.class) + return DnDEventMulticaster.getListeners (dragSourceMotionListener, + listenerType); + + // Return an empty EventListener array. + return new EventListener [0]; + } +} // class DragSource diff --git a/libjava/classpath/java/awt/dnd/DragSourceAdapter.java b/libjava/classpath/java/awt/dnd/DragSourceAdapter.java new file mode 100644 index 0000000..90d9a69 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DragSourceAdapter.java @@ -0,0 +1,126 @@ +/* DragSourceAdapter.java -- drag-and-drop listener adapter + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +/** + * This class implements <code>DragSourceListener</code> and + * <code>DragSourceMotionListener</code>, and implements all methods + * with empty bodies. This allows a listener interested in implementing only + * a subset of these interfaces to extend this class and override only the + * desired methods. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see DragSourceEvent + * @see DragSourceListener + * @see DragSourceMotionListener + * @since 1.4 + * @status updated to 1.4 + */ +public abstract class DragSourceAdapter + implements DragSourceListener, DragSourceMotionListener +{ + /** + * Default constructor. + */ + public DragSourceAdapter() + { + } + + /** + * Called when the cursor hotspot enters a drop site which will accept the + * drag. + * + * @param e the event + */ + public void dragEnter(DragSourceDragEvent e) + { + } + + /** + * Called when the cursor hotspot moves inside of a drop site which will + * accept the drag. + * + * @param e the event + */ + public void dragOver(DragSourceDragEvent e) + { + } + + /** + * Called whenever the mouse is moved during a drag-and-drop operation. + * + * @param e the event + */ + public void dragMouseMoved(DragSourceDragEvent e) + { + } + + /** + * Called when the user modifies the drop gesture. This is often the case + * when additional mouse or key events are received during the drag. + * + * @param e the event + */ + public void dropActionChanged(DragSourceDragEvent e) + { + } + + /** + * Called when the cursor hotspot moves outside of a drop site which will + * accept the drag. This could also happen if the drop site is no longer + * active, or no longer accepts the drag. + * + * @param e the event + */ + public void dragExit(DragSourceEvent e) + { + } + + /** + * Called when the drag and drop operation is complete. After this event, + * <code>getDropSuccess</code> of the event is valid, and + * <code>getDropAction</code> holds the action requested by the drop site. + * Furthermore, the <code>DragSourceContext</code> is invalidated. + * + * @param e the event + */ + public void dragDropEnd(DragSourceDropEvent e) + { + } +} // class DragSourceAdapter diff --git a/libjava/classpath/java/awt/dnd/DragSourceContext.java b/libjava/classpath/java/awt/dnd/DragSourceContext.java new file mode 100644 index 0000000..2cf0d6d --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DragSourceContext.java @@ -0,0 +1,200 @@ +/* DragSourceContext.java -- + Copyright (C) 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Image; +import java.awt.Point; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.peer.DragSourceContextPeer; +import java.io.Serializable; +import java.util.TooManyListenersException; + +/** + * @since 1.2 + */ +public class DragSourceContext + implements DragSourceListener, DragSourceMotionListener, Serializable +{ + /** + * Compatible with JDK 1.2+ + */ + static final long serialVersionUID = -115407898692194719L; + + protected static final int DEFAULT = 0; + protected static final int ENTER = 1; + protected static final int OVER = 2; + protected static final int CHANGED = 3; + + private DragSourceContextPeer peer; + private Cursor cursor; + private Transferable transferable; + private DragGestureEvent trigger; + private DragSourceListener dragSourceListener; + private boolean useCustomCursor; // FIXME: currently unused but needed for serialization. + private int sourceActions; // FIXME: currently unused but needed for serialization. + private Image image; + private Point offset; + + /** + * Initializes a drag source context. + * + * @exception IllegalArgumentException If Component or DragSource of trigger + * are null, the drag action for the trigger event is DnDConstants.ACTION_NONE + * or if the source actions for the DragGestureRecognizer associated with the + * trigger event are equal to DnDConstants.ACTION_NONE. + * @exception NullPointerException If peer or trigger is null. + */ + public DragSourceContext (DragSourceContextPeer peer, + DragGestureEvent trigger, Cursor cursor, + Image image, Point offset, Transferable trans, + DragSourceListener dsl) + { + if (peer == null + || trigger == null) + throw new NullPointerException (); + + if (trigger.getComponent () == null + || trigger.getDragSource () == null + || trigger.getDragAction () == DnDConstants.ACTION_NONE + || trigger.getSourceAsDragGestureRecognizer () + .getSourceActions () == DnDConstants.ACTION_NONE) + throw new IllegalArgumentException (); + + this.peer = peer; + this.trigger = trigger; + this.cursor = cursor; + this.image = image; + this.offset = offset; + this.transferable = trans; + this.dragSourceListener = dsl; + + throw new Error ("not implemented"); + } + + public DragSource getDragSource() + { + return trigger.getDragSource (); + } + + public Component getComponent() + { + return trigger.getComponent (); + } + + public DragGestureEvent getTrigger() + { + return trigger; + } + + public int getSourceActions() + { + return trigger.getSourceAsDragGestureRecognizer ().getSourceActions (); + } + + public void setCursor (Cursor cursor) + { + this.cursor = cursor; + // FIXME: Check if we need to do more here + } + + public Cursor getCursor() + { + return cursor; + } + + /** + * Adds a <code>DragSourceListener</code>. + * + * @exception TooManyListenersException If a <code>DragSourceListener</code> + * has already been added. + */ + public void addDragSourceListener (DragSourceListener dsl) + throws TooManyListenersException + { + if (dragSourceListener != null) + throw new TooManyListenersException (); + + dragSourceListener = dsl; + } + + public void removeDragSourceListener (DragSourceListener dsl) + { + if (dragSourceListener == dsl) + dragSourceListener = null; + } + + public void transferablesFlavorsChanged() + { + } + + public void dragEnter(DragSourceDragEvent e) + { + } + + public void dragOver(DragSourceDragEvent e) + { + } + + public void dragExit(DragSourceEvent e) + { + } + + public void dropActionChanged(DragSourceDragEvent e) + { + } + + public void dragDropEnd(DragSourceDropEvent e) + { + } + + public void dragMouseMoved(DragSourceDragEvent e) + { + } + + public Transferable getTransferable() + { + return transferable; + } + + protected void updateCurrentCursor(int dropOp, int targetAct, int status) + { + } +} // class DragSourceContext diff --git a/libjava/classpath/java/awt/dnd/DragSourceDragEvent.java b/libjava/classpath/java/awt/dnd/DragSourceDragEvent.java new file mode 100644 index 0000000..511700b --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DragSourceDragEvent.java @@ -0,0 +1,102 @@ +/* DragSourceDragEvent.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import gnu.java.awt.EventModifier; + +/** + * @author Michael Koch + * @since 1.2 + */ +public class DragSourceDragEvent extends DragSourceEvent +{ + /** + * Compatible with JDK 1.2+ + */ + private static final long serialVersionUID = 481346297933902471L; + + private final int dropAction; + private final int targetActions; + private final int gestureModifiers; + + public DragSourceDragEvent(DragSourceContext context, int dropAction, + int actions, int modifiers) + { + super(context); + this.dropAction = dropAction; + targetActions = actions; + gestureModifiers = EventModifier.extend(modifiers); + } + + public DragSourceDragEvent(DragSourceContext context, int dropAction, + int actions, int modifiers, int x, int y) + { + super(context, x, y); + this.dropAction = dropAction; + targetActions = actions; + gestureModifiers = EventModifier.extend(modifiers); + } + + public int getTargetActions() + { + return targetActions; + } + + public int getGestureModifiers() + { + return EventModifier.revert(gestureModifiers); + } + + public int getGestureModifiersEx() + { + return gestureModifiers; + } + + public int getUserAction() + { + return dropAction; + } + + public int getDropAction() + { + return (dropAction + & targetActions + & ((DragSourceContext) source).getSourceActions()); + } +} // class DragSourceDragEvent diff --git a/libjava/classpath/java/awt/dnd/DragSourceDropEvent.java b/libjava/classpath/java/awt/dnd/DragSourceDropEvent.java new file mode 100644 index 0000000..7621262 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DragSourceDropEvent.java @@ -0,0 +1,89 @@ +/* DragSourceDragEvent.java -- + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.dnd; + +/** + * @author Michael Koch (konqueror@gmx.de) + * @since 1.2 + * + * Written using JDK 1.4.1 Online API + * Status: JDK 1.4 complete + */ +public class DragSourceDropEvent extends DragSourceEvent +{ + /** + * Compatible with JDK 1.2+ + */ + private static final long serialVersionUID = -5571321229470821891L; + + private final int dropAction; + private final boolean dropSuccess; + + public DragSourceDropEvent (DragSourceContext context) + { + super (context); + this.dropAction = 0; + this.dropSuccess = false; + } + + public DragSourceDropEvent (DragSourceContext context, int dropAction, + boolean dropSuccess) + { + super (context); + this.dropAction = dropAction; + this.dropSuccess = dropSuccess; + } + + public DragSourceDropEvent (DragSourceContext context, int dropAction, + boolean dropSuccess, int x, int y) + { + super (context, x, y); + this.dropAction = dropAction; + this.dropSuccess = dropSuccess; + } + + public int getDropAction() + { + return dropAction & ((DragSourceContext) source).getSourceActions(); + } + + public boolean getDropSuccess() + { + return dropSuccess; + } +} // class DragSourceDropEvent diff --git a/libjava/classpath/java/awt/dnd/DragSourceEvent.java b/libjava/classpath/java/awt/dnd/DragSourceEvent.java new file mode 100644 index 0000000..c5cd42a --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DragSourceEvent.java @@ -0,0 +1,93 @@ +/* DragSourceEvent.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.awt.Point; +import java.util.EventObject; + +/** + * @since 1.2 + */ +public class DragSourceEvent extends EventObject +{ + /** + * Compatible with JDK 1.2+ + */ + private static final long serialVersionUID = -763287114604032641L; + + private final boolean locationSpecified; + private final int x; + private final int y; + + public DragSourceEvent(DragSourceContext context) + { + super(context); + locationSpecified = false; + x = 0; + y = 0; + } + + public DragSourceEvent(DragSourceContext context, int x, int y) + { + super(context); + locationSpecified = true; + this.x = x; + this.y = y; + } + + public DragSourceContext getDragSourceContext() + { + return (DragSourceContext) source; + } + + public Point getLocation() + { + return locationSpecified ? new Point(x, y) : null; + } + + public int getX() + { + return x; + } + + public int getY() + { + return y; + } +} // class DragSourceEvent diff --git a/libjava/classpath/java/awt/dnd/DragSourceListener.java b/libjava/classpath/java/awt/dnd/DragSourceListener.java new file mode 100644 index 0000000..aac6e94 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DragSourceListener.java @@ -0,0 +1,97 @@ +/* DragSourceListener.java -- listen to events during the drag + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.util.EventListener; + +/** + * This class allows an object to listen for drag and drop events. It can + * be used to provide appropriate feedback for "drag over" actions. You can + * also use a <code>DragSourceAdapter</code> to filter the events you are + * interested in. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ +public interface DragSourceListener extends EventListener +{ + /** + * Called when the cursor hotspot enters a drop site which will accept the + * drag. + * + * @param e the drag source drag event + */ + void dragEnter(DragSourceDragEvent e); + + /** + * Called when the cursor hotspot moves inside of a drop site which will + * accept the drag. + * + * @param e the drag source drag event + */ + void dragOver(DragSourceDragEvent e); + + /** + * Called when the user modifies the drop gesture. This is often the case + * when additional mouse or key events are received during the drag. + * + * @param e the drag source drag event + */ + void dropActionChanged(DragSourceDragEvent e); + + /** + * Called when the cursor hotspot moves outside of a drop site which will + * accept the drag. This could also happen if the drop site is no longer + * active, or no longer accepts the drag. + * + * @param e the drag source drag event + */ + void dragExit(DragSourceEvent e); + + /** + * Called when the drag and drop operation is complete. After this event, + * <code>getDropSuccess</code> of the event is valid, and + * <code>getDropAction</code> holds the action requested by the drop site. + * Furthermore, the <code>DragSourceContext</code> is invalidated. + * + * @param e the drag source drag event + */ + void dragDropEnd(DragSourceDropEvent e); +} // interface DragSourceListener diff --git a/libjava/classpath/java/awt/dnd/DragSourceMotionListener.java b/libjava/classpath/java/awt/dnd/DragSourceMotionListener.java new file mode 100644 index 0000000..5d04c22 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DragSourceMotionListener.java @@ -0,0 +1,64 @@ +/* DragSourceMotionListener.java -- tracks motion in the drag source + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.util.EventListener; + +/** + * This is a listener for mouse motion in the drag source before the drop + * event occurs. You can also use a <code>DragSourceAdapter</code> to filter + * the events you are interested in. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see DragSourceDragEvent + * @see DragSource + * @see DragSourceListener + * @see DragSourceAdapter + * @since 1.4 + * @status updated to 1.4 + */ +public interface DragSourceMotionListener extends EventListener +{ + /** + * Called whenever the mouse is moved during a drag-and-drop operation. + * + * @param e the event + */ + void dragMouseMoved(DragSourceDragEvent e); +} // interface DragSourceMotionListener diff --git a/libjava/classpath/java/awt/dnd/DropTarget.java b/libjava/classpath/java/awt/dnd/DropTarget.java new file mode 100644 index 0000000..9fd7ef8 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DropTarget.java @@ -0,0 +1,293 @@ +/* DropTarget.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.awt.Component; +import java.awt.GraphicsEnvironment; +import java.awt.HeadlessException; +import java.awt.Point; +import java.awt.datatransfer.FlavorMap; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.Serializable; +import java.util.EventListener; +import java.util.TooManyListenersException; + +/** + * @author Michael Koch + * @since 1.2 + */ +public class DropTarget + implements DropTargetListener, EventListener, Serializable +{ + /** + * Compatible with JDK 1.2+ + */ + private static final long serialVersionUID = -6283860791671019047L; + + /** @specnote According to the online documentation, this is + * protected, but in reality it is public. */ + public static class DropTargetAutoScroller + implements ActionListener + { + private Component component; + private Point point; + + protected DropTargetAutoScroller (Component c, Point p) + { + component = c; + point = p; + } + + protected void updateLocation (Point newLocn) + { + point = newLocn; + } + + protected void stop () + { + } + + public void actionPerformed (ActionEvent e) + { + } + } + + private Component component; + private FlavorMap flavorMap; + private int actions; + private DropTargetContext dropTargetContext; + private DropTargetListener dropTargetListener; + private boolean active = true; + + /** + * Creates a <code>DropTarget</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true. + */ + public DropTarget () + { + this (null, 0, null, true, null); + } + + /** + * Creates a <code>DropTarget</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true. + */ + public DropTarget (Component c, DropTargetListener dtl) + { + this (c, 0, dtl, true, null); + } + + /** + * Creates a <code>DropTarget</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true. + */ + public DropTarget (Component c, int i, DropTargetListener dtl) + { + this (c, i, dtl, true, null); + } + + /** + * Creates a <code>DropTarget</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true. + */ + public DropTarget (Component c, int i, DropTargetListener dtl, boolean b) + { + this (c, i, dtl, b, null); + } + + /** + * Creates a <code>DropTarget</code> object. + * + * @exception HeadlessException If GraphicsEnvironment.isHeadless() + * returns true. + */ + public DropTarget (Component c, int i, DropTargetListener dtl, boolean b, + FlavorMap fm) + { + if (GraphicsEnvironment.isHeadless ()) + throw new HeadlessException (); + + component = c; + actions = i; + dropTargetListener = dtl; + flavorMap = fm; + + setActive (b); + } + + /** + * Sets the component associated with this drop target object. + */ + public void setComponent (Component c) + { + component = c; + } + + /** + * Returns the component associated with this drop target object. + */ + public Component getComponent () + { + return component; + } + + /** + * Sets the default actions. + */ + public void setDefaultActions (int ops) + { + actions = ops; + } + + /** + * Returns the default actions. + */ + public int getDefaultActions () + { + return actions; + } + + public void setActive (boolean active) + { + this.active = active; + } + + public boolean isActive() + { + return active; + } + + /** + * Adds a new <code>DropTargetListener</code>. + * + * @exception TooManyListenersException Sun's JDK does not, despite + * documentation, throw this exception here when you install an additional + * <code>DropTargetListener</code>. So to be compatible, we do the same + * thing. + */ + public void addDropTargetListener (DropTargetListener dtl) + throws TooManyListenersException + { + dropTargetListener = dtl; + } + + public void removeDropTargetListener(DropTargetListener dtl) + { + // FIXME: Do we need to do something with dtl ? + dropTargetListener = null; + } + + public void dragEnter(DropTargetDragEvent dtde) + { + } + + public void dragOver(DropTargetDragEvent dtde) + { + } + + public void dropActionChanged(DropTargetDragEvent dtde) + { + } + + public void dragExit(DropTargetEvent dte) + { + } + + public void drop(DropTargetDropEvent dtde) + { + } + + public FlavorMap getFlavorMap() + { + return flavorMap; + } + + public void setFlavorMap(FlavorMap fm) + { + flavorMap = fm; + } + + public void addNotify(java.awt.peer.ComponentPeer peer) + { + } + + public void removeNotify(java.awt.peer.ComponentPeer peer) + { + } + + public DropTargetContext getDropTargetContext() + { + if (dropTargetContext == null) + dropTargetContext = createDropTargetContext (); + + return dropTargetContext; + } + + protected DropTargetContext createDropTargetContext() + { + return new DropTargetContext (this); + } + + protected DropTarget.DropTargetAutoScroller createDropTargetAutoScroller + (Component c, Point p) + { + return new DropTarget.DropTargetAutoScroller (c, p); + } + + protected void initializeAutoscrolling(Point p) + { + } + + protected void updateAutoscroll(Point dragCursorLocn) + { + } + + protected void clearAutoscroll() + { + } +} // class DropTarget diff --git a/libjava/classpath/java/awt/dnd/DropTargetAdapter.java b/libjava/classpath/java/awt/dnd/DropTargetAdapter.java new file mode 100644 index 0000000..13c6b9f --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DropTargetAdapter.java @@ -0,0 +1,100 @@ +/* DragSourceAdapter.java -- drag-and-drop listener adapter + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.dnd; + +/** + * This class implements <code>DropTargetListener</code>, and implements all methods + * with empty bodies. This allows a listener interested in implementing only + * a subset of these interfaces to extend this class and override only the + * desired methods. + * + * @author Michael Koch (konqueror@gmx.de) + * @since 1.4 + * @status updated to 1.4 + */ +public abstract class DropTargetAdapter + implements DropTargetListener +{ + /** + * Default constructor. + */ + public DropTargetAdapter() + { + } + + /** + * Called when the cursor hotspot enters a drop site which will accept the + * drag. + * + * @param e the event + */ + public void dragEnter (DropTargetDragEvent e) + { + } + + /** + * Called when the cursor hotspot moves inside of a drop site which will + * accept the drag. + * + * @param e the event + */ + public void dragOver (DropTargetDragEvent e) + { + } + + /** + * Called when the user modifies the drop gesture. This is often the case + * when additional mouse or key events are received during the drag. + * + * @param e the event + */ + public void dropActionChanged (DropTargetDragEvent e) + { + } + + /** + * Called when the cursor hotspot moves outside of a drop site which will + * accept the drag. This could also happen if the drop site is no longer + * active, or no longer accepts the drag. + * + * @param e the event + */ + public void dragExit(DropTargetEvent e) + { + } +} // class DropTargetAdapter diff --git a/libjava/classpath/java/awt/dnd/DropTargetContext.java b/libjava/classpath/java/awt/dnd/DropTargetContext.java new file mode 100644 index 0000000..d1fb66e --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DropTargetContext.java @@ -0,0 +1,188 @@ +/* DropTargetContext.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.dnd; + +import java.awt.Component; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +/** + * @author Michael Koch (konqueror@gmx.de) + * @since 1.2 + */ +public class DropTargetContext implements Serializable +{ + static final long serialVersionUID = -634158968993743371L; + + /** @specnote According to the online documentation, this is + * protected, but in reality it is public. */ + public class TransferableProxy implements Transferable + { + protected boolean isLocal; + protected Transferable transferable; + + TransferableProxy (Transferable t, boolean local) + { + this.transferable = t; + this.isLocal = local; + } + + public DataFlavor[] getTransferDataFlavors () + { + return transferable.getTransferDataFlavors (); + } + + public boolean isDataFlavorSupported (DataFlavor flavor) + { + return transferable.isDataFlavorSupported (flavor); + } + + public Object getTransferData (DataFlavor flavor) + throws UnsupportedFlavorException, IOException + { + return transferable.getTransferData (flavor); + } + } + + private DropTarget dropTarget; + private int targetActions; + private java.awt.dnd.peer.DropTargetContextPeer dtcp; + + // package private + DropTargetContext (DropTarget dropTarget) + { + this.dropTarget = dropTarget; + } + + public DropTarget getDropTarget () + { + return dropTarget; + } + + public Component getComponent () + { + return dropTarget.getComponent (); + } + + public void addNotify (java.awt.dnd.peer.DropTargetContextPeer dtcp) + { + this.dtcp = dtcp; + } + + public void removeNotify () + { + this.dtcp = null; + } + + protected void setTargetActions (int actions) + { + targetActions = actions; + } + + protected int getTargetActions() + { + return targetActions; + } + + /** + * Signals that the drop is completed. + * + * @exception InvalidDnDOperationException If a drop is not outstanding. + */ + public void dropComplete (boolean success) + { + // FIXME: implement this + } + + protected void acceptDrag (int dragOperation) + { + // FIXME: implement this + } + + protected void rejectDrag () + { + // FIXME: implement this + } + + protected void acceptDrop (int dropOperation) + { + // FIXME: implement this + } + + protected void rejectDrop () + { + // FIXME: implement this + } + + protected DataFlavor[] getCurrentDataFlavors () + { + // FIXME: implement this + return null; + } + + protected List getCurrentDataFlavorsAsList () + { + return Arrays.asList (getCurrentDataFlavors ()); + } + + protected boolean isDataFlavorSupported (DataFlavor flavor) + { + return getCurrentDataFlavorsAsList ().contains (flavor); + } + + /** + * Return the <code>Transferable</code> operandof this operation. + * + * @exception InvalidDnDOperationException If a drag is not outstanding. + */ + protected Transferable getTransferable() throws InvalidDnDOperationException + { + // FIXME: implement this + return null; + } + + protected Transferable createTransferableProxy(Transferable t, boolean local) + { + return new TransferableProxy (t, local); + } +} // class DropTargetContext diff --git a/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java b/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java new file mode 100644 index 0000000..6cdc3a2 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java @@ -0,0 +1,140 @@ +/* DropTargetDragEvent.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.awt.Point; +import java.awt.datatransfer.DataFlavor; +import java.util.List; + +/** + * @since 1.2 + */ +public class DropTargetDragEvent extends DropTargetEvent +{ + /** + * Compatible with 1.2+ + */ + private static final long serialVersionUID = -8422265619058953682L; + + private final int dropAction; + private final int srcActions; + private final Point location; + + /** + * Initializes a <code>DropTargetDragEvent</code>. + * + * @exception IllegalArgumentException If dropAction is not one of DnDConstants, + * srcActions is not a bitwise mask of DnDConstants, or dtc is null. + * @exception NullPointerException If location is null. + */ + public DropTargetDragEvent (DropTargetContext context, Point location, + int dropAction, int srcActions) + { + super (context); + + if (location == null) + throw new NullPointerException (); + + if (context == null) + throw new IllegalArgumentException (); + + if (dropAction != DnDConstants.ACTION_NONE + && dropAction != DnDConstants.ACTION_COPY + && dropAction != DnDConstants.ACTION_MOVE + && dropAction != DnDConstants.ACTION_COPY_OR_MOVE + && dropAction != DnDConstants.ACTION_LINK + && dropAction != DnDConstants.ACTION_REFERENCE) + throw new IllegalArgumentException (); + + int srcActionsMask = DnDConstants.ACTION_NONE + | DnDConstants.ACTION_COPY + | DnDConstants.ACTION_MOVE + | DnDConstants.ACTION_COPY_OR_MOVE + | DnDConstants.ACTION_LINK + | DnDConstants.ACTION_REFERENCE; + + if (~(srcActions ^ srcActionsMask) != 0) + throw new IllegalArgumentException (); + + this.dropAction = dropAction; + this.srcActions = srcActions; + this.location = location; + } + + public void acceptDrag (int dragOperation) + { + context.acceptDrag (dragOperation); + } + + public DataFlavor[] getCurrentDataFlavors () + { + return context.getCurrentDataFlavors (); + } + + public List getCurrentDataFlavorsAsList () + { + return context.getCurrentDataFlavorsAsList (); + } + + public int getDropAction() + { + return 0; + //return dropAction & ((DropTargetContext) source).getTargetActions(); + } + + public Point getLocation () + { + return location; + } + + public int getSourceActions () + { + return srcActions; + } + + public boolean isDataFlavorSupported (DataFlavor df) + { + return context.isDataFlavorSupported (df); + } + + public void rejectDrag () + { + context.rejectDrag (); + } +} // class DropTargetDragEvent diff --git a/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java b/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java new file mode 100644 index 0000000..0c0777f --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java @@ -0,0 +1,170 @@ +/* DropTargetDropEvent.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.dnd; + +import java.awt.Point; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.util.List; + +/** + * @since 1.2 + */ +public class DropTargetDropEvent extends DropTargetEvent +{ + /** + * Compatible with JDK 1.2+ + */ + private static final long serialVersionUID = -1721911170440459322L; + + private final int dropAction; + private final int actions; + private final Point location; + private final boolean isLocalTx; + + /** + * Initializes a <code>DropTargetDropEvent</code>. By default this constructor + * assumes that the target is not int same JVM. + * + * @exception IllegalArgumentException If dropAction is not one of DnDConstants, + * actions is not a bitwise mask of DnDConstants, or dtc is null. + * @exception NullPointerException If location is null. + */ + public DropTargetDropEvent (DropTargetContext dtc, Point location, + int dropAction, int actions) + { + this (dtc, location, dropAction, actions, false); + } + + /** + * Initializes a <code>DropTargetDropEvent</code>. + * + * @exception IllegalArgumentException If dropAction is not one of DnDConstants, + * actions is not a bitwise mask of DnDConstants, or dtc is null. + * @exception NullPointerException If location is null. + */ + public DropTargetDropEvent (DropTargetContext dtc, Point location, + int dropAction, int actions, boolean isLocalTx) + { + super (dtc); + + if (location == null) + throw new NullPointerException (); + + if (dtc == null) + throw new IllegalArgumentException (); + + if (dropAction != DnDConstants.ACTION_NONE + && dropAction != DnDConstants.ACTION_COPY + && dropAction != DnDConstants.ACTION_MOVE + && dropAction != DnDConstants.ACTION_COPY_OR_MOVE + && dropAction != DnDConstants.ACTION_LINK + && dropAction != DnDConstants.ACTION_REFERENCE) + throw new IllegalArgumentException (); + + int actionsMask = DnDConstants.ACTION_NONE + | DnDConstants.ACTION_COPY + | DnDConstants.ACTION_MOVE + | DnDConstants.ACTION_COPY_OR_MOVE + | DnDConstants.ACTION_LINK + | DnDConstants.ACTION_REFERENCE; + + if (~(actions ^ actionsMask) != 0) + throw new IllegalArgumentException (); + + this.dropAction = dropAction; + this.actions = actions; + this.location = location; + this.isLocalTx = isLocalTx; + } + + public Point getLocation () + { + return location; + } + + public DataFlavor[] getCurrentDataFlavors () + { + return context.getCurrentDataFlavors (); + } + + public List getCurrentDataFlavorsAsList () + { + return context.getCurrentDataFlavorsAsList (); + } + + public boolean isDataFlavorSupported (DataFlavor flavor) + { + return context.isDataFlavorSupported (flavor); + } + + public int getSourceActions () + { + return actions; + } + + public int getDropAction () + { + return dropAction; + } + + public Transferable getTransferable () + { + return context.getTransferable (); + } + + public void acceptDrop (int dropAction) + { + context.acceptDrop (dropAction); + } + + public void rejectDrop () + { + context.rejectDrop (); + } + + public void dropComplete (boolean success) + { + // FIXME: implement this + } + + public boolean isLocalTransfer() + { + return isLocalTx; + } +} // class DropTargetDropEvent diff --git a/libjava/classpath/java/awt/dnd/DropTargetEvent.java b/libjava/classpath/java/awt/dnd/DropTargetEvent.java new file mode 100644 index 0000000..56a4d48 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DropTargetEvent.java @@ -0,0 +1,56 @@ +/* DropTarget.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.dnd; + +import java.util.EventObject; + +public class DropTargetEvent extends EventObject +{ + protected DropTargetContext context; + + public DropTargetEvent (DropTargetContext context) + { + super (context); + this.context = context; + } + + public DropTargetContext getDropTargetContext () + { + return context; + } +} diff --git a/libjava/classpath/java/awt/dnd/DropTargetListener.java b/libjava/classpath/java/awt/dnd/DropTargetListener.java new file mode 100644 index 0000000..ceb839b --- /dev/null +++ b/libjava/classpath/java/awt/dnd/DropTargetListener.java @@ -0,0 +1,89 @@ +/* DropTargetListener.java -- listen to events during the drop + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +import java.util.EventListener; + +/** + * @author Michael Koch (konqueror@gmx.de) + * @since 1.2 + * @status updated to 1.4 + */ +public interface DropTargetListener extends EventListener +{ + /** + * Called when the cursor hotspot enters a drop site which will accept the + * drag. + * + * @param e the drag source drag event + */ + void dragEnter (DropTargetDragEvent e); + + /** + * Called when the cursor hotspot moves inside of a drop site which will + * accept the drag. + * + * @param e the drag source drag event + */ + void dragOver (DropTargetDragEvent e); + + /** + * Called when the user modifies the drop gesture. This is often the case + * when additional mouse or key events are received during the drag. + * + * @param e the drag source drag event + */ + void dropActionChanged (DropTargetDragEvent e); + + /** + * Called when the cursor hotspot moves outside of a drop site which will + * accept the drag. This could also happen if the drop site is no longer + * active, or no longer accepts the drag. + * + * @param e the drag source drag event + */ + void dragExit (DropTargetEvent e); + + /** + * Called when the drag operation has terminated with a drop. + * + * @param e the drag source drag event + */ + void drop (DropTargetDropEvent e); +} // interface DropTargetListener diff --git a/libjava/classpath/java/awt/dnd/InvalidDnDOperationException.java b/libjava/classpath/java/awt/dnd/InvalidDnDOperationException.java new file mode 100644 index 0000000..2fd9767 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/InvalidDnDOperationException.java @@ -0,0 +1,73 @@ +/* InvalidDnDOperationException.java -- thrown when drag-and-drop fails + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd; + +/** + * Thrown when a method in the java.awt.dnd package is unable to perform a + * requested operation, usually because the underlying DnD system is in the + * wrong state. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ +public class InvalidDnDOperationException extends IllegalStateException +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = -6062568741193956678L; + + /** + * Create an exception without a message. + */ + public InvalidDnDOperationException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public InvalidDnDOperationException(String s) + { + super(s); + } +} // class InvalidDnDOperationException diff --git a/libjava/classpath/java/awt/dnd/MouseDragGestureRecognizer.java b/libjava/classpath/java/awt/dnd/MouseDragGestureRecognizer.java new file mode 100644 index 0000000..9a2a7bc --- /dev/null +++ b/libjava/classpath/java/awt/dnd/MouseDragGestureRecognizer.java @@ -0,0 +1,131 @@ +/* MouseDragGestureRecognizer.java -- + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.dnd; + +import java.awt.Component; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +/** + * @author Michael Koch (konqueror@gmx.de) + */ +public abstract class MouseDragGestureRecognizer + extends DragGestureRecognizer + implements MouseListener, MouseMotionListener +{ + /** + * Creates a <code>MouseDragGestureRecognizer</code> object. + */ + protected MouseDragGestureRecognizer (DragSource ds, Component c, int act, + DragGestureListener dgl) + { + super (ds, c, act, dgl); + } + + /** + * Creates a <code>MouseDragGestureRecognizer</code> object. + */ + protected MouseDragGestureRecognizer (DragSource ds, Component c, int act) + { + super (ds, c, act); + } + + /** + * Creates a <code>MouseDragGestureRecognizer</code> object. + */ + protected MouseDragGestureRecognizer (DragSource ds, Component c) + { + super (ds, c); + } + + /** + * Creates a <code>MouseDragGestureRecognizer</code> object. + */ + protected MouseDragGestureRecognizer (DragSource ds) + { + super (ds); + } + + protected void registerListeners () + { + component.addMouseListener (this); + component.addMouseMotionListener (this); + } + + protected void unregisterListeners () + { + component.removeMouseListener (this); + component.removeMouseMotionListener (this); + } + + public void mouseClicked (MouseEvent e) + { + // Do nothing in here by default. + } + + public void mousePressed (MouseEvent e) + { + // Do nothing in here by default. + } + + public void mouseReleased (MouseEvent e) + { + // Do nothing in here by default. + } + + public void mouseEntered (MouseEvent e) + { + // Do nothing in here by default. + } + + public void mouseExited (MouseEvent e) + { + // Do nothing in here by default. + } + + public void mouseDragged (MouseEvent e) + { + // Do nothing in here by default. + } + + public void mouseMoved (MouseEvent e) + { + // Do nothing in here by default. + } +} // class MouseDragGestureRecognizer diff --git a/libjava/classpath/java/awt/dnd/package.html b/libjava/classpath/java/awt/dnd/package.html new file mode 100644 index 0000000..d1ae521 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.dnd package. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.dnd</title></head> + +<body> +<p>Events and listeners for drag and drop sources and targets.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/dnd/peer/DragSourceContextPeer.java b/libjava/classpath/java/awt/dnd/peer/DragSourceContextPeer.java new file mode 100644 index 0000000..8c134b6 --- /dev/null +++ b/libjava/classpath/java/awt/dnd/peer/DragSourceContextPeer.java @@ -0,0 +1,57 @@ +/* DragSourceContextPeer.java -- interface for drag-and-drop peers + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd.peer; + +import java.awt.Cursor; +import java.awt.Image; +import java.awt.Point; +import java.awt.dnd.DragSourceContext; +import java.awt.dnd.InvalidDnDOperationException; + +/** + * STUBBED + */ +public interface DragSourceContextPeer +{ + void startDrag(DragSourceContext context, Cursor c, Image i, Point p) + throws InvalidDnDOperationException; + Cursor getCursor(); + void setCursor(Cursor c) throws InvalidDnDOperationException; + void transferablesFlavorsChanged(); +} // interface DragSourceContextPeer diff --git a/libjava/classpath/java/awt/dnd/peer/DropTargetContextPeer.java b/libjava/classpath/java/awt/dnd/peer/DropTargetContextPeer.java new file mode 100644 index 0000000..6eae29b --- /dev/null +++ b/libjava/classpath/java/awt/dnd/peer/DropTargetContextPeer.java @@ -0,0 +1,68 @@ +/* DropTargetContextPeer.java -- interface for drag-and-drop peers + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.dnd.peer; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DropTarget; +import java.awt.dnd.InvalidDnDOperationException; + + +/** + * Used to control state of recipient protocol from the + * <code>DropTargetListener</code>. Occurs when a <code>Component</code> + * with an associated <code>DropTarget</code> and visible geometry is first + * intersected by a logical cursor. + * + * @author Michael Koch (konqueror@gmx.de) + */ +public interface DropTargetContextPeer +{ + void setTargetActions(int actions); + int getTargetActions(); + DropTarget getDropTarget(); + DataFlavor[] getTransferDataFlavors(); + Transferable getTransferable() throws InvalidDnDOperationException; + boolean isTransferableJVMLocal(); + void acceptDrag(int dragAction); + void rejectDrag(); + void acceptDrop(int dropAction); + void rejectDrop(); + void dropComplete(boolean success); +} diff --git a/libjava/classpath/java/awt/dnd/peer/DropTargetPeer.java b/libjava/classpath/java/awt/dnd/peer/DropTargetPeer.java new file mode 100644 index 0000000..ec17cbe --- /dev/null +++ b/libjava/classpath/java/awt/dnd/peer/DropTargetPeer.java @@ -0,0 +1,48 @@ +/* DropTargetPeer.java -- interface for drag-and-drop peers + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.dnd.peer; + +import java.awt.dnd.DropTarget; + +/** + */ +public interface DropTargetPeer +{ + void addDropTarget (DropTarget target); + void removeDropTarget (DropTarget target); +} // interface DropTargetContextPeer diff --git a/libjava/classpath/java/awt/dnd/peer/package.html b/libjava/classpath/java/awt/dnd/peer/package.html new file mode 100644 index 0000000..52ec19cb --- /dev/null +++ b/libjava/classpath/java/awt/dnd/peer/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.dnd.peer package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.dnd.peer</title></head> + +<body> +<p>Interfaces for using native interface components.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/event/AWTEventListener.java b/libjava/classpath/java/awt/event/AWTEventListener.java new file mode 100644 index 0000000..079a91d --- /dev/null +++ b/libjava/classpath/java/awt/event/AWTEventListener.java @@ -0,0 +1,65 @@ +/* AWTEventListener.java -- listen for all events in the AWT system + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.AWTEvent; +import java.awt.Toolkit; +import java.util.EventListener; + +/** + * This listener is for classes that need to listen to all events in the AWT + * system. In general, this should not be used except for classes like + * javax.accessibility or by event recorders. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see AWTEvent + * @see Toolkit#addAWTEventListener(AWTEventListener, long) + * @see Toolkit#removeAWTEventListener(AWTEventListener) + * @since 1.2 + * @status updated to 1.4 + */ +public interface AWTEventListener extends EventListener +{ + /** + * This method is called when any event in the AWT system is dispatched. + * + * @param event the AWTEvent that was dispatched + */ + void eventDispatched(AWTEvent event); +} // interface AWTEventListener diff --git a/libjava/classpath/java/awt/event/AWTEventListenerProxy.java b/libjava/classpath/java/awt/event/AWTEventListenerProxy.java new file mode 100644 index 0000000..3d9958b --- /dev/null +++ b/libjava/classpath/java/awt/event/AWTEventListenerProxy.java @@ -0,0 +1,155 @@ +/* AWTEventListenerProxy.java -- wrapper/filter for AWTEventListener + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.AWTEvent; +import java.awt.Toolkit; +import java.util.EventListenerProxy; + +/** + * This class allows adding an AWTEventListener which only pays attention to + * a specific event mask. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see Toolkit + * @see EventListenerProxy + * @since 1.4 + * @status updated to 1.4 + */ +public class AWTEventListenerProxy extends EventListenerProxy + implements AWTEventListener +{ + /** The event mask. */ + private final long mask; + + /** + * Construct an AWT Event Listener which only listens to events in the given + * mask, passing the work on to the real listener. + * + * @param eventMask the mask of events to listen to + * @param listener the wrapped listener + */ + public AWTEventListenerProxy(long eventMask, AWTEventListener listener) + { + super(listener); + mask = eventMask; + } + + /** + * Forwards events on to the delegate if they meet the event mask. + * + * @param event the property change event to filter + * @throws NullPointerException if the delegate this was created with is null + */ + public void eventDispatched(AWTEvent event) + { + int id = event == null ? 0 : event.getID(); + if (((mask & AWTEvent.ACTION_EVENT_MASK) != 0 + && event instanceof ActionEvent) + || ((mask & AWTEvent.ADJUSTMENT_EVENT_MASK) != 0 + && event instanceof AdjustmentEvent) + || ((mask & AWTEvent.COMPONENT_EVENT_MASK) != 0 + && event instanceof ComponentEvent + && (id >= ComponentEvent.COMPONENT_FIRST + && id <= ComponentEvent.COMPONENT_LAST)) + || ((mask & AWTEvent.CONTAINER_EVENT_MASK) != 0 + && event instanceof ContainerEvent) + || ((mask & AWTEvent.FOCUS_EVENT_MASK) != 0 + && event instanceof FocusEvent) + || ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 + && event instanceof HierarchyEvent + && (id == HierarchyEvent.ANCESTOR_MOVED + || id == HierarchyEvent.ANCESTOR_RESIZED)) + || ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 + && event instanceof HierarchyEvent + && id == HierarchyEvent.HIERARCHY_CHANGED) + || ((mask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0 + && event instanceof InputMethodEvent) + || ((mask & AWTEvent.INVOCATION_EVENT_MASK) != 0 + && event instanceof InvocationEvent) + || ((mask & AWTEvent.ITEM_EVENT_MASK) != 0 + && event instanceof ItemEvent) + || ((mask & AWTEvent.KEY_EVENT_MASK) != 0 + && event instanceof KeyEvent) + || ((mask & AWTEvent.MOUSE_EVENT_MASK) != 0 + && event instanceof MouseEvent + && (id == MouseEvent.MOUSE_PRESSED + || id == MouseEvent.MOUSE_RELEASED + || id == MouseEvent.MOUSE_CLICKED + || id == MouseEvent.MOUSE_ENTERED + || id == MouseEvent.MOUSE_EXITED)) + || ((mask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0 + && event instanceof MouseEvent + && (id == MouseEvent.MOUSE_MOVED + || id == MouseEvent.MOUSE_DRAGGED)) + || ((mask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0 + && event instanceof MouseWheelEvent) + || ((mask & AWTEvent.PAINT_EVENT_MASK) != 0 + && event instanceof PaintEvent) + || ((mask & AWTEvent.TEXT_EVENT_MASK) != 0 + && event instanceof TextEvent) + || ((mask & AWTEvent.WINDOW_EVENT_MASK) != 0 + && event instanceof WindowEvent + && (id == WindowEvent.WINDOW_OPENED + || id == WindowEvent.WINDOW_CLOSING + || id == WindowEvent.WINDOW_CLOSED + || id == WindowEvent.WINDOW_ICONIFIED + || id == WindowEvent.WINDOW_DEICONIFIED + || id == WindowEvent.WINDOW_ACTIVATED + || id == WindowEvent.WINDOW_DEACTIVATED)) + || ((mask & AWTEvent.WINDOW_FOCUS_EVENT_MASK) != 0 + && event instanceof WindowEvent + && (id == WindowEvent.WINDOW_GAINED_FOCUS + || id == WindowEvent.WINDOW_LOST_FOCUS)) + || ((mask & AWTEvent.WINDOW_STATE_EVENT_MASK) != 0 + && event instanceof WindowEvent + && id == WindowEvent.WINDOW_STATE_CHANGED)) + ((AWTEventListener) getListener()).eventDispatched(event); + } + + /** + * This returns the event mask associated with this listener. + * + * @return the event mask + */ + public long getEventMask() + { + return mask; + } +} // class AWTEventListenerProxy diff --git a/libjava/classpath/java/awt/event/ActionEvent.java b/libjava/classpath/java/awt/event/ActionEvent.java new file mode 100644 index 0000000..4bce7d4 --- /dev/null +++ b/libjava/classpath/java/awt/event/ActionEvent.java @@ -0,0 +1,226 @@ +/* ActionEvent.java -- an action has been triggered + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.AWTEvent; +import java.awt.EventQueue; + +/** + * This event is generated when an action on a component (such as a + * button press) occurs. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ActionListener + * @since 1.1 + * @status updated to 1.4 + */ +public class ActionEvent extends AWTEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -7671078796273832149L; + + /** Bit mask indicating the shift key was pressed. */ + public static final int SHIFT_MASK = InputEvent.SHIFT_MASK; + + /** Bit mask indicating the control key was pressed. */ + public static final int CTRL_MASK = InputEvent.CTRL_MASK; + + /** Bit mask indicating the that meta key was pressed. */ + public static final int META_MASK = InputEvent.META_MASK; + + /** Bit mask indicating that the alt key was pressed. */ + public static final int ALT_MASK = InputEvent.ALT_MASK; + + /** The first id number in the range of action id's. */ + public static final int ACTION_FIRST = 1001; + + /** The last id number in the range of action id's. */ + public static final int ACTION_LAST = 1001; + + /** An event id indicating that an action has occurred. */ + public static final int ACTION_PERFORMED = 1001; + + /** + * A nonlocalized string that gives more specific details of the event cause. + * + * @see #getActionCommand() + * @serial the command for this event + */ + private final String actionCommand; + + /** + * The bitmask of the modifiers that were pressed during the action. + * + * @see #getModifiers() + * @serial modifiers for this event + */ + private final int modifiers; + + /** + * The timestamp of this event; usually the same as the underlying input + * event. + * + * @see #getWhen() + * @serial the timestamp of the event + * @since 1.4 + */ + private final long when; + + /** + * Initializes a new instance of <code>ActionEvent</code> with the + * specified source, id, and command. Note that an invalid id leads to + * unspecified results. + * + * @param source the event source + * @param id the event id + * @param command the command string for this action + * @throws IllegalArgumentException if source is null + */ + public ActionEvent(Object source, int id, String command) + { + this(source, id, command, EventQueue.getMostRecentEventTime(), 0); + } + + /** + * Initializes a new instance of <code>ActionEvent</code> with the + * specified source, id, command, and modifiers. Note that an invalid id + * leads to unspecified results. + * + * @param source the event source + * @param id the event id + * @param command the command string for this action + * @param modifiers the bitwise or of modifier keys down during the action + * @throws IllegalArgumentException if source is null + */ + public ActionEvent(Object source, int id, String command, int modifiers) + { + this(source, id, command, EventQueue.getMostRecentEventTime(), modifiers); + } + + /** + * Initializes a new instance of <code>ActionEvent</code> with the + * specified source, id, command, and modifiers, and timestamp. Note that + * an invalid id leads to unspecified results. + * + * @param source the event source + * @param id the event id + * @param command the command string for this action + * @param when the timestamp of the event + * @param modifiers the bitwise or of modifier keys down during the action + * @throws IllegalArgumentException if source is null + * @since 1.4 + */ + public ActionEvent(Object source, int id, String command, long when, + int modifiers) + { + super(source, id); + actionCommand = command; + this.when = when; + this.modifiers = modifiers; + } + + /** + * Returns the command string associated with this action. + * + * @return the command string associated with this action + */ + public String getActionCommand() + { + return actionCommand; + } + + /** + * Gets the timestamp of when this action took place. Usually, this + * corresponds to the timestamp of the underlying InputEvent. + * + * @return the timestamp of this action + * @since 1.4 + */ + public long getWhen() + { + return when; + } + + /** + * Returns the keys held down during the action. This value will be a + * combination of the bit mask constants defined in this class, or 0 if no + * modifiers were pressed. + * + * @return the modifier bits + */ + public int getModifiers() + { + return modifiers; + } + + /** + * Returns a string that identifies the action event. This is in the format + * <code>"ACTION_PERFORMED,cmd=" + getActionCommand() + ",when=" + getWhen() + * + ",modifiers=" + <modifier string></code>, where the modifier + * string is in the order "Meta", "Ctrl", "Alt", "Shift", "Alt Graph", and + * "Button1", separated by '+', according to the bits set in getModifiers(). + * + * @return a string identifying the event + */ + public String paramString() + { + StringBuffer s = new StringBuffer(id == ACTION_PERFORMED + ? "ACTION_PERFORMED,cmd=" + : "unknown type,cmd="); + s.append(actionCommand).append(",when=").append(when).append(",modifiers"); + int len = s.length(); + s.setLength(len + 1); + if ((modifiers & META_MASK) != 0) + s.append("+Meta"); + if ((modifiers & CTRL_MASK) != 0) + s.append("+Ctrl"); + if ((modifiers & ALT_MASK) != 0) + s.append("+Alt"); + if ((modifiers & SHIFT_MASK) != 0) + s.append("+Shift"); + if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) + s.append("+Alt Graph"); + if ((modifiers & InputEvent.BUTTON1_MASK) != 0) + s.append("+Button1"); + s.setCharAt(len, '='); + return s.toString(); + } +} // class ActionEvent diff --git a/libjava/classpath/java/awt/event/ActionListener.java b/libjava/classpath/java/awt/event/ActionListener.java new file mode 100644 index 0000000..4c302cc --- /dev/null +++ b/libjava/classpath/java/awt/event/ActionListener.java @@ -0,0 +1,59 @@ +/* ActionListener.java -- listens for action events + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This interface is for classes that listen for action events. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ActionEvent + * @since 1.1 + * @status updated to 1.4 + */ +public interface ActionListener extends EventListener +{ + /** + * This method is invoked when an action occurs. + * + * @param event the <code>ActionEvent</code> that occurred + */ + void actionPerformed(ActionEvent event); +} diff --git a/libjava/classpath/java/awt/event/AdjustmentEvent.java b/libjava/classpath/java/awt/event/AdjustmentEvent.java new file mode 100644 index 0000000..867c577 --- /dev/null +++ b/libjava/classpath/java/awt/event/AdjustmentEvent.java @@ -0,0 +1,222 @@ +/* AdjustmentEvent.java -- an adjustable value was changed + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.AWTEvent; +import java.awt.Adjustable; + +/** + * This class represents an event that is generated when an adjustable + * value is changed. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see Adjustable + * @see AdjustmentListener + * @since 1.1 + * @status updated to 1.4 + */ +public class AdjustmentEvent extends AWTEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = 5700290645205279921L; + + /** This is the first id in the range of ids used by adjustment events. */ + public static final int ADJUSTMENT_FIRST = 601; + + /** This is the last id in the range of ids used by adjustment events. */ + public static final int ADJUSTMENT_LAST = 601; + + /** This is the id indicating an adjustment value changed. */ + public static final int ADJUSTMENT_VALUE_CHANGED = 601; + + /** Adjustment type for unit increments. */ + public static final int UNIT_INCREMENT = 1; + + /** Adjustment type for unit decrements. */ + public static final int UNIT_DECREMENT = 2; + + /** Adjustment type for block decrements. */ + public static final int BLOCK_DECREMENT = 3; + + /** Adjustment type for block increments. */ + public static final int BLOCK_INCREMENT = 4; + + /** Adjustment type for tracking adjustments. */ + public static final int TRACK = 5; + + /** + * The adjustable object that caused the event. + * + * @see #getAdjustable() + * @serial the cause + */ + private final Adjustable adjustable; + + /** + * The type of adjustment, one of {@link #UNIT_INCREMENT}, + * {@link #UNIT_DECREMENT}, {@link #BLOCK_INCREMENT}, + * {@link #BLOCK_DECREMENT}, or {@link #TRACK}. + * + * @see #getAdjustmentType() + * @serial the adjustment type + */ + private final int adjustmentType; + + /** + * The new value of the adjustable; it should be in the range of the + * adjustable cause. + * + * @see #getValue() + * @serial the adjustment value + */ + private final int value; + + /** + * True if this is in a series of multiple adjustment events. + * + * @see #getValueIsAdjusting() + * @serial true if this is not the last adjustment + * @since 1.4 + */ + private final boolean isAdjusting; + + /** + * Initializes an instance of <code>AdjustmentEvent</code> with the + * specified source, id, type, and value. Note that an invalid id leads to + * unspecified results. + * + * @param source the source of the event + * @param id the event id + * @param type the event type, one of the constants of this class + * @param value the value of the adjustment + * @throws IllegalArgumentException if source is null + */ + public AdjustmentEvent(Adjustable source, int id, int type, int value) + { + this(source, id, type, value, false); + } + + /** + * Initializes an instance of <code>AdjustmentEvent</code> with the + * specified source, id, type, and value. Note that an invalid id leads to + * unspecified results. + * + * @param source the source of the event + * @param id the event id + * @param type the event type, one of the constants of this class + * @param value the value of the adjustment + * @param isAdjusting if this event is in a chain of adjustments + * @throws IllegalArgumentException if source is null + * @since 1.4 + */ + public AdjustmentEvent(Adjustable source, int id, int type, int value, + boolean isAdjusting) + { + super(source, id); + this.adjustmentType = type; + this.value = value; + adjustable = source; + this.isAdjusting = isAdjusting; + } + + /** + * This method returns the source of the event as an <code>Adjustable</code>. + * + * @return the <code>Adjustable</code> source of the event + */ + public Adjustable getAdjustable() + { + return adjustable; + } + + /** + * Returns the new value of the adjustable object. + * + * @return the value of the event + */ + public int getValue() + { + return value; + } + + /** + * Returns the type of the event, which will be one of + * {@link #UNIT_INCREMENT}, {@link #UNIT_DECREMENT}, + * {@link #BLOCK_INCREMENT}, {@link #BLOCK_DECREMENT}, or {@link #TRACK}. + * + * @return the type of the event + */ + public int getAdjustmentType() + { + return adjustmentType; + } + + /** + * Test if this event is part of a sequence of multiple adjustements. + * + * @return true if this is not the last adjustment + * @since 1.4 + */ + public boolean getValueIsAdjusting() + { + return isAdjusting; + } + + /** + * Returns a string that describes the event. This is in the format + * <code>"ADJUSTMENT_VALUE_CHANGED,adjType=" + <type> + ",value=" + * + getValue() + ",isAdjusting=" + getValueIsAdjusting()</code>, where + * type is the name of the constant returned by getAdjustmentType(). + * + * @return a string that describes the event + */ + public String paramString() + { + return (id == ADJUSTMENT_VALUE_CHANGED + ? "ADJUSTMENT_VALUE_CHANGED,adjType=" : "unknown type,adjType=") + + (adjustmentType == UNIT_INCREMENT ? "UNIT_INCREMENT,value=" + : adjustmentType == UNIT_DECREMENT ? "UNIT_DECREMENT,value=" + : adjustmentType == BLOCK_INCREMENT ? "BLOCK_INCREMENT,value=" + : adjustmentType == BLOCK_DECREMENT ? "BLOCK_DECREMENT,value=" + : adjustmentType == TRACK ? "TRACK,value=" : "unknown type,value=") + + value + ",isAdjusting=" + isAdjusting; + } +} // class AdjustmentEvent diff --git a/libjava/classpath/java/awt/event/AdjustmentListener.java b/libjava/classpath/java/awt/event/AdjustmentListener.java new file mode 100644 index 0000000..1eb2e3b --- /dev/null +++ b/libjava/classpath/java/awt/event/AdjustmentListener.java @@ -0,0 +1,58 @@ +/* AdjustmentListener.java -- listen for adjustment events + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * Interface for classes that listen for adjustment events. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @since 1.1 + * @status updated to 1.4 + */ +public interface AdjustmentListener extends EventListener +{ + /** + * This method is called when an adjustable value changes. + * + * @param event the <code>AdjustmentEvent</code> that occurred + */ + void adjustmentValueChanged(AdjustmentEvent event); +} // interface AdjustmentListener diff --git a/libjava/classpath/java/awt/event/ComponentAdapter.java b/libjava/classpath/java/awt/event/ComponentAdapter.java new file mode 100644 index 0000000..6b4893f --- /dev/null +++ b/libjava/classpath/java/awt/event/ComponentAdapter.java @@ -0,0 +1,97 @@ +/* ComponentAdapter.java -- convenience class for writing component listeners + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +/** + * This class implements <code>ComponentListener</code> and implements + * all methods with empty bodies. This allows a listener interested in + * implementing only a subset of the <code>ComponentListener</code> + * interface to extend this class and override only the desired methods. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ComponentEvent + * @see ComponentListener + * @since 1.1 + * @status updated to 1.4 + */ +public abstract class ComponentAdapter implements ComponentListener +{ + /** + * Do nothing default constructor for subclasses. + */ + public ComponentAdapter() + { + } + + /** + * Implements this method from the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void componentResized(ComponentEvent event) + { + } + + /** + * Implements this method from the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void componentMoved(ComponentEvent event) + { + } + + /** + * Implements this method from the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void componentShown(ComponentEvent event) + { + } + + /** + * Implements this method from the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void componentHidden(ComponentEvent event) + { + } +} // class ComponentAdapter diff --git a/libjava/classpath/java/awt/event/ComponentEvent.java b/libjava/classpath/java/awt/event/ComponentEvent.java new file mode 100644 index 0000000..ba9c2a5 --- /dev/null +++ b/libjava/classpath/java/awt/event/ComponentEvent.java @@ -0,0 +1,137 @@ +/* ComponentEvent.java -- notification of events for components + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.AWTEvent; +import java.awt.Component; + +/** + * This class is for events generated when a component is moved, resized, + * hidden, or shown. These events normally do not need to be handled by the + * application, since the AWT system automatically takes care of them. This + * is also the superclass for other events on components, but + * ComponentListeners ignore such subclasses. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ComponentAdapter + * @see ComponentListener + * @since 1.1 + * @status updated to 1.4 + */ +public class ComponentEvent extends AWTEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = 8101406823902992965L; + + /** This is the first id in the range of ids used by this class. */ + public static final int COMPONENT_FIRST = 100; + + /** This is the last id in the range of ids used by this class. */ + public static final int COMPONENT_LAST = 103; + + /** This id indicates that a component was moved. */ + public static final int COMPONENT_MOVED = 100; + + /** This id indicates that a component was resized. */ + public static final int COMPONENT_RESIZED = 101; + + /** This id indicates that a component was shown. */ + public static final int COMPONENT_SHOWN = 102; + + /** This id indicates that a component was hidden. */ + public static final int COMPONENT_HIDDEN = 103; + + /** + * Initializes a new instance of <code>ComponentEvent</code> with the + * specified source and id. Note that an invalid id leads to unspecified + * results. + * + * @param source the source of the event + * @param id the event id + * @throws IllegalArgumentException if source is null + */ + public ComponentEvent(Component source, int id) + { + super(source, id); + } + + /** + * This method returns the event source as a <code>Component</code>. If the + * source has subsequently been modified to a non-Component, this returns + * null. + * + * @return the event source as a <code>Component</code>, or null + */ + public Component getComponent() + { + return source instanceof Component ? (Component) source : null; + } + + /** + * This method returns a string identifying this event. This is the field + * name of the id type, and for COMPONENT_MOVED or COMPONENT_RESIZED, the + * new bounding box of the component. + * + * @return a string identifying this event + */ + public String paramString() + { + // Unlike Sun, we don't throw NullPointerException or ClassCastException + // when source was illegally changed. + switch (id) + { + case COMPONENT_MOVED: + return "COMPONENT_MOVED " + + (source instanceof Component + ? ((Component) source).getBounds() : (Object) ""); + case COMPONENT_RESIZED: + return "COMPONENT_RESIZED " + + (source instanceof Component + ? ((Component) source).getBounds() : (Object) ""); + case COMPONENT_SHOWN: + return "COMPONENT_SHOWN"; + case COMPONENT_HIDDEN: + return "COMPONENT_HIDDEN"; + default: + return "unknown type"; + } + } +} // class ComponentEvent diff --git a/libjava/classpath/java/awt/event/ComponentListener.java b/libjava/classpath/java/awt/event/ComponentListener.java new file mode 100644 index 0000000..b43faae --- /dev/null +++ b/libjava/classpath/java/awt/event/ComponentListener.java @@ -0,0 +1,84 @@ +/* ComponentListener.java -- receive all events for a component + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This interface is for classes that receive all events from a component. + * Normally it is not necessary to process these events since the AWT + * handles them internally, taking all appropriate actions. To watch a subset + * of these events, use a ComponentAdapter. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ComponentAdapter + * @see ComponentEvent + * @since 1.1 + * @status updated to 1.4 + */ +public interface ComponentListener extends EventListener +{ + /** + * This method is called when the component is resized. + * + * @param event the <code>ComponentEvent</code> indicating the resize + */ + void componentResized(ComponentEvent event); + + /** + * This method is called when the component is moved. + * + * @param event the <code>ComponentEvent</code> indicating the move + */ + void componentMoved(ComponentEvent event); + + /** + * This method is called when the component is made visible. + * + * @param event the <code>ComponentEvent</code> indicating the visibility + */ + void componentShown(ComponentEvent event); + + /** + * This method is called when the component is hidden. + * + * @param event the <code>ComponentEvent</code> indicating the visibility + */ + void componentHidden(ComponentEvent event); +} // interface ComponentListener diff --git a/libjava/classpath/java/awt/event/ContainerAdapter.java b/libjava/classpath/java/awt/event/ContainerAdapter.java new file mode 100644 index 0000000..c847adf --- /dev/null +++ b/libjava/classpath/java/awt/event/ContainerAdapter.java @@ -0,0 +1,79 @@ +/* ContainerAdapter.java -- convenience class for writing container listeners + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +/** + * This class implements <code>ContainerListener</code> and implements + * all methods with empty bodies. This allows a listener interested in + * implementing only a subset of the <code>ContainerListener</code> + * interface to extend this class and override only the desired methods. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ContainerEvent + * @see ContainerListener + * @since 1.1 + * @status updated to 1.4 + */ +public abstract class ContainerAdapter implements ContainerListener +{ + /** + * Do nothing default constructor for subclasses. + */ + public ContainerAdapter() + { + } + + /** + * Implements this method from the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void componentAdded(ContainerEvent event) + { + } + + /** + * Implements this method from the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void componentRemoved(ContainerEvent event) + { + } +} // class ContainerAdapter diff --git a/libjava/classpath/java/awt/event/ContainerEvent.java b/libjava/classpath/java/awt/event/ContainerEvent.java new file mode 100644 index 0000000..3c401fe --- /dev/null +++ b/libjava/classpath/java/awt/event/ContainerEvent.java @@ -0,0 +1,135 @@ +/* ContainerEvent.java -- components added/removed from a container + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.Component; +import java.awt.Container; + +/** + * This event is generated when a component is added or removed from a + * container. Applications do not ordinarily need to handle these events + * since the AWT system handles them internally. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ContainerAdapter + * @see ContainerListener + * @since 1.1 + * @status updated to 1.4 + */ +public class ContainerEvent extends ComponentEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -4114942250539772041L; + + /** This is the first id in the id range used by this class. */ + public static final int CONTAINER_FIRST = 300; + + /** This is the last id in the id range used by this class. */ + public static final int CONTAINER_LAST = 301; + + /** This id indicates a component was added to the container. */ + public static final int COMPONENT_ADDED = 300; + + /** This id indicates a component was removed from the container. */ + public static final int COMPONENT_REMOVED = 301; + + /** + * The non-null child component that was added or removed. + * + * @serial the child component that changed + */ + private final Component child; + + /** + * Initializes a new instance of <code>ContainerEvent</code> with the + * specified source and id. Additionally, the affected child component + * is also passed as a parameter. Note that an invalid id leads to + * unspecified results. + * + * @param source the source container of the event + * @param id the event id + * @param child the child component affected by this event + * @throws IllegalArgumentException if source is null + */ + public ContainerEvent(Component source, int id, Component child) + { + super(source, id); + this.child = child; + } + + /** + * Returns the source of this event as a <code>Container</code>. + * + * @return the source of the event + * @throws ClassCastException if the source is changed to a non-Container + */ + public Container getContainer() + { + return (Container) source; + } + + /** + * This method returns the child object that was added or removed from + * the container. + * + * @return the child object added or removed + */ + public Component getChild() + { + return child; + } + + /** + * This method returns a string identifying this event. It is formatted as: + * <code>(getID() == COMPONENT_ADDED ? "COMPONENT_ADDED" + * : "COMPONENT_REMOVED") + ",child=" + getChild().getName()</code>. + * + * @return a string identifying this event + */ + public String paramString() + { + // Unlike Sun, we don't throw NullPointerException if child is illegally + // null. + return (id == COMPONENT_ADDED ? "COMPONENT_ADDED,child=" + : id == COMPONENT_REMOVED ? "COMPONENT_REMOVED,child=" + : "unknown type,child=") + (child == null ? "" : child.getName()); + } +} // class ContainerEvent diff --git a/libjava/classpath/java/awt/event/ContainerListener.java b/libjava/classpath/java/awt/event/ContainerListener.java new file mode 100644 index 0000000..b37d434 --- /dev/null +++ b/libjava/classpath/java/awt/event/ContainerListener.java @@ -0,0 +1,70 @@ +/* ContainerListener.java -- listen for container events + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This interface is for classes that wish to listen for all events from + * container objects. This is normally not necessary since the AWT system + * listens for and processes these events. To watch a subset of these events, + * use a ContainerAdapter. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ContainerAdapter + * @see ContainerEvent + * @since 1.1 + * @status updated to 1.4 + */ +public interface ContainerListener extends EventListener +{ + /** + * This method is called when a component is added to the container. + * + * @param event the <code>ContainerEvent</code> indicating component addition + */ + void componentAdded(ContainerEvent event); + + /** + * This method is called when a component is removed from the container. + * + * @param event the <code>ContainerEvent</code> indicating component removal + */ + void componentRemoved(ContainerEvent event); +} // interface ContainerListener diff --git a/libjava/classpath/java/awt/event/FocusAdapter.java b/libjava/classpath/java/awt/event/FocusAdapter.java new file mode 100644 index 0000000..fb0532a --- /dev/null +++ b/libjava/classpath/java/awt/event/FocusAdapter.java @@ -0,0 +1,79 @@ +/* FocusAdapter.java -- convenience class for writing focus listeners + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +/** + * This class implements <code>FocusListener</code> and implements all + * methods with empty bodies. This allows a listener interested in + * implementing only a subset of the <code>FocusListener</code> interface to + * extend this class and override only the desired methods. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see FocusEvent + * @see FocusListener + * @since 1.1 + * @status updated to 1.4 + */ +public abstract class FocusAdapter implements FocusListener +{ + /** + * Do nothing default constructor for subclasses. + */ + public FocusAdapter() + { + } + + /** + * Implements this method from the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void focusGained(FocusEvent event) + { + } + + /** + * Implements this method from the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void focusLost(FocusEvent event) + { + } +} // class FocusAdapter diff --git a/libjava/classpath/java/awt/event/FocusEvent.java b/libjava/classpath/java/awt/event/FocusEvent.java new file mode 100644 index 0000000..a44284a --- /dev/null +++ b/libjava/classpath/java/awt/event/FocusEvent.java @@ -0,0 +1,181 @@ +/* FocusEvent.java -- generated for a focus change + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.Component; + +/** + * This class represents an event generated when a focus change occurs for a + * component. There are both temporary changes, such as when focus is stolen + * during a sroll then returned, and permanent changes, such as when the user + * TABs through focusable components. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see FocusAdapter + * @see FocusListener + * @since 1.1 + * @status updated to 1.4 + */ +public class FocusEvent extends ComponentEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = 523753786457416396L; + + /** This is the first id in the range of ids used by this class. */ + public static final int FOCUS_FIRST = 1004; + + /** This is the last id in the range of ids used by this class. */ + public static final int FOCUS_LAST = 1005; + + /** This is the event id for a focus gained event. */ + public static final int FOCUS_GAINED = 1004; + + /** This is the event id for a focus lost event. */ + public static final int FOCUS_LOST = 1005; + + /** + * Indicates whether or not the focus change is temporary. + * + * @see #isTemporary() + * @serial true if the focus change is temporary + */ + private final boolean temporary; + + /** + * The other component which is giving up or stealing focus from this + * component, if known. + * + * @see #getOppositeComponent() + * @serial the component with the opposite focus event, or null + * @since 1.4 + */ + private final Component opposite; + + /** + * Initializes a new instance of <code>FocusEvent</code> with the + * specified source, id, temporary status, and opposite counterpart. Note + * that an invalid id leads to unspecified results. + * + * @param source the component that is gaining or losing focus + * @param id the event id + * @param temporary true if the focus change is temporary + * @param opposite the component receiving the opposite focus event, or null + * @throws IllegalArgumentException if source is null + */ + public FocusEvent(Component source, int id, boolean temporary, + Component opposite) + { + super(source, id); + this.temporary = temporary; + this.opposite = opposite; + } + + /** + * Initializes a new instance of <code>FocusEvent</code> with the + * specified source, id, and temporary status. Note that an invalid id + * leads to unspecified results. + * + * @param source the component that is gaining or losing focus + * @param id the event id + * @param temporary true if the focus change is temporary + * @throws IllegalArgumentException if source is null + */ + public FocusEvent(Component source, int id, boolean temporary) + { + this(source, id, temporary, null); + } + + /** + * Initializes a new instance of <code>FocusEvent</code> with the + * specified source and id. Note that an invalid id leads to unspecified + * results. + * + * @param source the component that is gaining or losing focus + * @param id the event id + * @throws IllegalArgumentException if source is null + */ + public FocusEvent(Component source, int id) + { + this(source, id, false, null); + } + + /** + * This method tests whether or not the focus change is temporary or + * permanent. + * + * @return true if the focus change is temporary + */ + public boolean isTemporary() + { + return temporary; + } + + /** + * Returns the component which received the opposite focus event. If this + * component gained focus, the opposite lost focus; likewise if this + * component is giving up focus, the opposite is gaining it. If this + * information is unknown, perhaps because the opposite is a native + * application, this returns null. + * + * @return the component with the focus opposite, or null + * @since 1.4 + */ + public Component getOppositeComponent() + { + return opposite; + } + + /** + * Returns a string identifying this event. This is formatted as: + * <code>(getID() == FOCUS_GAINED ? "FOCUS_GAINED" : "FOCUS_LOST") + * + (isTemporary() ? ",temporary," : ",permanent,") + "opposite=" + * + getOppositeComponent()</code>. + * + * @return a string identifying this event + */ + public String paramString() + { + return (id == FOCUS_GAINED ? "FOCUS_GAINED" + : id == FOCUS_LOST ? "FOCUS_LOST" : "unknown type") + + (temporary ? ",temporary,opposite=" : ",permanent,opposite=") + + opposite; + } +} // class FocusEvent diff --git a/libjava/classpath/java/awt/event/FocusListener.java b/libjava/classpath/java/awt/event/FocusListener.java new file mode 100644 index 0000000..1f72018 --- /dev/null +++ b/libjava/classpath/java/awt/event/FocusListener.java @@ -0,0 +1,69 @@ +/* FocusListener.java -- listen for focus changes + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This interface is for classes that wish to be notified of changes of + * keyboard focus for a component. To watch a subset of these events, use a + * FocusAdapter. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see FocusAdapter + * @see FocusEvent + * @since 1.1 + * @status updated to 1.4 + */ +public interface FocusListener extends EventListener +{ + /** + * This method is called when a component gains the keyboard focus. + * + * @param event the <code>FocusEvent</code> indicating that focus was gained + */ + void focusGained(FocusEvent event); + + /** + * This method is invoked when a component loses the keyboard focus. + * + * @param event the <code>FocusEvent</code> indicating that focus was lost + */ + void focusLost(FocusEvent event); +} // interface FocusListener diff --git a/libjava/classpath/java/awt/event/HierarchyBoundsAdapter.java b/libjava/classpath/java/awt/event/HierarchyBoundsAdapter.java new file mode 100644 index 0000000..340cf01 --- /dev/null +++ b/libjava/classpath/java/awt/event/HierarchyBoundsAdapter.java @@ -0,0 +1,78 @@ +/* HierarchyBoundsAdapter.java -- convenience class for writing listeners + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.event; + +/** + * This class implements <code>HierarchyBoundsListener</code> and implements + * all methods with empty bodies. This allows a listener interested in + * implementing only a subset of the <code>HierarchyBoundsListener</code> + * interface to extend this class and override only the desired methods. + * + * @author Bryce McKinlay + * @see HierarchyBoundsListener + * @see HierarchyEvent + * @since 1.3 + * @status updated to 1.4 + */ +public abstract class HierarchyBoundsAdapter implements HierarchyBoundsListener +{ + /** + * Do nothing default constructor for subclasses. + */ + public HierarchyBoundsAdapter() + { + } + + /** + * Implements this method from the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void ancestorMoved(HierarchyEvent event) + { + } + + /** + * Implements this method from the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void ancestorResized(HierarchyEvent event) + { + } +} diff --git a/libjava/classpath/java/awt/event/HierarchyBoundsListener.java b/libjava/classpath/java/awt/event/HierarchyBoundsListener.java new file mode 100644 index 0000000..6896237 --- /dev/null +++ b/libjava/classpath/java/awt/event/HierarchyBoundsListener.java @@ -0,0 +1,70 @@ +/* HierarchyBoundsListener.java -- listens to bounds changes of parents + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This listens for changes in an ancestors size or location. Normally it is + * not necessary to process these events since the AWT handles them + * internally, taking all appropriate actions. To watch a subset of these + * events, use a HierarchyBoundsAdapter. + * + * @author Bryce McKinlay + * @see HierarchyBoundsAdapter + * @see HierarchyEvent + * @since 1.3 + * @status updated to 1.4 + */ +public interface HierarchyBoundsListener extends EventListener +{ + /** + * Called when an ancestor component of the source is moved. + * + * @param e the event describing the ancestor's motion + */ + void ancestorMoved(HierarchyEvent e); + + /** + * Called when an ancestor component is resized. + * + * @param e the event describing the ancestor's resizing + */ + void ancestorResized(HierarchyEvent e); +} // interface HierarchyBoundsListener diff --git a/libjava/classpath/java/awt/event/HierarchyEvent.java b/libjava/classpath/java/awt/event/HierarchyEvent.java new file mode 100644 index 0000000..e10cefb --- /dev/null +++ b/libjava/classpath/java/awt/event/HierarchyEvent.java @@ -0,0 +1,253 @@ +/* HierarchyEvent.java -- generated for a change in hierarchy + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.Container; + +/** + * This class represents an event generated for an ancestor component which + * may affect this component. These events normally do not need to be handled + * by the application, since the AWT system automatically takes care of them. + * + * <p>There are two types of hierarchy events. The first type is handled by + * HierarchyListener, and includes addition or removal of an ancestor, or + * an ancestor changing its on-screen status (visible and/or displayble). The + * second type is handled by HierarchyBoundsListener, and includes resizing + * or moving of an ancestor. + * + * @author Bryce McKinlay + * @see HierarchyListener + * @see HierarchyBoundsAdapter + * @see HierarchyBoundsListener + * @since 1.3 + * @status updated to 1.4 + */ +public class HierarchyEvent extends AWTEvent +{ + /** + * Compatible with JDK 1.3+. + */ + private static final long serialVersionUID = -5337576970038043990L; + + /** This is the first id in the range of ids used by this class. */ + public static final int HIERARCHY_FIRST = 1400; + + /** This id indicates that the hierarchy tree changed. */ + public static final int HIERARCHY_CHANGED = 1400; + + /** This id indicates that an ancestor was moved. */ + public static final int ANCESTOR_MOVED = 1401; + + /** This id indicates that an ancestor was resized. */ + public static final int ANCESTOR_RESIZED = 1402; + + /** This is the last id in the range of ids used by this class. */ + public static final int HIERARCHY_LAST = 1402; + + /** This indicates that the HIERARCHY_CHANGED is a changed parent. */ + public static final int PARENT_CHANGED = 1; + + /** + * This indicates that the HIERARCHY_CHANGED is caused by a change in + * displayability. + * + * @see Component#isDisplayable() + * @see Component#addNotify() + * @see Component#removeNotify() + */ + public static final int DISPLAYABILITY_CHANGED = 2; + + /** + * This indicates that the HIERARCHY_CHANGED is a changed visibility. + * + * @see Component#isShowing() + * @see Component#addNotify() + * @see Component#removeNotify() + * @see Component#show() + * @see Component#hide() + */ + public static final int SHOWING_CHANGED = 4; + + /** + * The component at the top of the changed hierarchy. + * + * @serial the top component changed + */ + private final Component changed; + + /** + * The parent of this component, either before or after the change depending + * on the type of change. + * + * @serial the parent component changed + */ + private final Container changedParent; + + /** + * The bitmask of HIERARCHY_CHANGED event types. + * + * @serial the change flags + */ + private final long changeFlags; + + /** + * Initializes a new instance of <code>HierarchyEvent</code> with the + * specified parameters. Note that an invalid id leads to unspecified + * results. + * + * @param source the component whose hierarchy changed + * @param id the event id + * @param changed the top component in the tree of changed hierarchy + * @param changedParent the updated parent of this object + * @throws IllegalArgumentException if source is null + */ + public HierarchyEvent(Component source, int id, Component changed, + Container changedParent) + { + this(source, id, changed, changedParent, 0); + } + + /** + * Initializes a new instance of <code>HierarchyEvent</code> with the + * specified parameters. Note that an invalid id leads to unspecified + * results. + * + * @param source the component whose hierarchy changed + * @param id the event id + * @param changed the top component in the tree of changed hierarchy + * @param changedParent the updated parent of this object + * @param changeFlags the bitmask of specific HIERARCHY_CHANGED events + * @throws IllegalArgumentException if source is null + */ + public HierarchyEvent(Component source, int id, Component changed, + Container changedParent, long changeFlags) + { + super(source, id); + this.changed = changed; + this.changedParent = changedParent; + this.changeFlags = changeFlags; + } + + /** + * This method returns the event source as a <code>Component</code>. If the + * source has subsequently been modified to a non-Component, this returns + * null. + * + * @return the event source as a <code>Component</code>, or null + */ + public Component getComponent() + { + return source instanceof Component ? (Component) source : null; + } + + /** + * Returns the component at the top of the hierarchy which changed. + * + * @return the top changed component + */ + public Component getChanged() + { + return changed; + } + + /** + * Returns the parent of the component listed in <code>getChanged()</code>. + * If the cause of this event was <code>Container.add</code>, this is the + * new parent; if the cause was <code>Container.remove</code>, this is the + * old parent; otherwise it is the unchanged parent. + * + * @return the parent container of the changed component + */ + public Container getChangedParent() + { + return changedParent; + } + + /** + * If this is a HIERARCHY_CHANGED event, this returns a bitmask of the + * types of changes that took place. + * + * @return the bitwise or of hierarchy change types, or 0 + * @see #PARENT_CHANGED + * @see #DISPLAYABILITY_CHANGED + * @see #SHOWING_CHANGED + */ + public long getChangeFlags() + { + return changeFlags; + } + + /** + * This method returns a string identifying this event. This is the field + * name of the id type, followed by a parenthesized listing of the changed + * component and its parent container. In addition, if the type is + * HIERARCHY_CHANGED, the flags preceed the changed component, in the + * order PARENT_CHANGED, DISPLAYABILITY_CHANGED, and SHOWING_CHANGED. + * + * @return a string identifying this event + */ + public String paramString() + { + StringBuffer r = new StringBuffer(); + switch (id) + { + case HIERARCHY_CHANGED: + r.append("HIERARCHY_CHANGED ("); + if ((changeFlags & PARENT_CHANGED) != 0) + r.append("PARENT_CHANGED,"); + if ((changeFlags & DISPLAYABILITY_CHANGED) != 0) + r.append("DISPLAYABILITY_CHANGED,"); + if ((changeFlags & SHOWING_CHANGED) != 0) + r.append("SHOWING_CHANGED,"); + break; + case ANCESTOR_MOVED: + r.append("ANCESTOR_MOVED ("); + break; + case ANCESTOR_RESIZED: + r.append("ANCESTOR_RESIZED ("); + break; + default: + return "unknown type"; + } + r.append(changed).append(',').append(changedParent).append(')'); + return r.toString(); + } +} // class HierarchyEvent diff --git a/libjava/classpath/java/awt/event/HierarchyListener.java b/libjava/classpath/java/awt/event/HierarchyListener.java new file mode 100644 index 0000000..f90414b --- /dev/null +++ b/libjava/classpath/java/awt/event/HierarchyListener.java @@ -0,0 +1,62 @@ +/* HierarchyListener.java -- listens to changes in the component hierarchy + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This listens for changes in the hierarchy tree of components. Normally it is + * not necessary to process these events since the AWT handles them + * internally, taking all appropriate actions. + * + * @author Bryce McKinlay + * @see HierarchyEvent + * @since 1.3 + * @status updated to 1.4 + */ +public interface HierarchyListener extends EventListener +{ + /** + * Called when the hierarchy of this component changes. Use + * <code>getChangeFlags()</code> on the event to see what exactly changed. + * + * @param e the event describing the change + */ + void hierarchyChanged(HierarchyEvent e); +} // interface HierarchyListener diff --git a/libjava/classpath/java/awt/event/InputEvent.java b/libjava/classpath/java/awt/event/InputEvent.java new file mode 100644 index 0000000..8f9aed6 --- /dev/null +++ b/libjava/classpath/java/awt/event/InputEvent.java @@ -0,0 +1,381 @@ +/* InputEvent.java -- common superclass of component input events + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import gnu.java.awt.EventModifier; + +import java.awt.Component; + +/** + * This is the common superclass for all component input classes. These are + * passed to listeners before the component, so that listeners can consume + * the event before it does its default behavior. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see KeyEvent + * @see KeyAdapter + * @see MouseEvent + * @see MouseAdapter + * @see MouseMotionAdapter + * @see MouseWheelEvent + * @since 1.1 + * @status updated to 1.4 + */ +public abstract class InputEvent extends ComponentEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -2482525981698309786L; + + /** + * This is the bit mask which indicates the shift key is down. It is + * recommended that SHIFT_DOWN_MASK be used instead. + * + * @see #SHIFT_DOWN_MASK + */ + public static final int SHIFT_MASK = 1; + + /** + * This is the bit mask which indicates the control key is down. It is + * recommended that CTRL_DOWN_MASK be used instead. + * + * @see #CTRL_DOWN_MASK + */ + public static final int CTRL_MASK = 2; + + /** + * This is the bit mask which indicates the meta key is down. It is + * recommended that META_DOWN_MASK be used instead. + * + * @see #META_DOWN_MASK + */ + public static final int META_MASK = 4; + + /** + * This is the bit mask which indicates the alt key is down. It is + * recommended that ALT_DOWN_MASK be used instead. + * + * @see #ALT_DOWN_MASK + */ + public static final int ALT_MASK = 8; + + /** + * This is the bit mask which indicates the alt-graph modifier is in effect. + * It is recommended that ALT_GRAPH_DOWN_MASK be used instead. + * + * @see #ALT_GRAPH_DOWN_MASK + */ + public static final int ALT_GRAPH_MASK = 0x20; + + /** + * This bit mask indicates mouse button one is down. It is recommended that + * BUTTON1_DOWN_MASK be used instead. + * + * @see #BUTTON1_DOWN_MASK + */ + public static final int BUTTON1_MASK = 0x10; + + /** + * This bit mask indicates mouse button two is down. It is recommended that + * BUTTON2_DOWN_MASK be used instead. + * + * @see #BUTTON2_DOWN_MASK + */ + public static final int BUTTON2_MASK = 8; + + /** + * This bit mask indicates mouse button three is down. It is recommended + * that BUTTON3_DOWN_MASK be used instead. + * + * @see #BUTTON3_DOWN_MASK + */ + public static final int BUTTON3_MASK = 4; + + /** + * The SHIFT key extended modifier. + * + * @since 1.4 + */ + public static final int SHIFT_DOWN_MASK = 0x0040; + + /** + * The CTRL key extended modifier. + * + * @since 1.4 + */ + public static final int CTRL_DOWN_MASK = 0x0080; + + /** + * The META key extended modifier. + * + * @since 1.4 + */ + public static final int META_DOWN_MASK = 0x0100; + + /** + * The ALT key extended modifier. + * + * @since 1.4 + */ + public static final int ALT_DOWN_MASK = 0x0200; + + /** + * The mouse button1 key extended modifier. + * + * @since 1.4 + */ + public static final int BUTTON1_DOWN_MASK = 0x0400; + + /** + * The mouse button2 extended modifier. + * + * @since 1.4 + */ + public static final int BUTTON2_DOWN_MASK = 0x0800; + + /** + * The mouse button3 extended modifier. + * + * @since 1.4 + */ + public static final int BUTTON3_DOWN_MASK = 0x1000; + + /** + * The ALT_GRAPH key extended modifier. + * + * @since 1.4 + */ + public static final int ALT_GRAPH_DOWN_MASK = 0x2000; + + /** The mask to convert new to old, package visible for use in subclasses. */ + static final int CONVERT_MASK + = EventModifier.NEW_MASK & ~(BUTTON2_DOWN_MASK | BUTTON3_DOWN_MASK); + + /** + * The timestamp when this event occurred. + * + * @see #getWhen() + * @serial the timestamp + */ + private final long when; + + /** + * The modifiers in effect for this event. Package visible for use by + * subclasses. The old style (bitmask 0x3f) should not be mixed with the + * new style (bitmasks 0xffffffc0). + * + * @see #getModifiers() + * @see MouseEvent + * @serial the modifier state, stored in the new style + */ + int modifiers; + + /** + * Initializes a new instance of <code>InputEvent</code> with the specified + * source, id, timestamp, and modifiers. Note that an invalid id leads to + * unspecified results. + * + * @param source the source of the event + * @param id the event id + * @param when the timestamp when the event occurred + * @param modifiers the modifiers in effect for this event, old or new style + * @throws IllegalArgumentException if source is null + */ + InputEvent(Component source, int id, long when, int modifiers) + { + super(source, id); + this.when = when; + this.modifiers = EventModifier.extend(modifiers); + } + + /** + * This method tests whether or not the shift key was down during the event. + * + * @return true if the shift key is down + */ + public boolean isShiftDown() + { + return (modifiers & SHIFT_DOWN_MASK) != 0; + } + + /** + * This method tests whether or not the control key was down during the + * event. + * + * @return true if the control key is down + */ + public boolean isControlDown() + { + return (modifiers & CTRL_DOWN_MASK) != 0; + } + + /** + * This method tests whether or not the meta key was down during the event. + * + * @return true if the meta key is down + */ + public boolean isMetaDown() + { + return (modifiers & META_DOWN_MASK) != 0; + } + + /** + * This method tests whether or not the alt key was down during the event. + * + * @return true if the alt key is down + */ + public boolean isAltDown() + { + return (modifiers & ALT_DOWN_MASK) != 0; + } + + /** + * This method tests whether or not the alt-graph modifier was in effect + * during the event. + * + * @return true if the alt-graph modifier is down + */ + public boolean isAltGraphDown() + { + return (modifiers & ALT_GRAPH_DOWN_MASK) != 0; + } + + /** + * This method returns the timestamp when this event occurred. + * + * @return the timestamp when this event occurred + */ + public long getWhen() + { + return when; + } + + /** + * This method returns the old-style modifiers in effect for this event. + * Note that this is ambiguous between button2 and alt, and between + * button3 and meta. Also, code which generated these modifiers tends to + * only list the modifier that just changed, even if others were down at + * the time. Consider using getModifiersEx instead. This will be a union + * of the bit masks defined in this class that are applicable to the event. + * + * @return the modifiers in effect for this event + * @see #getModifiersEx() + */ + public int getModifiers() + { + return EventModifier.revert(modifiers); + } + + /** + * Returns the extended modifiers (new-style) for this event. This represents + * the state of all modal keys and mouse buttons at the time of the event, + * and does not suffer from the problems mentioned in getModifiers. + * + * <p>For an example of checking multiple modifiers, this code will return + * true only if SHIFT and BUTTON1 were pressed and CTRL was not: + * <pre> + * int onmask = InputEvent.SHIFT_DOWN_MASK | InputEvent.BUTTON1_DOWN_MASK; + * int offmask = InputEvent.CTRL_DOWN_MASK; + * return (event.getModifiersEx() & (onmask | offmask)) == onmask; + * </pre> + * + * @return the bitwise or of all modifiers pressed during the event + * @since 1.4 + */ + public int getModifiersEx() + { + return modifiers; + } + + /** + * Consumes this event. A consumed event is not processed further by the AWT + * system. + */ + public void consume() + { + consumed = true; + } + + /** + * This method tests whether or not this event has been consumed. + * + * @return true if this event has been consumed + */ + public boolean isConsumed() + { + return consumed; + } + + /** + * Convert the extended modifier bitmask into a String, such as "Shift" or + * "Ctrl+Button1". + * + * XXX Sun claims this can be localized via the awt.properties file - how + * do we implement that? + * + * @param modifiers the modifiers + * @return a string representation of the modifiers in this bitmask + * @since 1.4 + */ + public static String getModifiersExText(int modifiers) + { + modifiers &= EventModifier.NEW_MASK; + if (modifiers == 0) + return ""; + StringBuffer s = new StringBuffer(); + if ((modifiers & META_DOWN_MASK) != 0) + s.append("Meta+"); + if ((modifiers & CTRL_DOWN_MASK) != 0) + s.append("Ctrl+"); + if ((modifiers & ALT_DOWN_MASK) != 0) + s.append("Alt+"); + if ((modifiers & SHIFT_DOWN_MASK) != 0) + s.append("Shift+"); + if ((modifiers & ALT_GRAPH_DOWN_MASK) != 0) + s.append("Alt Graph+"); + if ((modifiers & BUTTON1_DOWN_MASK) != 0) + s.append("Button1+"); + if ((modifiers & BUTTON2_DOWN_MASK) != 0) + s.append("Button2+"); + if ((modifiers & BUTTON3_DOWN_MASK) != 0) + s.append("Button3+"); + return s.substring(0, s.length() - 1); + } +} // class InputEvent diff --git a/libjava/classpath/java/awt/event/InputMethodEvent.java b/libjava/classpath/java/awt/event/InputMethodEvent.java new file mode 100644 index 0000000..f6711a8 --- /dev/null +++ b/libjava/classpath/java/awt/event/InputMethodEvent.java @@ -0,0 +1,303 @@ +/* InputMethodEvent.java -- events from a text input method + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.font.TextHitInfo; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.text.AttributedCharacterIterator; + +/** + * This class is for event generated by change in a text input method. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see InputMethodListener + * @since 1.2 + * @status updated to 1.4 + */ +public class InputMethodEvent extends AWTEvent +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 4727190874778922661L; + + /** This is the first id in the range of event ids used by this class. */ + public static final int INPUT_METHOD_FIRST = 1100; + + /** This event id indicates that the text in the input method has changed. */ + public static final int INPUT_METHOD_TEXT_CHANGED = 1100; + + /** This event id indicates that the input method curor point has changed. */ + public static final int CARET_POSITION_CHANGED = 1101; + + /** This is the last id in the range of event ids used by this class. */ + public static final int INPUT_METHOD_LAST = 1101; + + /** + * The timestamp when this event was created. + * + * @serial the timestamp + * @since 1.4 + */ + private long when; + + /** The input method text. */ + private final transient AttributedCharacterIterator text; + + /** The number of committed characters in the text. */ + private final transient int committedCharacterCount; + + /** The caret. */ + private final transient TextHitInfo caret; + + /** The most important position to be visible. */ + private final transient TextHitInfo visiblePosition; + + /** + * Initializes a new instance of <code>InputMethodEvent</code> with the + * specified source, id, timestamp, text, char count, caret, and visible + * position. + * + * @param source the source that generated the event + * @param id the event id + * @param when the timestamp of the event + * @param text the input text + * @param committedCharacterCount the number of committed characters + * @param caret the caret position + * @param visiblePosition the position most important to make visible + * @throws IllegalArgumentException if source is null, id is invalid, id is + * CARET_POSITION_CHANGED and text is non-null, or if + * committedCharacterCount is out of range + * @since 1.4 + */ + public InputMethodEvent(Component source, int id, long when, + AttributedCharacterIterator text, + int committedCharacterCount, TextHitInfo caret, + TextHitInfo visiblePosition) + { + super(source, id); + this.when = when; + this.text = text; + this.committedCharacterCount = committedCharacterCount; + this.caret = caret; + this.visiblePosition = visiblePosition; + if (id < INPUT_METHOD_FIRST || id > INPUT_METHOD_LAST + || (id == CARET_POSITION_CHANGED && text != null) + || committedCharacterCount < 0 + || (committedCharacterCount + > (text == null ? 0 : text.getEndIndex() - text.getBeginIndex()))) + throw new IllegalArgumentException(); + } + + /** + * Initializes a new instance of <code>InputMethodEvent</code> with the + * specified source, id, text, char count, caret, and visible position. + * + * @param source the source that generated the event + * @param id the event id + * @param text the input text + * @param committedCharacterCount the number of committed characters + * @param caret the caret position + * @param visiblePosition the position most important to make visible + * @throws IllegalArgumentException if source is null, id is invalid, id is + * CARET_POSITION_CHANGED and text is non-null, or if + * committedCharacterCount is out of range + * @since 1.4 + */ + public InputMethodEvent(Component source, int id, + AttributedCharacterIterator text, + int committedCharacterCount, TextHitInfo caret, + TextHitInfo visiblePosition) + { + this(source, id, EventQueue.getMostRecentEventTime(), text, + committedCharacterCount, caret, visiblePosition); + } + + /** + * Initializes a new instance of <code>InputMethodEvent</code> with the + * specified source, id, caret, and visible position, and with a null + * text and char count. + * + * @param source the source that generated the event + * @param id the event id + * @param caret the caret position + * @param visiblePosition the position most important to make visible + * @throws IllegalArgumentException if source is null or id is invalid + * @since 1.4 + */ + public InputMethodEvent(Component source, int id, TextHitInfo caret, + TextHitInfo visiblePosition) + { + this(source, id, EventQueue.getMostRecentEventTime(), null, 0, caret, + visiblePosition); + } + + /** + * This method returns the input method text. This can be <code>null</code>, + * and will always be null for <code>CARET_POSITION_CHANGED</code> events. + * Characters from 0 to <code>getCommittedCharacterCount()-1</code> have + * been committed, the remaining characters are composed text. + * + * @return the input method text, or null + */ + public AttributedCharacterIterator getText() + { + return text; + } + + /** + * Returns the number of committed characters in the input method text. + * + * @return the number of committed characters in the input method text + */ + public int getCommittedCharacterCount() + { + return committedCharacterCount; + } + + /** + * Returns the caret position. The caret offset is relative to the composed + * text of the most recent <code>INPUT_METHOD_TEXT_CHANGED</code> event. + * + * @return the caret position, or null + */ + public TextHitInfo getCaret() + { + return caret; + } + + /** + * Returns the position that is most important to be visible, or null if + * such a hint is not necessary. The caret offset is relative to the composed + * text of the most recent <code>INPUT_METHOD_TEXT_CHANGED</code> event. + * + * @return the position that is most important to be visible + */ + public TextHitInfo getVisiblePosition() + { + return visiblePosition; + } + + /** + * This method consumes the event. A consumed event is not processed + * in the default manner by the component that generated it. + */ + public void consume() + { + consumed = true; + } + + /** + * This method tests whether or not this event has been consumed. + * + * @return true if the event has been consumed + */ + public boolean isConsumed() + { + return consumed; + } + + /** + * Return the timestamp of this event. + * + * @return the timestamp + * @since 1.4 + */ + public long getWhen() + { + return when; + } + + /** + * This method returns a string identifying the event. This contains the + * event ID, the committed and composed characters separated by '+', the + * number of committed characters, the caret, and the visible position. + * + * @return a string identifying the event + */ + public String paramString() + { + StringBuffer s + = new StringBuffer(80 + (text == null ? 0 + : text.getEndIndex() - text.getBeginIndex())); + s.append(id == INPUT_METHOD_TEXT_CHANGED ? "INPUT_METHOD_TEXT_CHANGED, " + : "CARET_POSITION_CHANGED, "); + if (text == null) + s.append("no text, 0 characters committed, caret: "); + else + { + s.append('"'); + int i = text.getBeginIndex(); + int j = committedCharacterCount; + while (--j >= 0) + s.append(text.setIndex(i++)); + s.append("\" + \""); + j = text.getEndIndex() - i; + while (--j >= 0) + s.append(text.setIndex(i++)); + s.append("\", ").append(committedCharacterCount) + .append(" characters committed, caret: "); + } + s.append(caret == null ? (Object) "no caret" : caret).append(", ") + .append(visiblePosition == null ? (Object) "no visible position" + : visiblePosition); + return s.toString(); + } + + /** + * Reads in the object from a serial stream, updating when to + * {@link EventQueue#getMostRecentEventTime()} if necessary. + * + * @param s the stream to read from + * @throws IOException if deserialization fails + * @throws ClassNotFoundException if deserialization fails + * @serialData default, except for updating when + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + if (when == 0) + when = EventQueue.getMostRecentEventTime(); + } +} // class InputMethodEvent diff --git a/libjava/classpath/java/awt/event/InputMethodListener.java b/libjava/classpath/java/awt/event/InputMethodListener.java new file mode 100644 index 0000000..e2f6a4e --- /dev/null +++ b/libjava/classpath/java/awt/event/InputMethodListener.java @@ -0,0 +1,70 @@ +/* InputMethodListener.java -- listen for input method events + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.im.InputMethodRequests; +import java.util.EventListener; + +/** + * This interface is for classes that wish to receive events from an input + * method. For a text component to use input methods, it must also install + * an InputMethodRequests handler. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see InputMethodEvent + * @see InputMethodRequests + * @since 1.2 + * @status updated to 1.4 + */ +public interface InputMethodListener extends EventListener +{ + /** + * This method is called when the text is changed. + * + * @param event the <code>InputMethodEvent</code> indicating the text change + */ + void inputMethodTextChanged(InputMethodEvent event); + + /** + * This method is called when the cursor position within the text is changed. + * + * @param event the <code>InputMethodEvent</code> indicating the change + */ + void caretPositionChanged(InputMethodEvent event); +} // interface InputMethodListener diff --git a/libjava/classpath/java/awt/event/InvocationEvent.java b/libjava/classpath/java/awt/event/InvocationEvent.java new file mode 100644 index 0000000..75feb62 --- /dev/null +++ b/libjava/classpath/java/awt/event/InvocationEvent.java @@ -0,0 +1,237 @@ +/* InvocationEvent.java -- call a runnable when dispatched + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.AWTEvent; +import java.awt.ActiveEvent; +import java.awt.EventQueue; + +/** + * This event executes {@link Runnable#run()} of a target object when it is + * dispatched. This class is used by calls to <code>invokeLater</code> and + * <code>invokeAndWait</code>, so client code can use this fact to avoid + * writing special-casing AWTEventListener objects. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ActiveEvent + * @see EventQueue#invokeLater(Runnable) + * @see EventQueue#invokeAndWait(Runnable) + * @see AWTEventListener + * @since 1.2 + * @status updated to 1.4 + */ +public class InvocationEvent extends AWTEvent implements ActiveEvent +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 436056344909459450L; + + /** This is the first id in the range of event ids used by this class. */ + public static final int INVOCATION_FIRST = 1200; + + /** This is the default id for this event type. */ + public static final int INVOCATION_DEFAULT = 1200; + + /** This is the last id in the range of event ids used by this class. */ + public static final int INVOCATION_LAST = 1200; + + /** + * This is the <code>Runnable</code> object to call when dispatched. + * + * @serial the runnable to execute + */ + protected Runnable runnable; + + /** + * This is the object to call <code>notifyAll()</code> on when + * the call to <code>run()</code> returns, or <code>null</code> if no + * object is to be notified. + * + * @serial the object to notify + */ + protected Object notifier; + + /** + * This variable is set to <code>true</code> if exceptions are caught + * and stored in a variable during the call to <code>run()</code>, otherwise + * exceptions are ignored and propagate up. + * + * @serial true to catch exceptions + */ + protected boolean catchExceptions; + + /** + * This is the caught exception thrown in the <code>run()</code> method. It + * is null if exceptions are ignored, the run method hasn't completed, or + * there were no exceptions. + * + * @serial the caught exception, if any + */ + private Exception exception; + + /** + * The timestamp when this event was created. + * + * @see #getWhen() + * @serial the timestamp + * @since 1.4 + */ + private final long when = EventQueue.getMostRecentEventTime(); + + /** + * Initializes a new instance of <code>InvocationEvent</code> with the + * specified source and runnable. + * + * @param source the source of the event + * @param runnable the <code>Runnable</code> object to invoke + * @throws IllegalArgumentException if source is null + */ + public InvocationEvent(Object source, Runnable runnable) + { + this(source, INVOCATION_DEFAULT, runnable, null, false); + } + + /** + * Initializes a new instance of <code>InvocationEvent</code> with the + * specified source, runnable, and notifier. It will also catch exceptions + * if specified. If notifier is non-null, this will call notifyAll() on + * the object when the runnable is complete. If catchExceptions is true, + * this traps any exception in the runnable, otherwise it lets the exception + * propagate up the Event Dispatch thread. + * + * @param source the source of the event + * @param runnable the <code>Runnable</code> object to invoke + * @param notifier the object to notify, or null + * @param catchExceptions true to catch exceptions from the runnable + */ + public InvocationEvent(Object source, Runnable runnable, Object notifier, + boolean catchExceptions) + { + this(source, INVOCATION_DEFAULT, runnable, notifier, catchExceptions); + } + + /** + * Initializes a new instance of <code>InvocationEvent</code> with the + * specified source, runnable, and notifier. It will also catch exceptions + * if specified. If notifier is non-null, this will call notifyAll() on + * the object when the runnable is complete. If catchExceptions is true, + * this traps any exception in the runnable, otherwise it lets the exception + * propagate up the Event Dispatch thread. Note that an invalid id leads to + * unspecified results. + * + * @param source the source of the event + * @param id the event id + * @param runnable the <code>Runnable</code> object to invoke + * @param notifier the object to notify, or null + * @param catchExceptions true to catch exceptions from the runnable + */ + protected InvocationEvent(Object source, int id, Runnable runnable, + Object notifier, boolean catchExceptions) + { + super(source, id); + this.runnable = runnable; + this.notifier = notifier; + this.catchExceptions = catchExceptions; + } + + /** + * This method calls the <code>run()</code> method of the runnable, traps + * exceptions if instructed to do so, and calls <code>notifyAll()</code> + * on any notifier if all worked successfully. + */ + public void dispatch() + { + if (catchExceptions) + try + { + runnable.run(); + } + catch (Exception e) + { + exception = e; + } + else + runnable.run(); + + Object o = notifier; + if (o != null) + synchronized(o) + { + o.notifyAll(); + } + } + + /** + * This method returns the exception that occurred during the execution of + * the runnable, or <code>null</code> if not exception was thrown or + * exceptions were not caught. + * + * @return the exception thrown by the runnable + */ + public Exception getException() + { + return exception; + } + + /** + * Gets the timestamp of when this event was created. + * + * @return the timestamp of this event + * @since 1.4 + */ + public long getWhen() + { + return when; + } + + /** + * This method returns a string identifying this event. This is formatted as: + * <code>"INVOCATION_DEFAULT,runnable=" + runnable + ",notifier=" + notifier + * + ",catchExceptions=" + catchExceptions + ",when=" + getWhen()</code>. + * + * @return a string identifying this event + */ + public String paramString() + { + return (id == INVOCATION_DEFAULT ? "INVOCATION_DEFAULT,runnable=" + : "unknown type,runnable=") + runnable + ",notifier=" + notifier + + ",catchExceptions=" + catchExceptions + ",when=" + when; + } +} // class InvocationEvent diff --git a/libjava/classpath/java/awt/event/ItemEvent.java b/libjava/classpath/java/awt/event/ItemEvent.java new file mode 100644 index 0000000..467815b --- /dev/null +++ b/libjava/classpath/java/awt/event/ItemEvent.java @@ -0,0 +1,155 @@ +/* ItemEvent.java -- event for item state changes + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.AWTEvent; +import java.awt.ItemSelectable; + +/** + * This event is generated when a selection item changes state. This is an + * abstraction that distills a large number of individual mouse or keyboard + * events into a simpler "item selected" and "item deselected" events. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ItemSelectable + * @see ItemListener + * @since 1.1 + * @status updated to 1.4 + */ +public class ItemEvent extends AWTEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -608708132447206933L; + + /** This is the first id in the event id range used by this class. */ + public static final int ITEM_FIRST = 701; + + /** This is the last id in the event id range used by this class. */ + public static final int ITEM_LAST = 701; + + /** This event id indicates a state change occurred. */ + public static final int ITEM_STATE_CHANGED = 701; + + /** This type indicates that the item was selected. */ + public static final int SELECTED = 1; + + /** This type indicates that the item was deselected. */ + public static final int DESELECTED = 2; + + /** + * The item affected by this event. + * + * @serial the item of the selection + */ + private final Object item; + + /** + * The state change direction, one of {@link #SELECTED} or + * {@link #DESELECTED}. + * + * @serial the selection state + */ + private final int stateChange; + + /** + * Initializes a new instance of <code>ItemEvent</code> with the specified + * source, id, and state change constant. Note that an invalid id leads to + * unspecified results. + * + * @param source the source of the event + * @param id the event id + * @param item the item affected by the state change + * @param stateChange one of {@link #SELECTED} or {@link #DESELECTED} + */ + public ItemEvent(ItemSelectable source, int id, Object item, int stateChange) + { + super(source, id); + this.item = item; + this.stateChange = stateChange; + } + + /** + * This method returns the event source as an <code>ItemSelectable</code>. + * + * @return the event source as an <code>ItemSelected</code> + * @throws ClassCastException if source is changed to a non-ItemSelectable + */ + public ItemSelectable getItemSelectable() + { + return (ItemSelectable) source; + } + + /** + * Returns the item affected by this state change. + * + * @return the item affected by this state change + */ + public Object getItem() + { + return item; + } + + /** + * Returns the type of state change, either {@link #SELECTED} or + * {@link #DESELECTED}. + * + * @return the type of state change + */ + public int getStateChange() + { + return stateChange; + } + + /** + * Returns a string identifying this event. This is in the format: + * <code>"ITEM_STATE_CHANGED,item=" + item + ",stateChange=" + * + (getStateChange() == DESELECTED ? "DESELECTED" : "SELECTED")</code>. + * + * @return a string identifying this event + */ + public String paramString() + { + return (id == ITEM_STATE_CHANGED ? "ITEM_STATE_CHANGED,item=" + : "unknown type,item=") + item + ",stateChange=" + + (stateChange == SELECTED ? "SELECTED" + : stateChange == DESELECTED ? "DESELECTED" : "unknown type"); + } +} // class ItemEvent diff --git a/libjava/classpath/java/awt/event/ItemListener.java b/libjava/classpath/java/awt/event/ItemListener.java new file mode 100644 index 0000000..fa5f3aa --- /dev/null +++ b/libjava/classpath/java/awt/event/ItemListener.java @@ -0,0 +1,62 @@ +/* ItemListener.java -- listen for item events + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.ItemSelectable; +import java.util.EventListener; + +/** + * This interface is for classes that wish to receive events when an + * item's selection state changes. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ItemSelectable + * @see ItemEvent + * @since 1.1 + * @status updated to 1.4 + */ +public interface ItemListener extends EventListener +{ + /** + * This method is called when an item's state is changed. + * + * @param event the <code>ItemEvent</code> indicating the change + */ + void itemStateChanged(ItemEvent event); +} // interface ItemListener diff --git a/libjava/classpath/java/awt/event/KeyAdapter.java b/libjava/classpath/java/awt/event/KeyAdapter.java new file mode 100644 index 0000000..c01d61f --- /dev/null +++ b/libjava/classpath/java/awt/event/KeyAdapter.java @@ -0,0 +1,88 @@ +/* KeyAdapter.java -- convenience class for writing key listeners + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +/** + * This class implements <code>KeyListener</code> and implements all methods + * with empty bodies. This allows a listener interested in implementing only + * a subset of the <code>KeyListener</code> interface to extend this class + * and override only the desired methods. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see KeyEvent + * @see KeyListener + * @since 1.1 + * @status updated to 1.4 + */ +public abstract class KeyAdapter implements KeyListener +{ + /** + * Do nothing default constructor for subclasses. + */ + public KeyAdapter() + { + } + + /** + * Implements this method in the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void keyTyped(KeyEvent event) + { + } + + /** + * Implements this method in the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void keyPressed(KeyEvent event) + { + } + + /** + * Implements this method in the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void keyReleased(KeyEvent event) + { + } +} // class KeyAdapter diff --git a/libjava/classpath/java/awt/event/KeyEvent.java b/libjava/classpath/java/awt/event/KeyEvent.java new file mode 100644 index 0000000..a40a8e1 --- /dev/null +++ b/libjava/classpath/java/awt/event/KeyEvent.java @@ -0,0 +1,1740 @@ +/* KeyEvent.java -- event for key presses + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import gnu.java.awt.EventModifier; + +import java.awt.Component; +import java.io.IOException; +import java.io.ObjectInputStream; + +/** + * This event is generated when a key is pressed or released. There are two + * categories of key events: + * + * <p><em>"Key typed" events</em> are higher-level, and have already + * compensated for modifiers and keyboard layout to generate a single Unicode + * character. It may take several key press events to generate one key typed. + * The <code>getKeyCode</code> method will return <code>VK_UNDEFINED</code>, + * and <code>getKeyChar</code> will return a valid Unicode character or + * <code>CHAR_UNDEFINED</code>. + * + * <p><em>"Key pressed" and "key released" events</em> are lower-level, and + * are platform and keyboard dependent. They correspond to the actaul motion + * on a keyboard, and return a virtual key code which labels the key that was + * pressed. The <code>getKeyCode</code> method will return one of the + * <code>VK_*</code> constants (except VK_UNDEFINED), and the + * <code>getKeyChar</code> method is undefined. + * + * <p>Some keys do not generate key typed events, such as the F1 or HELP keys. + * Not all keyboards can generate all virtual keys, and no attempt is made to + * simulate the ones that can't be typed. Virtual keys correspond to the + * keyboard layout, so for example, VK_Q in English is VK_A in French. Also, + * there are some additional virtual keys to ease handling of actions, such + * as VK_ALL_CANDIDATES in place of ALT+VK_CONVERT. Do not rely on the value + * of the VK_* constants, except for VK_ENTER, VK_BACK_SPACE, and VK_TAB. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @see KeyAdapter + * @see KeyListener + * @since 1.1 + * @status updated to 1.4 + */ +public class KeyEvent extends InputEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -2352130953028126954L; + + /** This is the first id in the range of event ids used by this class. */ + public static final int KEY_FIRST = 400; + + /** This is the last id in the range of event ids used by this class. */ + public static final int KEY_LAST = 402; + + /** + * This event id indicates a key was typed, which is a key press followed + * by a key release to generate an actual Unicode character. It may take + * several key presses to generate one key typed event, and some action + * keys have no corresponding key typed. + */ + public static final int KEY_TYPED = 400; + + /** This event id indicates a key was pressed. */ + public static final int KEY_PRESSED = 401; + + /** This event it indicates a key was released. */ + public static final int KEY_RELEASED = 402; + + /** The virtual key Enter, which will always map to '\n'. */ + public static final int VK_ENTER = '\n'; + + /** The virtual key Backspace, which will always map to '\b'. */ + public static final int VK_BACK_SPACE = '\b'; + + /** The virtual key Tab, which will always map to '\t'. */ + public static final int VK_TAB = '\t'; + + /** The virtual key Cancel. */ + public static final int VK_CANCEL = 3; + + /** The virtual key VK_CLEAR. */ + public static final int VK_CLEAR = 12; + + /** The virtual key VK_SHIFT. */ + public static final int VK_SHIFT = 16; + + /** The virtual key VK_CONTROL. */ + public static final int VK_CONTROL = 17; + + /** The virtual key VK_ALT. */ + public static final int VK_ALT = 18; + + /** The virtual key VK_PAUSE. */ + public static final int VK_PAUSE = 19; + + /** The virtual key VK_CAPS_LOCK. */ + public static final int VK_CAPS_LOCK = 20; + + /** The virtual key VK_ESCAPE. */ + public static final int VK_ESCAPE = 27; + + /** The virtual key VK_SPACE. */ + public static final int VK_SPACE = ' '; + + /** The virtual key VK_PAGE_UP. */ + public static final int VK_PAGE_UP = 33; + + /** The virtual key VK_PAGE_DOWN. */ + public static final int VK_PAGE_DOWN = 34; + + /** The virtual key VK_END. */ + public static final int VK_END = 35; + + /** The virtual key VK_HOME. */ + public static final int VK_HOME = 36; + + /** + * The virtual key for the non-numpad VK_LEFT. + * + * @see #VK_KP_LEFT + */ + public static final int VK_LEFT = 37; + + /** + * The virtual key for the non-numpad VK_UP. + * + * @see #VK_KP_UP + */ + public static final int VK_UP = 38; + + /** + * The virtual key for the non-numpad VK_RIGHT. + * + * @see #VK_KP_RIGHT + */ + public static final int VK_RIGHT = 39; + + /** + * The virtual key for the non-numpad VK_DOWN. + * + * @see #VK_KP_DOWN + */ + public static final int VK_DOWN = 40; + + /** The virtual key VK_COMMA. */ + public static final int VK_COMMA = ','; + + /** + * The virtual key VK_MINUS. + * + * @since 1.2 + */ + public static final int VK_MINUS = '-'; + + /** The virtual key VK_PERIOD. */ + public static final int VK_PERIOD = '.'; + + /** The virtual key VK_SLASH. */ + public static final int VK_SLASH = '/'; + + /** The virtual key VK_0. */ + public static final int VK_0 = '0'; + + /** The virtual key VK_1. */ + public static final int VK_1 = '1'; + + /** The virtual key VK_2. */ + public static final int VK_2 = '2'; + + /** The virtual key VK_3. */ + public static final int VK_3 = '3'; + + /** The virtual key VK_4. */ + public static final int VK_4 = '4'; + + /** The virtual key VK_5. */ + public static final int VK_5 = '5'; + + /** The virtual key VK_6. */ + public static final int VK_6 = '6'; + + /** The virtual key VK_7. */ + public static final int VK_7 = '7'; + + /** The virtual key VK_8. */ + public static final int VK_8 = '8'; + + /** The virtual key VK_9. */ + public static final int VK_9 = '9'; + + /** The virtual key VK_SEMICOLON. */ + public static final int VK_SEMICOLON = ';'; + + /** The virtual key VK_EQUALS. */ + public static final int VK_EQUALS = '='; + + /** The virtual key VK_A. */ + public static final int VK_A = 'A'; + + /** The virtual key VK_B. */ + public static final int VK_B = 'B'; + + /** The virtual key VK_C. */ + public static final int VK_C = 'C'; + + /** The virtual key VK_D. */ + public static final int VK_D = 'D'; + + /** The virtual key VK_E. */ + public static final int VK_E = 'E'; + + /** The virtual key VK_F. */ + public static final int VK_F = 'F'; + + /** The virtual key VK_G. */ + public static final int VK_G = 'G'; + + /** The virtual key VK_H. */ + public static final int VK_H = 'H'; + + /** The virtual key VK_I. */ + public static final int VK_I = 'I'; + + /** The virtual key VK_J. */ + public static final int VK_J = 'J'; + + /** The virtual key VK_K. */ + public static final int VK_K = 'K'; + + /** The virtual key VK_L. */ + public static final int VK_L = 'L'; + + /** The virtual key VK_M. */ + public static final int VK_M = 'M'; + + /** The virtual key VK_N. */ + public static final int VK_N = 'N'; + + /** The virtual key VK_O. */ + public static final int VK_O = 'O'; + + /** The virtual key VK_P. */ + public static final int VK_P = 'P'; + + /** The virtual key VK_Q. */ + public static final int VK_Q = 'Q'; + + /** The virtual key VK_R. */ + public static final int VK_R = 'R'; + + /** The virtual key VK_S. */ + public static final int VK_S = 'S'; + + /** The virtual key VK_T. */ + public static final int VK_T = 'T'; + + /** The virtual key VK_U. */ + public static final int VK_U = 'U'; + + /** The virtual key VK_V. */ + public static final int VK_V = 'V'; + + /** The virtual key VK_W. */ + public static final int VK_W = 'W'; + + /** The virtual key VK_X. */ + public static final int VK_X = 'X'; + + /** The virtual key VK_Y. */ + public static final int VK_Y = 'Y'; + + /** The virtual key VK_Z. */ + public static final int VK_Z = 'Z'; + + /** The virtual key VK_OPEN_BRACKET. */ + public static final int VK_OPEN_BRACKET = '['; + + /** The virtual key VK_BACK_SLASH. */ + public static final int VK_BACK_SLASH = '\\'; + + /** The virtual key VK_CLOSE_BRACKET. */ + public static final int VK_CLOSE_BRACKET = ']'; + + /** The virtual key VK_NUMPAD0. */ + public static final int VK_NUMPAD0 = 96; + + /** The virtual key VK_NUMPAD1. */ + public static final int VK_NUMPAD1 = 97; + + /** The virtual key VK_NUMPAD2. */ + public static final int VK_NUMPAD2 = 98; + + /** The virtual key VK_NUMPAD3. */ + public static final int VK_NUMPAD3 = 99; + + /** The virtual key VK_NUMPAD4. */ + public static final int VK_NUMPAD4 = 100; + + /** The virtual key VK_NUMPAD5. */ + public static final int VK_NUMPAD5 = 101; + + /** The virtual key VK_NUMPAD6. */ + public static final int VK_NUMPAD6 = 102; + + /** The virtual key VK_NUMPAD7. */ + public static final int VK_NUMPAD7 = 103; + + /** The virtual key VK_NUMPAD8. */ + public static final int VK_NUMPAD8 = 104; + + /** The virtual key VK_NUMPAD9. */ + public static final int VK_NUMPAD9 = 105; + + /** The virtual key VK_MULTIPLY. */ + public static final int VK_MULTIPLY = 106; + + /** The virtual key VK_ADD. */ + public static final int VK_ADD = 107; + + /** + * The virtual key VK_SEPARATOR, handily mispelled for those who can't + * figure it out. + * + * @deprecated use {@link #VK_SEPARATOR} + */ + public static final int VK_SEPARATER = 108; + + /** + * The virtual key VK_SEPARATOR. + * + * @since 1.4 + */ + public static final int VK_SEPARATOR = 108; + + /** The virtual key VK_SUBTRACT. */ + public static final int VK_SUBTRACT = 109; + + /** The virtual key VK_DECIMAL. */ + public static final int VK_DECIMAL = 110; + + /** The virtual key VK_DIVIDE. */ + public static final int VK_DIVIDE = 111; + + /** The virtual key VK_DELETE. */ + public static final int VK_DELETE = 127; + + /** The virtual key VK_NUM_LOCK. */ + public static final int VK_NUM_LOCK = 144; + + /** The virtual key VK_SCROLL_LOCK. */ + public static final int VK_SCROLL_LOCK = 145; + + /** The virtual key VK_F1. */ + public static final int VK_F1 = 112; + + /** The virtual key VK_F2. */ + public static final int VK_F2 = 113; + + /** The virtual key VK_F3. */ + public static final int VK_F3 = 114; + + /** The virtual key VK_F4. */ + public static final int VK_F4 = 115; + + /** The virtual key VK_F5. */ + public static final int VK_F5 = 116; + + /** The virtual key VK_F6. */ + public static final int VK_F6 = 117; + + /** The virtual key VK_F7. */ + public static final int VK_F7 = 118; + + /** The virtual key VK_F8. */ + public static final int VK_F8 = 119; + + /** The virtual key VK_F9. */ + public static final int VK_F9 = 120; + + /** The virtual key VK_F10. */ + public static final int VK_F10 = 121; + + /** The virtual key VK_F11. */ + public static final int VK_F11 = 122; + + /** The virtual key VK_F12. */ + public static final int VK_F12 = 123; + + /** + * The virtual key VK_F13. + * + * @since 1.2 + */ + public static final int VK_F13 = 61440; + + /** + * The virtual key VK_F14. + * + * @since 1.2 + */ + public static final int VK_F14 = 61441; + + /** + * The virtual key VK_F15. + * + * @since 1.2 + */ + public static final int VK_F15 = 61442; + + /** + * The virtual key VK_F16. + * + * @since 1.2 + */ + public static final int VK_F16 = 61443; + + /** + * The virtual key VK_F17. + * + * @since 1.2 + */ + public static final int VK_F17 = 61444; + + /** + * The virtual key VK_F18. + * + * @since 1.2 + */ + public static final int VK_F18 = 61445; + + /** + * The virtual key VK_F19. + * + * @since 1.2 + */ + public static final int VK_F19 = 61446; + + /** + * The virtual key VK_F20. + * + * @since 1.2 + */ + public static final int VK_F20 = 61447; + + /** + * The virtual key VK_F21. + * + * @since 1.2 + */ + public static final int VK_F21 = 61448; + + /** + * The virtual key VK_F22. + * + * @since 1.2 + */ + public static final int VK_F22 = 61449; + + /** + * The virtual key VK_F23. + * + * @since 1.2 + */ + public static final int VK_F23 = 61450; + + /** + * The virtual key VK_F24. + * + * @since 1.2 + */ + public static final int VK_F24 = 61451; + + /** The virtual key VK_PRINTSCREEN. */ + public static final int VK_PRINTSCREEN = 154; + + /** The virtual key VK_INSERT. */ + public static final int VK_INSERT = 155; + + /** The virtual key VK_HELP. */ + public static final int VK_HELP = 156; + + /** The virtual key VK_META. */ + public static final int VK_META = 157; + + /** The virtual key VK_BACK_QUOTE. */ + public static final int VK_BACK_QUOTE = 192; + + /** The virtual key VK_QUOTE. */ + public static final int VK_QUOTE = 222; + + /** + * The virtual key for the numpad VK_KP_UP. + * + * @see #VK_UP + * @since 1.2 + */ + public static final int VK_KP_UP = 224; + + /** + * The virtual key for the numpad VK_KP_DOWN. + * + * @see #VK_DOWN + * @since 1.2 + */ + public static final int VK_KP_DOWN = 225; + + /** + * The virtual key for the numpad VK_KP_LEFT. + * + * @see #VK_LEFT + * @since 1.2 + */ + public static final int VK_KP_LEFT = 226; + + /** + * The virtual key for the numpad VK_KP_RIGHT. + * + * @see #VK_RIGHT + * @since 1.2 + */ + public static final int VK_KP_RIGHT = 227; + + /** + * The virtual key VK_DEAD_GRAVE. + * + * @since 1.2 + */ + public static final int VK_DEAD_GRAVE = 128; + + /** + * The virtual key VK_DEAD_ACUTE. + * + * @since 1.2 + */ + public static final int VK_DEAD_ACUTE = 129; + + /** + * The virtual key VK_DEAD_CIRCUMFLEX. + * + * @since 1.2 + */ + public static final int VK_DEAD_CIRCUMFLEX = 130; + + /** + * The virtual key VK_DEAD_TILDE. + * + * @since 1.2 + */ + public static final int VK_DEAD_TILDE = 131; + + /** + * The virtual key VK_DEAD_MACRON. + * + * @since 1.2 + */ + public static final int VK_DEAD_MACRON = 132; + + /** + * The virtual key VK_DEAD_BREVE. + * + * @since 1.2 + */ + public static final int VK_DEAD_BREVE = 133; + + /** + * The virtual key VK_DEAD_ABOVEDOT. + * + * @since 1.2 + */ + public static final int VK_DEAD_ABOVEDOT = 134; + + /** + * The virtual key VK_DEAD_DIAERESIS. + * + * @since 1.2 + */ + public static final int VK_DEAD_DIAERESIS = 135; + + /** + * The virtual key VK_DEAD_ABOVERING. + * + * @since 1.2 + */ + public static final int VK_DEAD_ABOVERING = 136; + + /** + * The virtual key VK_DEAD_DOUBLEACUTE. + * + * @since 1.2 + */ + public static final int VK_DEAD_DOUBLEACUTE = 137; + + /** + * The virtual key VK_DEAD_CARON. + * + * @since 1.2 + */ + public static final int VK_DEAD_CARON = 138; + + /** + * The virtual key VK_DEAD_CEDILLA. + * + * @since 1.2 + */ + public static final int VK_DEAD_CEDILLA = 139; + + /** + * The virtual key VK_DEAD_OGONEK. + * + * @since 1.2 + */ + public static final int VK_DEAD_OGONEK = 140; + + /** + * The virtual key VK_DEAD_IOTA. + * + * @since 1.2 + */ + public static final int VK_DEAD_IOTA = 141; + + /** + * The virtual key VK_DEAD_VOICED_SOUND. + * + * @since 1.2 + */ + public static final int VK_DEAD_VOICED_SOUND = 142; + + /** + * The virtual key VK_DEAD_SEMIVOICED_SOUND. + * + * @since 1.2 + */ + public static final int VK_DEAD_SEMIVOICED_SOUND = 143; + + /** + * The virtual key VK_AMPERSAND. + * + * @since 1.2 + */ + public static final int VK_AMPERSAND = 150; + + /** + * The virtual key VK_ASTERISK. + * + * @since 1.2 + */ + public static final int VK_ASTERISK = 151; + + /** + * The virtual key VK_QUOTEDBL. + * + * @since 1.2 + */ + public static final int VK_QUOTEDBL = 152; + + /** + * The virtual key VK_LESS. + * + * @since 1.2 + */ + public static final int VK_LESS = 153; + + /** + * The virtual key VK_GREATER. + * + * @since 1.2 + */ + public static final int VK_GREATER = 160; + + /** + * The virtual key VK_BRACELEFT. + * + * @since 1.2 + */ + public static final int VK_BRACELEFT = 161; + + /** + * The virtual key VK_BRACERIGHT. + * + * @since 1.2 + */ + public static final int VK_BRACERIGHT = 162; + + /** + * The virtual key VK_AT. + * + * @since 1.2 + */ + public static final int VK_AT = 512; + + /** + * The virtual key VK_COLON. + * + * @since 1.2 + */ + public static final int VK_COLON = 513; + + /** + * The virtual key VK_CIRCUMFLEX. + * + * @since 1.2 + */ + public static final int VK_CIRCUMFLEX = 514; + + /** + * The virtual key VK_DOLLAR. + * + * @since 1.2 + */ + public static final int VK_DOLLAR = 515; + + /** + * The virtual key VK_EURO_SIGN. + * + * @since 1.2 + */ + public static final int VK_EURO_SIGN = 516; + + /** + * The virtual key VK_EXCLAMATION_MARK. + * + * @since 1.2 + */ + public static final int VK_EXCLAMATION_MARK = 517; + + /** + * The virtual key VK_INVERTED_EXCLAMATION_MARK. + * + * @since 1.2 + */ + public static final int VK_INVERTED_EXCLAMATION_MARK = 518; + + /** + * The virtual key VK_LEFT_PARENTHESIS. + * + * @since 1.2 + */ + public static final int VK_LEFT_PARENTHESIS = 519; + + /** + * The virtual key VK_NUMBER_SIGN. + * + * @since 1.2 + */ + public static final int VK_NUMBER_SIGN = 520; + + /** + * The virtual key VK_PLUS. + * + * @since 1.2 + */ + public static final int VK_PLUS = 521; + + /** + * The virtual key VK_RIGHT_PARENTHESIS. + * + * @since 1.2 + */ + public static final int VK_RIGHT_PARENTHESIS = 522; + + /** + * The virtual key VK_UNDERSCORE. + * + * @since 1.2 + */ + public static final int VK_UNDERSCORE = 523; + + /** The virtual key VK_FINAL. */ + public static final int VK_FINAL = 24; + + /** The virtual key VK_CONVERT. */ + public static final int VK_CONVERT = 28; + + /** The virtual key VK_NONCONVERT. */ + public static final int VK_NONCONVERT = 29; + + /** The virtual key VK_ACCEPT. */ + public static final int VK_ACCEPT = 30; + + /** The virtual key VK_MODECHANGE. */ + public static final int VK_MODECHANGE = 31; + + /** The virtual key VK_KANA. */ + public static final int VK_KANA = 21; + + /** The virtual key VK_KANJI. */ + public static final int VK_KANJI = 25; + + /** + * The virtual key VK_ALPHANUMERIC. + * + * @since 1.2 + */ + public static final int VK_ALPHANUMERIC = 240; + + /** + * The virtual key VK_KATAKANA. + * + * @since 1.2 + */ + public static final int VK_KATAKANA = 241; + + /** + * The virtual key VK_HIRAGANA. + * + * @since 1.2 + */ + public static final int VK_HIRAGANA = 242; + + /** + * The virtual key VK_FULL_WIDTH. + * + * @since 1.2 + */ + public static final int VK_FULL_WIDTH = 243; + + /** + * The virtual key VK_HALF_WIDTH. + * + * @since 1.2 + */ + public static final int VK_HALF_WIDTH = 244; + + /** + * The virtual key VK_ROMAN_CHARACTERS. + * + * @since 1.2 + */ + public static final int VK_ROMAN_CHARACTERS = 245; + + /** + * The virtual key VK_ALL_CANDIDATES. + * + * @since 1.2 + */ + public static final int VK_ALL_CANDIDATES = 256; + + /** + * The virtual key VK_PREVIOUS_CANDIDATE. + * + * @since 1.2 + */ + public static final int VK_PREVIOUS_CANDIDATE = 257; + + /** + * The virtual key VK_CODE_INPUT. + * + * @since 1.2 + */ + public static final int VK_CODE_INPUT = 258; + + /** + * The virtual key VK_JAPANESE_KATAKANA. + * + * @since 1.2 + */ + public static final int VK_JAPANESE_KATAKANA = 259; + + /** + * The virtual key VK_JAPANESE_HIRAGANA. + * + * @since 1.2 + */ + public static final int VK_JAPANESE_HIRAGANA = 260; + + /** + * The virtual key VK_JAPANESE_ROMAN. + * + * @since 1.2 + */ + public static final int VK_JAPANESE_ROMAN = 261; + + /** + * The virtual key VK_KANA_LOCK. + * + * @since 1.3 + */ + public static final int VK_KANA_LOCK = 262; + + /** + * The virtual key VK_INPUT_METHOD_ON_OFF. + * + * @since 1.3 + */ + public static final int VK_INPUT_METHOD_ON_OFF = 263; + + /** + * The virtual key VK_CUT. + * + * @since 1.2 + */ + public static final int VK_CUT = 65489; + + /** + * The virtual key VK_COPY. + * + * @since 1.2 + */ + public static final int VK_COPY = 65485; + + /** + * The virtual key VK_PASTE. + * + * @since 1.2 + */ + public static final int VK_PASTE = 65487; + + /** + * The virtual key VK_UNDO. + * + * @since 1.2 + */ + public static final int VK_UNDO = 65483; + + /** + * The virtual key VK_AGAIN. + * + * @since 1.2 + */ + public static final int VK_AGAIN = 65481; + + /** + * The virtual key VK_FIND. + * + * @since 1.2 + */ + public static final int VK_FIND = 65488; + + /** + * The virtual key VK_PROPS. + * + * @since 1.2 + */ + public static final int VK_PROPS = 65482; + + /** + * The virtual key VK_STOP. + * + * @since 1.2 + */ + public static final int VK_STOP = 65480; + + /** + * The virtual key VK_COMPOSE. + * + * @since 1.2 + */ + public static final int VK_COMPOSE = 65312; + + /** + * The virtual key VK_ALT_GRAPH. + * + * @since 1.2 + */ + public static final int VK_ALT_GRAPH = 65406; + + /** + * The virtual key VK_UNDEFINED. This is used for key typed events, which + * do not have a virtual key. + */ + public static final int VK_UNDEFINED = 0; + + /** + * The only char with no valid Unicode interpretation. This is used for + * key pressed and key released events which do not have a valid keyChar. + */ + public static final char CHAR_UNDEFINED = '\uffff'; + + /** + * Indicates unknown or irrelavent key location. This is also used for + * key typed events, which do not need a location. + * + * @since 1.4 + */ + public static final int KEY_LOCATION_UNKNOWN = 0; + + /** + * Indicates a standard key location, with no left/right variants and not + * on the numeric pad. + * + * @since 1.4 + */ + public static final int KEY_LOCATION_STANDARD = 1; + + /** + * Indicates the key is on the left side of the keyboard, such as the left + * shift. + * + * @since 1.4 + */ + public static final int KEY_LOCATION_LEFT = 2; + + /** + * Indicates the key is on the right side of the keyboard, such as the right + * shift. + * + * @since 1.4 + */ + public static final int KEY_LOCATION_RIGHT = 3; + + /** + * Indicates the key is on the numeric pad, such as the numpad 0. + * + * @since 1.4 + */ + public static final int KEY_LOCATION_NUMPAD = 4; + + /** + * The code assigned to the physical keyboard location (as adjusted by the + * keyboard layout). Use the symbolic VK_* names instead of numbers. + * + * @see #getKeyCode() + * @serial the VK_ code for this key + */ + private int keyCode; + + /** + * The Unicode character produced by the key type event. This has no meaning + * for key pressed and key released events. + * + * @see #getKeyChar() + * @serial the Unicode value for this key + */ + private char keyChar; + + /** + * The keyboard location of the key. One of {@link #KEY_LOCATION_UNKNOWN}, + * {@link #KEY_LOCATION_STANDARD}, {@link #KEY_LOCATION_LEFT}, + * {@link #KEY_LOCATION_RIGHT}, or {@link #KEY_LOCATION_NUMPAD}. + * + * @see #getKeyLocation() + * @serial the key location + * @since 1.4 + */ + private final int keyLocation; + + /** + * Stores the state of the native event dispatching system, to correctly + * dispatch in Component#dispatchEventImpl when a proxy is active. + * + * XXX Does this matter in Classpath? + * + * @serial whether the proxy is active + */ + private boolean isProxyActive; + + + /** + * Initializes a new instance of <code>KeyEvent</code> with the specified + * information. Note that an invalid id leads to unspecified results. + * + * @param source the component that generated this event + * @param id the event id + * @param when the timestamp when the even occurred + * @param modifiers the modifier keys during the event, in old or new style + * @param keyCode the integer constant for the virtual key type + * @param keyChar the Unicode value of the key + * @param keyLocation the location of the key + * @throws IllegalArgumentException if source is null, if keyLocation is + * invalid, or if (id == KEY_TYPED && (keyCode != VK_UNDEFINED + * || keyChar == CHAR_UNDEFINED)) + */ + public KeyEvent(Component source, int id, long when, int modifiers, + int keyCode, char keyChar, int keyLocation) + { + super(source, id, when, modifiers); + this.keyCode = keyCode; + this.keyChar = keyChar; + this.keyLocation = keyLocation; + if ((id == KEY_TYPED && (keyCode != VK_UNDEFINED + || keyChar == CHAR_UNDEFINED)) + || keyLocation < KEY_LOCATION_UNKNOWN + || keyLocation > KEY_LOCATION_NUMPAD) + throw new IllegalArgumentException(); + } + + /** + * Initializes a new instance of <code>KeyEvent</code> with the specified + * information. Note that an invalid id leads to unspecified results. + * + * @param source the component that generated this event + * @param id the event id + * @param when the timestamp when the even occurred + * @param modifiers the modifier keys during the event, in old or new style + * @param keyCode the integer constant for the virtual key type + * @param keyChar the Unicode value of the key + * @throws IllegalArgumentException if source is null, or if + * (id == KEY_TYPED && (keyCode != VK_UNDEFINED + * || keyChar == CHAR_UNDEFINED)) + */ + public KeyEvent(Component source, int id, long when, int modifiers, + int keyCode, char keyChar) + { + this(source, id, when, modifiers, keyCode, keyChar, KEY_LOCATION_UNKNOWN); + } + + /** + * Initializes a new instance of <code>KeyEvent</code> with the specified + * information. Note that an invalid id leads to unspecified results. + * + * @param source the component that generated this event + * @param id the event id + * @param when the timestamp when the even occurred + * @param modifiers the modifier keys during the event, in old or new style + * @param keyCode the integer constant for the virtual key type + * @throws IllegalArgumentException if source is null, or if + * id == KEY_TYPED but keyCode != VK_UNDEFINED + * + * @deprecated + */ + public KeyEvent(Component source, int id, long when, int modifiers, + int keyCode) + { + this(source, id, when, modifiers, keyCode, '\0', KEY_LOCATION_UNKNOWN); + } + + /** + * Returns the key code for the event key. This will be one of the + * <code>VK_*</code> constants defined in this class. If the event type is + * KEY_TYPED, the result will be VK_UNDEFINED. + * + * @return the key code for this event + */ + public int getKeyCode() + { + return keyCode; + } + + /** + * Sets the key code for this event. This must be one of the + * <code>VK_*</code> constants defined in this class. + * + * @param keyCode the new key code for this event + */ + public void setKeyCode(int keyCode) + { + this.keyCode = keyCode; + } + + /** + * Returns the Unicode value for the event key. This will be + * <code>CHAR_UNDEFINED</code> if there is no Unicode equivalent for + * this key, usually when this is a KEY_PRESSED or KEY_RELEASED event. + * + * @return the Unicode character for this event + */ + public char getKeyChar() + { + return keyChar; + } + + /** + * Sets the Unicode character for this event to the specified value. + * + * @param keyChar the new Unicode character for this event + */ + public void setKeyChar(char keyChar) + { + this.keyChar = keyChar; + } + + /** + * Sets the modifier keys to the specified value. This should be a union + * of the bit mask constants from <code>InputEvent</code>. The use of this + * method is not recommended, particularly for KEY_TYPED events, which do + * not check if the modifiers were changed. + * + * @param modifiers the new modifier value, in either old or new style + * @see InputEvent + * + * @deprecated + */ + public void setModifiers(int modifiers) + { + this.modifiers = EventModifier.extend(modifiers); + } + + /** + * Returns the keyboard location of the key that generated this event. This + * provides a way to distinguish between keys like left and right shift + * which share a common key code. The result will be one of + * {@link #KEY_LOCATION_UNKNOWN}, {@link #KEY_LOCATION_STANDARD}, + * {@link #KEY_LOCATION_LEFT}, {@link #KEY_LOCATION_RIGHT}, or + * {@link #KEY_LOCATION_NUMPAD}. + * + * @return the key location + * @since 1.4 + */ + public int getKeyLocation() + { + return keyLocation; + } + + /** + * Returns the text name of key code, such as "HOME", "F1", or "A". + * + * XXX Sun claims this can be localized via the awt.properties file - how + * do we implement that? + * + * @return the text name of the key code + */ + public static String getKeyText(int keyCode) + { + switch (keyCode) + { + case VK_CANCEL: + return "Cancel"; + case VK_BACK_SPACE: + return "Backspace"; + case VK_TAB: + return "Tab"; + case VK_ENTER: + return "Enter"; + case VK_CLEAR: + return "Clear"; + case VK_SHIFT: + return "Shift"; + case VK_CONTROL: + return "Ctrl"; + case VK_ALT: + return "Alt"; + case VK_PAUSE: + return "Pause"; + case VK_CAPS_LOCK: + return "Caps Lock"; + case VK_KANA: + return "Kana"; + case VK_FINAL: + return "Final"; + case VK_KANJI: + return "Kanji"; + case VK_ESCAPE: + return "Escape"; + case VK_CONVERT: + return "Convert"; + case VK_NONCONVERT: + return "No Convert"; + case VK_ACCEPT: + return "Accept"; + case VK_MODECHANGE: + return "Mode Change"; + case VK_SPACE: + return "Space"; + case VK_PAGE_UP: + return "Page Up"; + case VK_PAGE_DOWN: + return "Page Down"; + case VK_END: + return "End"; + case VK_HOME: + return "Home"; + case VK_LEFT: + case VK_KP_LEFT: + return "Left"; + case VK_UP: + case VK_KP_UP: + return "Up"; + case VK_RIGHT: + case VK_KP_RIGHT: + return "Right"; + case VK_DOWN: + case VK_KP_DOWN: + return "Down"; + case VK_MINUS: + return "Minus"; + case VK_MULTIPLY: + return "NumPad *"; + case VK_ADD: + return "NumPad +"; + case VK_SEPARATOR: + return "NumPad ,"; + case VK_SUBTRACT: + return "NumPad -"; + case VK_DECIMAL: + return "NumPad ."; + case VK_DIVIDE: + return "NumPad /"; + case VK_DELETE: + return "Delete"; + case VK_DEAD_GRAVE: + return "Dead Grave"; + case VK_DEAD_ACUTE: + return "Dead Acute"; + case VK_DEAD_CIRCUMFLEX: + return "Dead Circumflex"; + case VK_DEAD_TILDE: + return "Dead Tilde"; + case VK_DEAD_MACRON: + return "Dead Macron"; + case VK_DEAD_BREVE: + return "Dead Breve"; + case VK_DEAD_ABOVEDOT: + return "Dead Above Dot"; + case VK_DEAD_DIAERESIS: + return "Dead Diaeresis"; + case VK_DEAD_ABOVERING: + return "Dead Above Ring"; + case VK_DEAD_DOUBLEACUTE: + return "Dead Double Acute"; + case VK_DEAD_CARON: + return "Dead Caron"; + case VK_DEAD_CEDILLA: + return "Dead Cedilla"; + case VK_DEAD_OGONEK: + return "Dead Ogonek"; + case VK_DEAD_IOTA: + return "Dead Iota"; + case VK_DEAD_VOICED_SOUND: + return "Dead Voiced Sound"; + case VK_DEAD_SEMIVOICED_SOUND: + return "Dead Semivoiced Sound"; + case VK_NUM_LOCK: + return "Num Lock"; + case VK_SCROLL_LOCK: + return "Scroll Lock"; + case VK_AMPERSAND: + return "Ampersand"; + case VK_ASTERISK: + return "Asterisk"; + case VK_QUOTEDBL: + return "Double Quote"; + case VK_LESS: + return "Less"; + case VK_PRINTSCREEN: + return "Print Screen"; + case VK_INSERT: + return "Insert"; + case VK_HELP: + return "Help"; + case VK_META: + return "Meta"; + case VK_GREATER: + return "Greater"; + case VK_BRACELEFT: + return "Left Brace"; + case VK_BRACERIGHT: + return "Right Brace"; + case VK_BACK_QUOTE: + return "Back Quote"; + case VK_QUOTE: + return "Quote"; + case VK_ALPHANUMERIC: + return "Alphanumeric"; + case VK_KATAKANA: + return "Katakana"; + case VK_HIRAGANA: + return "Hiragana"; + case VK_FULL_WIDTH: + return "Full-Width"; + case VK_HALF_WIDTH: + return "Half-Width"; + case VK_ROMAN_CHARACTERS: + return "Roman Characters"; + case VK_ALL_CANDIDATES: + return "All Candidates"; + case VK_PREVIOUS_CANDIDATE: + return "Previous Candidate"; + case VK_CODE_INPUT: + return "Code Input"; + case VK_JAPANESE_KATAKANA: + return "Japanese Katakana"; + case VK_JAPANESE_HIRAGANA: + return "Japanese Hiragana"; + case VK_JAPANESE_ROMAN: + return "Japanese Roman"; + case VK_KANA_LOCK: + return "Kana Lock"; + case VK_INPUT_METHOD_ON_OFF: + return "Input Method On/Off"; + case VK_AT: + return "At"; + case VK_COLON: + return "Colon"; + case VK_CIRCUMFLEX: + return "Circumflex"; + case VK_DOLLAR: + return "Dollar"; + case VK_EURO_SIGN: + return "Euro"; + case VK_EXCLAMATION_MARK: + return "Exclamation Mark"; + case VK_INVERTED_EXCLAMATION_MARK: + return "Inverted Exclamation Mark"; + case VK_LEFT_PARENTHESIS: + return "Left Parenthesis"; + case VK_NUMBER_SIGN: + return "Number Sign"; + case VK_PLUS: + return "Plus"; + case VK_RIGHT_PARENTHESIS: + return "Right Parenthesis"; + case VK_UNDERSCORE: + return "Underscore"; + case VK_COMPOSE: + return "Compose"; + case VK_ALT_GRAPH: + return "Alt Graph"; + case VK_STOP: + return "Stop"; + case VK_AGAIN: + return "Again"; + case VK_PROPS: + return "Props"; + case VK_UNDO: + return "Undo"; + case VK_COPY: + return "Copy"; + case VK_PASTE: + return "Paste"; + case VK_FIND: + return "Find"; + case VK_CUT: + return "Cut"; + case VK_COMMA: + case VK_PERIOD: + case VK_SLASH: + case VK_0: + case VK_1: + case VK_2: + case VK_3: + case VK_4: + case VK_5: + case VK_6: + case VK_7: + case VK_8: + case VK_9: + case VK_SEMICOLON: + case VK_EQUALS: + case VK_A: + case VK_B: + case VK_C: + case VK_D: + case VK_E: + case VK_F: + case VK_G: + case VK_H: + case VK_I: + case VK_J: + case VK_K: + case VK_L: + case VK_M: + case VK_N: + case VK_O: + case VK_P: + case VK_Q: + case VK_R: + case VK_S: + case VK_T: + case VK_U: + case VK_V: + case VK_W: + case VK_X: + case VK_Y: + case VK_Z: + case VK_OPEN_BRACKET: + case VK_BACK_SLASH: + case VK_CLOSE_BRACKET: + return "" + (char) keyCode; + case VK_NUMPAD0: + case VK_NUMPAD1: + case VK_NUMPAD2: + case VK_NUMPAD3: + case VK_NUMPAD4: + case VK_NUMPAD5: + case VK_NUMPAD6: + case VK_NUMPAD7: + case VK_NUMPAD8: + case VK_NUMPAD9: + return "NumPad-" + (keyCode - VK_NUMPAD0); + case VK_F1: + case VK_F2: + case VK_F3: + case VK_F4: + case VK_F5: + case VK_F6: + case VK_F7: + case VK_F8: + case VK_F9: + case VK_F10: + case VK_F11: + case VK_F12: + return "F" + (keyCode - (VK_F1 - 1)); + case VK_F13: + case VK_F14: + case VK_F15: + case VK_F16: + case VK_F17: + case VK_F18: + case VK_F19: + case VK_F20: + case VK_F21: + case VK_F22: + case VK_F23: + case VK_F24: + return "F" + (keyCode - (VK_F13 - 13)); + default: + // This is funky on negative numbers, but that's Sun's fault. + return "Unknown keyCode: 0x" + (keyCode < 0 ? "-" : "") + + Integer.toHexString(Math.abs(keyCode)); + } + } + + /** + * Returns a string describing the modifiers, such as "Shift" or + * "Ctrl+Button1". + * + * XXX Sun claims this can be localized via the awt.properties file - how + * do we implement that? + * + * @param modifiers the old-style modifiers to convert to text + * @return a string representation of the modifiers in this bitmask + */ + public static String getKeyModifiersText(int modifiers) + { + return getModifiersExText(EventModifier.extend(modifiers + & EventModifier.OLD_MASK)); + } + + /** + * Tests whether or not this key is an action key. An action key typically + * does not fire a KEY_TYPED event, and is not a modifier. + * + * @return true if this is an action key + */ + public boolean isActionKey() + { + switch (keyCode) + { + case VK_PAUSE: + case VK_CAPS_LOCK: + case VK_KANA: + case VK_FINAL: + case VK_KANJI: + case VK_CONVERT: + case VK_NONCONVERT: + case VK_ACCEPT: + case VK_MODECHANGE: + case VK_PAGE_UP: + case VK_PAGE_DOWN: + case VK_END: + case VK_HOME: + case VK_LEFT: + case VK_UP: + case VK_RIGHT: + case VK_DOWN: + case VK_F1: + case VK_F2: + case VK_F3: + case VK_F4: + case VK_F5: + case VK_F6: + case VK_F7: + case VK_F8: + case VK_F9: + case VK_F10: + case VK_F11: + case VK_F12: + case VK_NUM_LOCK: + case VK_SCROLL_LOCK: + case VK_PRINTSCREEN: + case VK_INSERT: + case VK_HELP: + case VK_KP_UP: + case VK_KP_DOWN: + case VK_KP_LEFT: + case VK_KP_RIGHT: + case VK_ALPHANUMERIC: + case VK_KATAKANA: + case VK_HIRAGANA: + case VK_FULL_WIDTH: + case VK_HALF_WIDTH: + case VK_ROMAN_CHARACTERS: + case VK_ALL_CANDIDATES: + case VK_PREVIOUS_CANDIDATE: + case VK_CODE_INPUT: + case VK_JAPANESE_KATAKANA: + case VK_JAPANESE_HIRAGANA: + case VK_JAPANESE_ROMAN: + case VK_KANA_LOCK: + case VK_INPUT_METHOD_ON_OFF: + case VK_F13: + case VK_F14: + case VK_F15: + case VK_F16: + case VK_F17: + case VK_F18: + case VK_F19: + case VK_F20: + case VK_F21: + case VK_F22: + case VK_F23: + case VK_F24: + case VK_STOP: + case VK_AGAIN: + case VK_PROPS: + case VK_UNDO: + case VK_COPY: + case VK_PASTE: + case VK_FIND: + case VK_CUT: + return true; + default: + return false; + } + } + + /** + * Returns a string identifying the event. This is formatted as the + * field name of the id type, followed by the keyCode, then the + * keyChar, modifiers (if any), extModifiers (if any), and + * keyLocation. + * + * @return a string identifying the event + */ + public String paramString() + { + StringBuffer s = new StringBuffer(); + + switch (id) + { + case KEY_PRESSED: + s.append("KEY_PRESSED"); + break; + case KEY_RELEASED: + s.append("KEY_RELEASED"); + break; + case KEY_TYPED: + s.append("KEY_TYPED"); + break; + default: + s.append("unknown type"); + } + + s.append(",keyCode=").append(keyCode); + + s.append(",keyText=").append(getKeyText(keyCode)); + + s.append(",keyChar="); + if (isActionKey() + || keyCode == VK_SHIFT + || keyCode == VK_CONTROL + || keyCode == VK_ALT) + s.append("Undefined keyChar"); + else + { + /* This output string must be selected by examining keyChar + * rather than keyCode, because key code information is not + * included in KEY_TYPED events. + */ + if (keyChar == VK_BACK_SPACE + || keyChar == VK_TAB + || keyChar == VK_ENTER + || keyChar == VK_ESCAPE + || keyChar == VK_DELETE) + s.append(getKeyText(keyChar)); + else + s.append("'").append(keyChar).append("'"); + } + + if ((modifiers & CONVERT_MASK) != 0) + s.append(",modifiers=").append(getModifiersExText(modifiers + & CONVERT_MASK)); + if (modifiers != 0) + s.append(",extModifiers=").append(getModifiersExText(modifiers)); + + s.append(",keyLocation=KEY_LOCATION_"); + switch (keyLocation) + { + case KEY_LOCATION_UNKNOWN: + s.append("UNKNOWN"); + break; + case KEY_LOCATION_STANDARD: + s.append("STANDARD"); + break; + case KEY_LOCATION_LEFT: + s.append("LEFT"); + break; + case KEY_LOCATION_RIGHT: + s.append("RIGHT"); + break; + case KEY_LOCATION_NUMPAD: + s.append("NUMPAD"); + } + + return s.toString(); + } + + /** + * Reads in the object from a serial stream. + * + * @param s the stream to read from + * @throws IOException if deserialization fails + * @throws ClassNotFoundException if deserialization fails + * @serialData default, except that the modifiers are converted to new style + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + modifiers = EventModifier.extend(modifiers); + } +} // class KeyEvent diff --git a/libjava/classpath/java/awt/event/KeyListener.java b/libjava/classpath/java/awt/event/KeyListener.java new file mode 100644 index 0000000..5c0a640 --- /dev/null +++ b/libjava/classpath/java/awt/event/KeyListener.java @@ -0,0 +1,77 @@ +/* KeyListener.java -- listen for keyboard presses + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This interface is for classes that wish to receive keyboard events. To + * watch a subset of these events, use a KeyAdapter. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see KeyAdapter + * @see KeyEvent + * @since 1.1 + * @status updated to 1.4 + */ +public interface KeyListener extends EventListener +{ + /** + * This method is called when a key is typed. A key is considered typed + * when it and all modifiers have been pressed and released, mapping to + * a single virtual key. + * + * @param event the <code>KeyEvent</code> indicating that a key was typed + */ + void keyTyped(KeyEvent event); + + /** + * This method is called when a key is pressed. + * + * @param event the <code>KeyEvent</code> indicating the key press + */ + void keyPressed(KeyEvent event); + + /** + * This method is called when a key is released. + * + * @param event the <code>KeyEvent</code> indicating the key release + */ + void keyReleased(KeyEvent event); +} // interface KeyListener diff --git a/libjava/classpath/java/awt/event/MouseAdapter.java b/libjava/classpath/java/awt/event/MouseAdapter.java new file mode 100644 index 0000000..9f40c28 --- /dev/null +++ b/libjava/classpath/java/awt/event/MouseAdapter.java @@ -0,0 +1,106 @@ +/* MouseAdapter.java -- convenience class for writing mouse listeners + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +/** + * This class implements <code>MouseListener</code> and implements all methods + * with empty bodies. This allows a listener interested in implementing only + * a subset of the <code>MouseListener</code> interface to extend this class + * and override only the desired methods. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see MouseEvent + * @see MouseListener + * @since 1.1 + * @status updated to 1.4 + */ +public abstract class MouseAdapter implements MouseListener +{ + /** + * Do nothing default constructor for subclasses. + */ + public MouseAdapter() + { + } + + /** + * Implements this method in the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void mouseClicked(MouseEvent event) + { + } + + /** + * Implements this method in the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void mousePressed(MouseEvent event) + { + } + + /** + * Implements this method in the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void mouseReleased(MouseEvent event) + { + } + + /** + * Implements this method in the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void mouseEntered(MouseEvent event) + { + } + + /** + * Implements this method in the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void mouseExited(MouseEvent event) + { + } +} // class MouseAdapter diff --git a/libjava/classpath/java/awt/event/MouseEvent.java b/libjava/classpath/java/awt/event/MouseEvent.java new file mode 100644 index 0000000..249c3d1 --- /dev/null +++ b/libjava/classpath/java/awt/event/MouseEvent.java @@ -0,0 +1,432 @@ +/* MouseEvent.java -- a mouse event + Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import gnu.java.awt.EventModifier; + +import java.awt.Component; +import java.awt.Point; +import java.io.IOException; +import java.io.ObjectInputStream; + +/** + * This event is generated for a mouse event. There are three main categories + * of mouse events: Regular events include pressing, releasing, and clicking + * buttons, as well as moving over the boundary of the unobscured portion of + * a component. Motion events include movement and dragging. Wheel events are + * covered separately by the subclass MouseWheelEvent. + * + * <p>A mouse event is tied to the unobstructed visible component that the + * mouse cursor was over at the time of the action. The button that was + * most recently pressed is the only one that shows up in + * <code>getModifiers</code>, and is returned by <code>getButton</code>, + * while all buttons that are down show up in <code>getModifiersEx</code>. + * + * <p>Drag events may be cut short if native drag-and-drop operations steal + * the event. Likewise, if a mouse drag exceeds the bounds of a window or + * virtual device, some platforms may clip the path to fit in the bounds of + * the component. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @see MouseAdapter + * @see MouseListener + * @see MouseMotionAdapter + * @see MouseMotionListener + * @see MouseWheelListener + * @since 1.1 + * @status updated to 1.4 + */ +public class MouseEvent extends InputEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -991214153494842848L; + + /** This is the first id in the range of event ids used by this class. */ + public static final int MOUSE_FIRST = 500; + + /** This is the last id in the range of event ids used by this class. */ + public static final int MOUSE_LAST = 507; + + /** This event id indicates that the mouse was clicked. */ + public static final int MOUSE_CLICKED = 500; + + /** This event id indicates that the mouse was pressed. */ + public static final int MOUSE_PRESSED = 501; + + /** This event id indicates that the mouse was released. */ + public static final int MOUSE_RELEASED = 502; + + /** This event id indicates that the mouse was moved. */ + public static final int MOUSE_MOVED = 503; + + /** This event id indicates that the mouse entered a component. */ + public static final int MOUSE_ENTERED = 504; + + /** This event id indicates that the mouse exited a component. */ + public static final int MOUSE_EXITED = 505; + + /** + * This indicates that no button changed state. + * + * @see #getButton() + * @since 1.4 + */ + public static final int NOBUTTON = 0; + + /** + * This indicates that button 1 changed state. + * + * @see #getButton() + * @since 1.4 + */ + public static final int BUTTON1 = 1; + + /** + * This indicates that button 2 changed state. + * + * @see #getButton() + * @since 1.4 + */ + public static final int BUTTON2 = 2; + + /** + * This indicates that button 3 changed state. + * + * @see #getButton() + * @since 1.4 + */ + public static final int BUTTON3 = 3; + + /** This event id indicates that the mouse was dragged over a component. */ + public static final int MOUSE_DRAGGED = 506; + + /** + * This event id indicates that the mouse wheel was rotated. + * + * @since 1.4 + */ + public static final int MOUSE_WHEEL = 507; + + /** + * The X coordinate of the mouse cursor at the time of the event. + * + * @see #getX() + * @serial the x coordinate + */ + private int x; + + /** + * The Y coordinate of the mouse cursor at the time of the event. + * + * @see #getY() + * @serial the y coordinate + */ + private int y; + + /** + * The number of clicks that took place. For MOUSE_CLICKED, MOUSE_PRESSED, + * and MOUSE_RELEASED, this will be at least 1; otherwise it is 0. + * + * see #getClickCount() + * @serial the number of clicks + */ + private final int clickCount; + + /** + * Indicates which mouse button changed state. Can only be one of + * {@link #NOBUTTON}, {@link #BUTTON1}, {@link #BUTTON2}, or + * {@link #BUTTON3}. + * + * @see #getButton() + * @since 1.4 + */ + private int button; + + /** + * Whether or not this event should trigger a popup menu. + * + * @see PopupMenu + * @see #isPopupTrigger() + * @serial true if this is a popup trigger + */ + private final boolean popupTrigger; + + /** + * Initializes a new instance of <code>MouseEvent</code> with the specified + * information. Note that an invalid id leads to unspecified results. + * + * @param source the source of the event + * @param id the event id + * @param when the timestamp of when the event occurred + * @param modifiers the modifier keys during the event, in old or new style + * @param x the X coordinate of the mouse point + * @param y the Y coordinate of the mouse point + * @param clickCount the number of mouse clicks for this event + * @param popupTrigger true if this event triggers a popup menu + * @param button the most recent mouse button to change state + * @throws IllegalArgumentException if source is null or button is invalid + * @since 1.4 + */ + public MouseEvent(Component source, int id, long when, int modifiers, + int x, int y, int clickCount, boolean popupTrigger, + int button) + { + super(source, id, when, modifiers); + this.x = x; + this.y = y; + this.clickCount = clickCount; + this.popupTrigger = popupTrigger; + this.button = button; + if (button < NOBUTTON || button > BUTTON3) + throw new IllegalArgumentException(); + if ((modifiers & EventModifier.OLD_MASK) != 0) + { + if ((modifiers & BUTTON1_MASK) != 0) + this.button = BUTTON1; + else if ((modifiers & BUTTON2_MASK) != 0) + this.button = BUTTON2; + else if ((modifiers & BUTTON3_MASK) != 0) + this.button = BUTTON3; + } + } + + /** + * Initializes a new instance of <code>MouseEvent</code> with the specified + * information. Note that an invalid id leads to unspecified results. + * + * @param source the source of the event + * @param id the event id + * @param when the timestamp of when the event occurred + * @param modifiers the modifier keys during the event, in old or new style + * @param x the X coordinate of the mouse point + * @param y the Y coordinate of the mouse point + * @param clickCount the number of mouse clicks for this event + * @param popupTrigger true if this event triggers a popup menu + * @throws IllegalArgumentException if source is null + */ + public MouseEvent(Component source, int id, long when, int modifiers, + int x, int y, int clickCount, boolean popupTrigger) + { + this(source, id, when, modifiers, x, y, clickCount, popupTrigger, + NOBUTTON); + } + + /** + * This method returns the X coordinate of the mouse position. This is + * relative to the source component. + * + * @return the x coordinate + */ + public int getX() + { + return x; + } + + /** + * This method returns the Y coordinate of the mouse position. This is + * relative to the source component. + * + * @return the y coordinate + */ + public int getY() + { + return y; + } + + /** + * This method returns a <code>Point</code> for the x,y position of + * the mouse pointer. This is relative to the source component. + * + * @return a <code>Point</code> for the event position + */ + public Point getPoint() + { + return new Point(x, y); + } + + /** + * Translates the event coordinates by the specified x and y offsets. + * + * @param dx the value to add to the X coordinate of this event + * @param dy the value to add to the Y coordiante of this event + */ + public void translatePoint(int dx, int dy) + { + x += dx; + y += dy; + } + + /** + * This method returns the number of mouse clicks associated with this + * event. + * + * @return the number of mouse clicks for this event + */ + public int getClickCount() + { + return clickCount; + } + + /** + * Returns which button, if any, was the most recent to change state. This + * will be one of {@link #NOBUTTON}, {@link #BUTTON1}, {@link #BUTTON2}, or + * {@link #BUTTON3}. + * + * @return the button that changed state + * @since 1.4 + */ + public int getButton() + { + return button; + } + + /** + * This method tests whether or not the event is a popup menu trigger. This + * should be checked in both MousePressed and MouseReleased to be + * cross-platform compatible, as different systems have different popup + * triggers. + * + * @return true if the event is a popup menu trigger + */ + public boolean isPopupTrigger() + { + return popupTrigger; + } + + /** + * Returns a string describing the modifiers, such as "Shift" or + * "Ctrl+Button1". + * + * XXX Sun claims this can be localized via the awt.properties file - how + * do we implement that? + * + * @param modifiers the old-style modifiers to convert to text + * @return a string representation of the modifiers in this bitmask + */ + public static String getMouseModifiersText(int modifiers) + { + modifiers &= EventModifier.OLD_MASK; + if ((modifiers & BUTTON2_MASK) != 0) + modifiers |= BUTTON2_DOWN_MASK; + if ((modifiers & BUTTON3_MASK) != 0) + modifiers |= BUTTON3_DOWN_MASK; + return getModifiersExText(EventModifier.extend(modifiers)); + } + + /** + * Returns a string identifying this event. This is formatted as the field + * name of the id type, followed by the (x,y) point, the most recent button + * changed, modifiers (if any), extModifiers (if any), and clickCount. + * + * @return a string identifying this event + */ + public String paramString() + { + StringBuffer s = new StringBuffer(); + switch (id) + { + case MOUSE_CLICKED: + s.append("MOUSE_CLICKED,("); + break; + case MOUSE_PRESSED: + s.append("MOUSE_PRESSED,("); + break; + case MOUSE_RELEASED: + s.append("MOUSE_RELEASED,("); + break; + case MOUSE_MOVED: + s.append("MOUSE_MOVED,("); + break; + case MOUSE_ENTERED: + s.append("MOUSE_ENTERED,("); + break; + case MOUSE_EXITED: + s.append("MOUSE_EXITED,("); + break; + case MOUSE_DRAGGED: + s.append("MOUSE_DRAGGED,("); + break; + case MOUSE_WHEEL: + s.append("MOUSE_WHEEL,("); + break; + default: + s.append("unknown type,("); + } + s.append(x).append(',').append(y).append("),button=").append(button); + if ((modifiers & EventModifier.NEW_MASK) != 0) + { + int mod = modifiers; + if ((mod & (ALT_DOWN_MASK | BUTTON2_DOWN_MASK)) != 0) + mod |= ALT_DOWN_MASK | BUTTON2_DOWN_MASK; + if ((mod & (META_DOWN_MASK | BUTTON3_DOWN_MASK)) != 0) + mod |= META_DOWN_MASK | BUTTON3_DOWN_MASK; + s.append(",modifiers=").append(getModifiersExText(mod)); + } + if (modifiers != 0) + s.append(",extModifiers=").append(getModifiersExText(modifiers)); + return s.append(",clickCount=").append(clickCount).toString(); + } + + /** + * Reads in the object from a serial stream. + * + * @param s the stream to read from + * @throws IOException if deserialization fails + * @throws ClassNotFoundException if deserialization fails + * @serialData default, except that the modifiers are converted to new style + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + if ((modifiers & EventModifier.OLD_MASK) != 0) + { + if ((modifiers & BUTTON1_MASK) != 0) + button = BUTTON1; + else if ((modifiers & BUTTON2_MASK) != 0) + button = BUTTON2; + else if ((modifiers & BUTTON3_MASK) != 0) + button = BUTTON3; + modifiers = EventModifier.extend(modifiers); + } + } +} // class MouseEvent diff --git a/libjava/classpath/java/awt/event/MouseListener.java b/libjava/classpath/java/awt/event/MouseListener.java new file mode 100644 index 0000000..4508019 --- /dev/null +++ b/libjava/classpath/java/awt/event/MouseListener.java @@ -0,0 +1,94 @@ +/* MouseListener.java -- listen for mouse clicks and crossing component edges + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This interface is for classes that wish to receive mouse events other than + * simple motion events. This includes clicks (but not mouse wheel events), + * and crossing component boundaries without change in button status. To + * track moves and drags, use MouseMotionListener, and to track wheel events, + * use MouseWheelListener. To watch a subset of these events, use a + * MouseAdapter. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see MouseAdapter + * @see MouseEvent + * @since 1.1 + * @status updated to 1.4 + */ +public interface MouseListener extends EventListener +{ + /** + * This method is called when the mouse is clicked (pressed and released + * in short succession) on a component. + * + * @param event the <code>MouseEvent</code> indicating the click + */ + void mouseClicked(MouseEvent event); + + /** + * This method is called when the mouse is pressed over a component. + * + * @param event the <code>MouseEvent</code> for the press + */ + void mousePressed(MouseEvent event); + + /** + * This method is called when the mouse is released over a component. + * + * @param event the <code>MouseEvent</code> for the release + */ + void mouseReleased(MouseEvent event); + + /** + * This method is called when the mouse enters a component. + * + * @param event the <code>MouseEvent</code> for the entry + */ + void mouseEntered(MouseEvent event); + + /** + * This method is called when the mouse exits a component. + * + * @param event the <code>MouseEvent</code> for the exit + */ + void mouseExited(MouseEvent event); +} // interface MouseListener diff --git a/libjava/classpath/java/awt/event/MouseMotionAdapter.java b/libjava/classpath/java/awt/event/MouseMotionAdapter.java new file mode 100644 index 0000000..8a295f6 --- /dev/null +++ b/libjava/classpath/java/awt/event/MouseMotionAdapter.java @@ -0,0 +1,79 @@ +/* MouseMotionAdapter.java -- convenience class for mouse motion listeners + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +/** + * This class implements <code>MouseMotionListener</code> and implements all + * methods with empty bodies. This allows a listener interested in + * implementing only a subset of the <code>MouseMotionListener</code> + * interface to extend this class and override only the desired methods. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see MouseEvent + * @see MouseMotionListener + * @since 1.1 + * @status updated to 1.4 + */ +public abstract class MouseMotionAdapter implements MouseMotionListener +{ + /** + * Do nothing default constructor for subclasses. + */ + public MouseMotionAdapter() + { + } + + /** + * Implement this method in the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void mouseDragged(MouseEvent event) + { + } + + /** + * Implement this method in the interface with an empty body. + * + * @param event the event, ignored in this implementation + */ + public void mouseMoved(MouseEvent event) + { + } +} // class MouseMotionAdapter diff --git a/libjava/classpath/java/awt/event/MouseMotionListener.java b/libjava/classpath/java/awt/event/MouseMotionListener.java new file mode 100644 index 0000000..ba2c569 --- /dev/null +++ b/libjava/classpath/java/awt/event/MouseMotionListener.java @@ -0,0 +1,72 @@ +/* MouseMotionListener.java -- listen to mouse motion events + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This interface is for classes that wish to be notified of mouse movements. + * This includes moves and drags, but not crossing component boundaries. To + * track other mouse events, use MouseListener or MouseWheelListener. To + * watch a subset of these events, use a MouseMotionAdapter. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see MouseMotionAdapter + * @see MouseEvent + * @since 1.1 + * @status updated to 1.4 + */ +public interface MouseMotionListener extends EventListener +{ + /** + * This method is called when the mouse is moved over a component + * while a button has been pressed. + * + * @param event the <code>MouseEvent</code> indicating the motion + */ + void mouseDragged(MouseEvent event); + + /** + * This method is called when the mouse is moved over a component + * while no button is pressed. + * + * @param event the <code>MouseEvent</code> indicating the motion + */ + void mouseMoved(MouseEvent event); +} // interface MouseMotionListener diff --git a/libjava/classpath/java/awt/event/MouseWheelEvent.java b/libjava/classpath/java/awt/event/MouseWheelEvent.java new file mode 100644 index 0000000..bc603aa --- /dev/null +++ b/libjava/classpath/java/awt/event/MouseWheelEvent.java @@ -0,0 +1,232 @@ +/* MouseWheelEvent.java -- a mouse wheel event + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.Adjustable; +import java.awt.Component; +import java.awt.Rectangle; +import java.awt.ScrollPane; + +import javax.swing.JScrollPane; +import javax.swing.Scrollable; + +/** + * This event is generated for a mouse wheel rotation. The wheel (the middle + * mouse button on most modern mice) can be rotated towards or away from the + * user, and is ofteh used for scrolling. + * + * <p>Because of the special use for scrolling components, MouseWheelEvents + * often affect a different component than the one located at the point of + * the event. If the component under the mouse cursor does not accept wheel + * events, the event is passed to the first ancestor container which does. This + * is often a ScrollPane, which knows how to scroll. If an AWT component is + * built from a native widget that knows how to use mouse wheel events, that + * component will consume the event. + * + * <p>The two most common scroll types are "units" (lines at a time) or + * "blocks" (pages at a time). The initial setting is taken from the platform, + * although the user can adjust the setting at any time. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see MouseWheelListener + * @see ScrollPane + * @see ScrollPane#setWheelScrollingEnabled(boolean) + * @see JScrollPane + * @see JScrollPane#setWheelScrollingEnabled(boolean) + * @since 1.4 + * @status updated to 1.4 + */ +public class MouseWheelEvent extends MouseEvent +{ + /** + * Compatible with JDK 1.4+. + */ + private static final long serialVersionUID = 6459879390515399677L; + + /** + * Indicates scrolling by units (lines). + * + * @see #getScrollType() + */ + public static final int WHEEL_UNIT_SCROLL = 0; + + /** + * Indicates scrolling by blocks (pages). + * + * @see #getScrollType() + */ + public static final int WHEEL_BLOCK_SCROLL = 1; + + /** + * Indicates what scroll type should take place. This should be limited + * to {@link #WHEEL_UNIT_SCROLL} and {@link #WHEEL_BLOCK_SCROLL}. + * + * @serial the scroll type + */ + private final int scrollType; + + /** + * Indicates the scroll amount. This is only meaningful if scrollType is + * WHEEL_UNIT_SCROLL. + * + * @serial the number of lines to scroll + */ + private final int scrollAmount; + + /** + * Indicates how far the mouse wheel was rotated. + * + * @serial the rotation amount + */ + private final int wheelRotation; + + /** + * Initializes a new instance of <code>MouseWheelEvent</code> with the + * specified information. Note that an invalid id leads to unspecified + * results. + * + * @param source the source of the event + * @param id the event id + * @param when the timestamp of when the event occurred + * @param modifiers any modifier bits for this event + * @param x the X coordinate of the mouse point + * @param y the Y coordinate of the mouse point + * @param clickCount the number of mouse clicks for this event + * @param popupTrigger true if this event triggers a popup menu + * @param scrollType one of {@link #WHEEL_UNIT_SCROLL}, + * {@link #WHEEL_BLOCK_SCROLL} + * @param scrollAmount the number of units to scroll, ignored for block type + * @param wheelRotation the number of rotation "clicks" + * @throws IllegalArgumentException if source is null + * @see MouseEvent#MouseEvent(Component, int, long, int, int, int, int, + * boolean) + */ + public MouseWheelEvent(Component source, int id, long when, int modifiers, + int x, int y, int clickCount, boolean popupTrigger, + int scrollType, int scrollAmount, int wheelRotation) + { + super(source, id, when, modifiers, x, y, clickCount, popupTrigger); + this.scrollType = scrollType; + this.scrollAmount = scrollAmount; + this.wheelRotation = wheelRotation; + } + + /** + * This method returns the scrolling pattern this event requests. Legal + * values are {@link #WHEEL_UNIT_SCROLL} and {@link #WHEEL_BLOCK_SCROLL}. + * + * @return the scroll type + * @see Adjustable#getUnitIncrement() + * @see Adjustable#getBlockIncrement() + * @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int) + * @see Scrollable#getScrollableBlockIncrement(Rectangle, int, int) + */ + public int getScrollType() + { + return scrollType; + } + + /** + * Returns the number of units to scroll in response to this event. This + * only makes sense when the scroll type is WHEEL_UNIT_SCROLL. + * + * @return the number of scroll units, if defined + * @see #getScrollType() + */ + public int getScrollAmount() + { + return scrollAmount; + } + + /** + * Gets the number of "clicks" the wheel was rotated. Negative values move + * up (away) from the user, positive values move down (towards) the user. + * + * @return the number of rotation clicks + */ + public int getWheelRotation() + { + return wheelRotation; + } + + /** + * This is a convenience method which aids in a common listener for scrolling + * a scrollpane (although this is already built into ScrollPane and + * JScrollPane). This method only makes sense when getScrollType() returns + * WHEEL_UNIT_SCROLL. + * + * <p>This accounts for direction of scroll and amount of wheel movement, as + * interpreted by the platform settings. + * + * @return the number of units to scroll + * @see #getScrollType() + * @see #getScrollAmount() + * @see MouseWheelListener + * @see Adjustable + * @see Adjustable#getUnitIncrement() + * @see Scrollable + * @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int) + * @see ScrollPane + * @see ScrollPane#setWheelScrollingEnabled(boolean) + * @see JScrollPane + * @see JScrollPane#setWheelScrollingEnabled(boolean) + */ + public int getUnitsToScroll() + { + return wheelRotation * scrollAmount; + } + + /** + * Returns a string identifying this event. For mouse wheel events, this + * is <code>super.paramString() + ",scrollType=WHEEL_" + + * (getScrollType() == WHEEL_UNIT_SCROLL ? "UNIT" : "BLOCK") + * + "_SCROLL,scrollAmount=" + getScrollAmount() + ",wheelRotation=" + * + getWheelRotation()</code>. + * + * @return a string identifying this event + */ + public String paramString() + { + return super.paramString() + ",scrollType=" + + (scrollType == WHEEL_UNIT_SCROLL ? "WHEEL_UNIT_SCROLL" + : scrollType == WHEEL_BLOCK_SCROLL ? "WHEEL_BLOCK_SCROLL" + : "unknown scroll type") + + ",scrollAmount=" + scrollAmount + ",wheelRotation=" + wheelRotation; + } +} // class MouseWheelEvent diff --git a/libjava/classpath/java/awt/event/MouseWheelListener.java b/libjava/classpath/java/awt/event/MouseWheelListener.java new file mode 100644 index 0000000..1125582 --- /dev/null +++ b/libjava/classpath/java/awt/event/MouseWheelListener.java @@ -0,0 +1,60 @@ +/* MouseWheelListener.java -- listen for mouse wheel events + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This interface is for classes that wish to receive mouse wheel events. For + * other events, use MouseListener or MouseMotionListener. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see MouseWheelEvent + * @since 1.4 + * @status updated to 1.4 + */ +public interface MouseWheelListener extends EventListener +{ + /** + * This method is called when the mouse wheel is rotated. + * + * @param event the <code>MouseWheelEvent</code> indicating the rotation + */ + void mouseWheelMoved(MouseWheelEvent event); +} // interface MouseWheelListener diff --git a/libjava/classpath/java/awt/event/PaintEvent.java b/libjava/classpath/java/awt/event/PaintEvent.java new file mode 100644 index 0000000..bb89c37 --- /dev/null +++ b/libjava/classpath/java/awt/event/PaintEvent.java @@ -0,0 +1,127 @@ +/* PaintEvent.java -- an area of the screen needs to be repainted + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.Component; +import java.awt.Rectangle; + +/** + * This event is generated when an area of the screen needs to be painted. + * This event is not meant for users, but exists to allow proper serialization + * behavior in the EventQueue with user-accessible events. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @since 1.1 + * @status updated to 1.4 + */ +public class PaintEvent extends ComponentEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = 1267492026433337593L; + + /** This is the first id in the range of event ids used by this class. */ + public static final int PAINT_FIRST = 800; + + /** This is the last id in the range of event ids used by this class. */ + public static final int PAINT_LAST = 801; + + /** This id is for paint event types. */ + public static final int PAINT = 800; + + /** This id is for update event types. */ + public static final int UPDATE = 801; + + /** + * This is the rectange to be painted or updated. + * + * @see #getUpdateRect() + * @see #setUpdateRect(Rectangle) + * @serial the non-null rectangle to be painted + */ + private Rectangle updateRect; + + /** + * Initializes a new instance of <code>PaintEvent</code> with the specified + * source, id, and update region. Note that an invalid id leads to + * unspecified results. + * + * @param source the event source + * @param id the event id + * @param updateRect the rectangle to repaint + * @throws IllegalArgumentException if source is null + */ + public PaintEvent(Component source, int id, Rectangle updateRect) + { + super(source, id); + this.updateRect = updateRect; + } + + /** + * Returns the rectange to be updated for this event. + * + * @return the rectangle to update + */ + public Rectangle getUpdateRect() + { + return updateRect; + } + + /** + * Sets the rectangle to be updated for this event. + * + * @param updateRect the new update rectangle for this event + */ + public void setUpdateRect(Rectangle updateRect) + { + this.updateRect = updateRect; + } + + /** + * Returns a string identifying this event. + * + * @return a string identifying this event + */ + public String paramString() + { + return (id == PAINT ? "PAINT,updateRect=" : id == UPDATE + ? "UPDATE,updateRect=" : "unknown type,updateRect=") + updateRect; + } +} // class PaintEvent diff --git a/libjava/classpath/java/awt/event/TextEvent.java b/libjava/classpath/java/awt/event/TextEvent.java new file mode 100644 index 0000000..0288abb --- /dev/null +++ b/libjava/classpath/java/awt/event/TextEvent.java @@ -0,0 +1,93 @@ +/* TextEvent.java -- event for text changes + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.AWTEvent; +import java.awt.TextComponent; + +/** + * This event is generated when a text box changes contents. This is an + * abstraction that distills a large number of individual mouse or keyboard + * events into a simpler "text changed" event. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see TextComponent + * @see TextListener + * @since 1.1 + * @status updated to 1.4 + */ +public class TextEvent extends AWTEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = 6269902291250941179L; + + /** This is the first id in the range of event ids used by this class. */ + public static final int TEXT_FIRST = 900; + + /** This is the last id in the range of event ids used by this class. */ + public static final int TEXT_LAST = 900; + + /** This event id indicates that the text of an object has changed. */ + public static final int TEXT_VALUE_CHANGED = 900; + + /** + * Initializes a new instance of <code>TextEvent</code> with the specified + * source and id. Note that an invalid id leads to unspecified results. + * + * @param source the (TextComponent) object that generated this event + * @param id the event id + * @throws IllegalArgumentException if source is null + */ + public TextEvent(Object source, int id) + { + super(source, id); + } + + /** + * Returns a string identifying this event. This is "TEXT_VALUE_CHANGED". + * + * @return a string identifying this event + */ + public String paramString() + { + return id == TEXT_VALUE_CHANGED ? "TEXT_VALUE_CHANGED" : "unknown type"; + } +} // class TextEvent diff --git a/libjava/classpath/java/awt/event/TextListener.java b/libjava/classpath/java/awt/event/TextListener.java new file mode 100644 index 0000000..bcdd7fa --- /dev/null +++ b/libjava/classpath/java/awt/event/TextListener.java @@ -0,0 +1,60 @@ +/* TextListener.java -- listen for text changes + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This interface is for classes that wish to be notified when text changes + * in a component. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see TextEvent + * @since 1.1 + * @status updated to 1.4 + */ +public interface TextListener extends EventListener +{ + /** + * This method is called when the text being monitored changes. + * + * @param event the <code>TextEvent</code> indicating the change + */ + void textValueChanged(TextEvent event); +} // interface TextListener diff --git a/libjava/classpath/java/awt/event/WindowAdapter.java b/libjava/classpath/java/awt/event/WindowAdapter.java new file mode 100644 index 0000000..708de58 --- /dev/null +++ b/libjava/classpath/java/awt/event/WindowAdapter.java @@ -0,0 +1,156 @@ +/* WindowAdapter.java -- convenience class for writing window listeners + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +/** + * This class implements <code>WindowListener</code>, + * <code>WindowStateListener</code>, and <code>WindowFocusListener</code>, and + * implements all methods with empty bodies. This allows a listener + * interested in listening to only a subset of any <code>WindowEvent</code> + * actions to extend this class and override only the desired methods. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see ComponentEvent + * @see ComponentListener + * @since 1.1 + * @status updated to 1.4 + */ +public abstract class WindowAdapter + implements WindowListener, WindowStateListener, WindowFocusListener +{ + /** + * Do nothing default constructor for subclasses. + */ + public WindowAdapter() + { + } + + /** + * Implements this method from the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void windowOpened(WindowEvent event) + { + } + + /** + * Implements this method from the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void windowClosing(WindowEvent event) + { + } + + /** + * Implements this method from the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void windowClosed(WindowEvent event) + { + } + + /** + * Implements this method from the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void windowIconified(WindowEvent event) + { + } + + /** + * Implements this method from the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void windowDeiconified(WindowEvent event) + { + } + + /** + * Implements this method from the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void windowActivated(WindowEvent event) + { + } + + /** + * Implements this method from the interface with an empty method body. + * + * @param event the event, ignored in this implementation + */ + public void windowDeactivated(WindowEvent event) + { + } + + /** + * Implements this method from the interface with an empty method body. + * + * @param event the event, ignored in this implementation + * @since 1.4 + */ + public void windowStateChanged(WindowEvent event) + { + } + + /** + * Implements this method from the interface with an empty method body. + * + * @param event the event, ignored in this implementation + * @since 1.4 + */ + public void windowGainedFocus(WindowEvent event) + { + } + + /** + * Implements this method from the interface with an empty method body. + * + * @param event the event, ignored in this implementation + * @since 1.4 + */ + public void windowLostFocus(WindowEvent event) + { + } +} // class WindowAdapter diff --git a/libjava/classpath/java/awt/event/WindowEvent.java b/libjava/classpath/java/awt/event/WindowEvent.java new file mode 100644 index 0000000..2186889 --- /dev/null +++ b/libjava/classpath/java/awt/event/WindowEvent.java @@ -0,0 +1,312 @@ +/* WindowEvent.java -- window change event + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.Frame; +import java.awt.Window; + +/** + * This event is generated when there is a change in a window. This includes + * creation, closing, iconification, activation, and focus changes. There + * are three listeners, for three types of events: WindowListeners deal with + * the lifecycle of a window, WindowStateListeners deal with window state + * like maximization, and WindowFocusListeners deal with focus switching to + * or from a window. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see WindowAdapter + * @see WindowListener + * @see WindowFocusListener + * @see WindowStateListener + * @since 1.1 + * @status updated to 1.4 + */ +public class WindowEvent extends ComponentEvent +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -1567959133147912127L; + + /** This is the first id in the range of event ids used by this class. */ + public static final int WINDOW_FIRST = 200; + + /** This is the id for a window that is opened. */ + public static final int WINDOW_OPENED = 200; + + /** This is the id for a window that is about to close. */ + public static final int WINDOW_CLOSING = 201; + + /** This is the id for a window that finished closing. */ + public static final int WINDOW_CLOSED = 202; + + /** This is the id for a window that is iconified. */ + public static final int WINDOW_ICONIFIED = 203; + + /** This is the id for a window that is de-iconified. */ + public static final int WINDOW_DEICONIFIED = 204; + + /** This is the id for a window that is activated. */ + public static final int WINDOW_ACTIVATED = 205; + + /** This is the id for a window that is de-activated. */ + public static final int WINDOW_DEACTIVATED = 206; + + /** + * This is the id for a window becoming the focused window. + * + * @since 1.4 + */ + public static final int WINDOW_GAINED_FOCUS = 207; + + /** + * This is the id for a window losing all focus. + * + * @since 1.4 + */ + public static final int WINDOW_LOST_FOCUS = 208; + + /** + * This is the id for a window state change, such as maximization. + * + * @since 1.4 + */ + public static final int WINDOW_STATE_CHANGED = 209; + + /** This is the last id in the range of event ids used by this class. */ + public static final int WINDOW_LAST = 209; + + /** + * The other Window involved in a focus or activation change. For + * WINDOW_ACTIVATED and WINDOW_GAINED_FOCUS events, this is the window that + * lost focus; for WINDOW_DEACTIVATED and WINDOW_LOST_FOCUS, this is the + * window that stole focus; and for other events (or when native + * implementation does not have the data available), this is null. + * + * @see #getOppositeWindow() + * @serial the opposite window, or null + * @since 1.4 + */ + private final Window opposite; + + /** + * The former state of the window. + * + * @serial bitmask of the old window state + * @since 1.4 + */ + private final int oldState; + + /** + * The present state of the window. + * + * @serial bitmask of the new window state + * @since 1.4 + */ + private final int newState; + + /** + * Initializes a new instance of <code>WindowEvent</code> with the specified + * parameters. Note that an invalid id leads to unspecified results. + * + * @param source the window that generated this event + * @param id the event id + * @param opposite the window that received the opposite event, or null + * @param oldState the previous state of this window + * @param newState the new state of this window + * @throws IllegalArgumentException if source is null + * @since 1.4 + */ + public WindowEvent(Window source, int id, Window opposite, + int oldState, int newState) + { + super(source, id); + this.opposite = opposite; + this.oldState = oldState; + this.newState = newState; + } + + /** + * Initializes a new instance of <code>WindowEvent</code> with the specified + * parameters. Note that an invalid id leads to unspecified results. + * + * @param source the window that generated this event + * @param id the event id + * @param opposite the window that received the opposite event, or null + * @throws IllegalArgumentException if source is null + * @since 1.4 + */ + public WindowEvent(Window source, int id, Window opposite) + { + this(source, id, opposite, 0, 0); + } + + /** + * Initializes a new instance of <code>WindowEvent</code> with the specified + * parameters. Note that an invalid id leads to unspecified results. + * + * @param source the window that generated this event + * @param id the event id + * @param oldState the previous state of this window + * @param newState the new state of this window + * @throws IllegalArgumentException if source is null + * @since 1.4 + */ + public WindowEvent(Window source, int id, int oldState, int newState) + { + this(source, id, null, oldState, newState); + } + + /** + * Initializes a new instance of <code>WindowEvent</code> with the specified + * parameters. Note that an invalid id leads to unspecified results. + * + * @param source the window that generated this event + * @param id the event id + * @throws IllegalArgumentException if source is null + */ + public WindowEvent(Window source, int id) + { + this(source, id, null, 0, 0); + } + + /** + * Returns the event source as a <code>Window</code>. If the source has + * subsequently been modified to a non-Window, this returns null. + * + * @return the event source as a <code>Window</code> + */ + public Window getWindow() + { + return source instanceof Window ? (Window) source : null; + } + + /** + * Returns the opposite window if this window was involved in an activation + * or focus change. For WINDOW_ACTIVATED and WINDOW_GAINED_FOCUS events, + * this is the window that lost focus; for WINDOW_DEACTIVATED and + * WINDOW_LOST_FOCUS, this is the window that stole focus; and for other + * events (or when native implementation does not have the data available), + * this is null. + * + * @return the opposite window, or null + * @since 1.4 + */ + public Window getOppositeWindow() + { + return opposite; + } + + /** + * Returns the state of this window before the event. This is the bitwise + * or of fields in Frame: NORMAL, ICONIFIED, MAXIMIZED_HORIZ, MAXIMIZED_VERT, + * and MAXIMIZED_BOTH. + * + * @return the former state + * @see Frame#getExtendedState() + * @since 1.4 + */ + public int getOldState() + { + return oldState; + } + + /** + * Returns the state of this window after the event. This is the bitwise + * or of fields in Frame: NORMAL, ICONIFIED, MAXIMIZED_HORIZ, MAXIMIZED_VERT, + * and MAXIMIZED_BOTH. + * + * @return the updated state + * @see Frame#getExtendedState() + * @since 1.4 + */ + public int getNewState() + { + return newState; + } + + /** + * Returns a string that identifies this event. This is formatted as the + * field name of the id, followed by the opposite window, old state, and + * new state. + * + * @return a string that identifies this event + */ + public String paramString() + { + StringBuffer s = new StringBuffer(); + switch (id) + { + case WINDOW_OPENED: + s.append("WINDOW_OPENED,opposite="); + break; + case WINDOW_CLOSING: + s.append("WINDOW_CLOSING,opposite="); + break; + case WINDOW_CLOSED: + s.append("WINDOW_CLOSED,opposite="); + break; + case WINDOW_ICONIFIED: + s.append("WINDOW_ICONIFIED,opposite="); + break; + case WINDOW_DEICONIFIED: + s.append("WINDOW_DEICONIFIED,opposite="); + break; + case WINDOW_ACTIVATED: + s.append("WINDOW_ACTIVATED,opposite="); + break; + case WINDOW_DEACTIVATED: + s.append("WINDOW_DEACTIVATED,opposite="); + break; + case WINDOW_GAINED_FOCUS: + s.append("WINDOW_GAINED_FOCUS,opposite="); + break; + case WINDOW_LOST_FOCUS: + s.append("WINDOW_LOST_FOCUS,opposite="); + break; + case WINDOW_STATE_CHANGED: + s.append("WINDOW_STATE_CHANGED,opposite="); + break; + default: + s.append("unknown type,opposite="); + } + return s.append(opposite).append(",oldState=").append(oldState) + .append(",newState=").append(newState).toString(); + } +} // class WindowEvent diff --git a/libjava/classpath/java/awt/event/WindowFocusListener.java b/libjava/classpath/java/awt/event/WindowFocusListener.java new file mode 100644 index 0000000..7384253 --- /dev/null +++ b/libjava/classpath/java/awt/event/WindowFocusListener.java @@ -0,0 +1,68 @@ +/* WindowFocusListener.java -- listens for window focus events + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This interface is for classes that wish to monitor events for window + * focus changes. To watch a subset of these events, use a WindowAdapter. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see WindowAdapter + * @see WindowEvent + * @since 1.4 + * @status updated to 1.4 + */ +public interface WindowFocusListener extends EventListener +{ + /** + * This method is called when a window gains focus. + * + * @param event the <code>WindowEvent</code> indicating the focus change + */ + void windowGainedFocus(WindowEvent event); + + /** + * This method is called when a window loses focus. + * + * @param event the <code>WindowEvent</code> indicating the focus change + */ + void windowLostFocus(WindowEvent event); +} // interface WindowFocusListener diff --git a/libjava/classpath/java/awt/event/WindowListener.java b/libjava/classpath/java/awt/event/WindowListener.java new file mode 100644 index 0000000..52213eb --- /dev/null +++ b/libjava/classpath/java/awt/event/WindowListener.java @@ -0,0 +1,109 @@ +/* WindowListener.java -- listens for window events + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.awt.Frame; +import java.awt.Image; +import java.util.EventListener; + +/** + * This interface is for classes that wish to monitor events for window + * changes. To watch a subset of these events, use a WindowAdapter. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @see WindowAdapter + * @see WindowEvent + * @since 1.1 + * @status updated to 1.4 + */ +public interface WindowListener extends EventListener +{ + /** + * This method is called when the window is made visible. + * + * @param event the <code>WindowEvent</code> indicating the change + */ + void windowOpened(WindowEvent event); + + /** + * This method is called when the user calls the system menu close + * function, giving the program a chance to cancel the close. + * + * @param event the <code>WindowEvent</code> indicating the close attempt + */ + void windowClosing(WindowEvent event); + + /** + * This method is called when the window is closed. + * + * @param event the <code>WindowEvent</code> indicating the dispose + */ + void windowClosed(WindowEvent event); + + /** + * This method is called when the window is iconified. + * + * @param event the <code>WindowEvent</code> indicating the iconification + * @see Frame#setIconImage(Image) + */ + void windowIconified(WindowEvent event); + + /** + * This method is called when the window is deiconified. + * + * @param event the <code>WindowEvent</code> indicating the deiconification + */ + void windowDeiconified(WindowEvent event); + + /** + * This method is called when a window is activated. Only Frames and Dialogs + * can be active, and the active window always contains the component with + * focus. + * + * @param event the <code>WindowEvent</code> indicating the activation + */ + void windowActivated(WindowEvent event); + + /** + * This method is called when the window is deactivated. + * + * @param event the <code>WindowEvent</code> indicating the deactivation + */ + void windowDeactivated(WindowEvent event); +} // interface WindowListener diff --git a/libjava/classpath/java/awt/event/WindowStateListener.java b/libjava/classpath/java/awt/event/WindowStateListener.java new file mode 100644 index 0000000..9bc6174 --- /dev/null +++ b/libjava/classpath/java/awt/event/WindowStateListener.java @@ -0,0 +1,62 @@ +/* WindowStateListener.java -- listens for window state changes + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.event; + +import java.util.EventListener; + +/** + * This interface is for classes that wish to monitor events for window + * state changes. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see WindowAdapter + * @see WindowEvent + * @since 1.4 + * @status updated to 1.4 + */ +public interface WindowStateListener extends EventListener +{ + /** + * This method is called when the window state is changed, because of + * iconification or maximization. + * + * @param event the <code>WindowEvent</code> indicating the change + */ + void windowStateChanged(WindowEvent event); +} // interface WindowStateListener diff --git a/libjava/classpath/java/awt/event/package.html b/libjava/classpath/java/awt/event/package.html new file mode 100644 index 0000000..77662a3 --- /dev/null +++ b/libjava/classpath/java/awt/event/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.event package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.event</title></head> + +<body> +<p>Listeners and adapters for different kinds of AWT events.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/font/FontRenderContext.java b/libjava/classpath/java/awt/font/FontRenderContext.java new file mode 100644 index 0000000..78564a6 --- /dev/null +++ b/libjava/classpath/java/awt/font/FontRenderContext.java @@ -0,0 +1,126 @@ +/* FontRenderContext.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.awt.geom.AffineTransform; + +/** + * @author Michael Koch + */ +public class FontRenderContext +{ + private AffineTransform affineTransform; + private boolean isAntiAliased; + private boolean usesFractionalMetrics; + + /** + * Construct a new <code>FontRenderContext</code>. + */ + protected FontRenderContext() + { + // Do nothing here. + } + + /** + * Construct a new <code>FontRenderContext</code>. + */ + public FontRenderContext (AffineTransform tx, boolean isAntiAliased, + boolean usesFractionalMetrics) + { + if (tx != null + && !tx.isIdentity ()) + { + this.affineTransform = new AffineTransform (tx); + } + + this.isAntiAliased = isAntiAliased; + this.usesFractionalMetrics = usesFractionalMetrics; + } + + public boolean equals (Object obj) + { + if (! (obj instanceof FontRenderContext)) + return false; + + return equals ((FontRenderContext) obj); + } + + public boolean equals (FontRenderContext rhs) + { + return (affineTransform.equals (rhs.getTransform ()) + && isAntiAliased == rhs.isAntiAliased () + && usesFractionalMetrics == rhs.usesFractionalMetrics ()); + } + + + /** + * Retrieves the affine transform for scaling typographical points + * to raster pixels. + * + * @return a clone of the transform object. + */ + public AffineTransform getTransform () + { + if (affineTransform == null) + return new AffineTransform (); + else + return new AffineTransform (affineTransform); + } + + + /** + * Returns the hash code of the font render context. + */ + public int hashCode () + { + // FIXME: check what SUN does here. + return affineTransform == null ? 0 : affineTransform.hashCode (); + } + + public boolean isAntiAliased () + { + return isAntiAliased; + } + + public boolean usesFractionalMetrics () + { + return usesFractionalMetrics; + } +} + diff --git a/libjava/classpath/java/awt/font/GlyphJustificationInfo.java b/libjava/classpath/java/awt/font/GlyphJustificationInfo.java new file mode 100644 index 0000000..5f45fd5 --- /dev/null +++ b/libjava/classpath/java/awt/font/GlyphJustificationInfo.java @@ -0,0 +1,77 @@ +/* GlyphJustificationInfo.java + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +/** + * @author Michael Koch + */ +public final class GlyphJustificationInfo +{ + public static final int PRIORITY_KASHIDA = 0; + public static final int PRIORITY_WHITESPACE = 1; + public static final int PRIORITY_INTERCHAR = 2; + public static final int PRIORITY_NONE = 3; + + public final float weight; + public final int growPriority; + public final boolean growAbsorb; + public final float growLeftLimit; + public final float growRightLimit; + public final int shrinkPriority; + public final boolean shrinkAbsorb; + public final float shrinkLeftLimit; + public final float shrinkRightLimit; + + public GlyphJustificationInfo (float weight, boolean growAbsorb, + int growPriority, float growLeftLimit, + float growRightLimit, boolean shrinkAbsorb, + int shrinkPriority, float shrinkLeftLimit, + float shrinkRightLimit) + { + this.weight = weight; + this.growAbsorb = growAbsorb; + this.growPriority = growPriority; + this.growLeftLimit = growLeftLimit; + this.growRightLimit = growRightLimit; + this.shrinkAbsorb = shrinkAbsorb; + this.shrinkPriority = shrinkPriority; + this.shrinkLeftLimit = shrinkLeftLimit; + this.shrinkRightLimit = shrinkRightLimit; + } +} diff --git a/libjava/classpath/java/awt/font/GlyphMetrics.java b/libjava/classpath/java/awt/font/GlyphMetrics.java new file mode 100644 index 0000000..28b2088 --- /dev/null +++ b/libjava/classpath/java/awt/font/GlyphMetrics.java @@ -0,0 +1,134 @@ +/* GlyphMetrics.java + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.awt.geom.Rectangle2D; + +/** + * @author Michael Koch + */ +public final class GlyphMetrics +{ + public static final byte COMBINING = 2; + public static final byte COMPONENT = 3; + public static final byte LIGATURE = 1; + public static final byte STANDARD = 0; + public static final byte WHITESPACE = 4; + + private boolean horizontal; + private float advanceX; + private float advanceY; + private Rectangle2D bounds; + private byte glyphType; + + public GlyphMetrics (boolean horizontal, float advanceX, float advanceY, + Rectangle2D bounds, byte glyphType) + { + this.horizontal = horizontal; + this.advanceX = advanceX; + this.advanceY = advanceY; + this.bounds = bounds; + this.glyphType = glyphType; + } + + public GlyphMetrics (float advance, Rectangle2D bounds, byte glyphType) + { + this (true, advance, advance, bounds, glyphType); + } + + public float getAdvance () + { + return horizontal ? advanceX : advanceY; + } + + public float getAdvanceX () + { + return advanceX; + } + + public float getAdvanceY () + { + return advanceY; + } + + public Rectangle2D getBounds2D () + { + return bounds; + } + + public float getLSB () + { + throw new Error ("not implemented"); + } + + public float getRSB () + { + throw new Error ("not implemented"); + } + + public int getType () + { + return glyphType; + } + + public boolean isCombining () + { + return (glyphType == COMBINING); + } + + public boolean isComponent () + { + return (glyphType == COMPONENT); + } + + public boolean isLigature() + { + return (glyphType == LIGATURE); + } + + public boolean isStandard() + { + return (glyphType == STANDARD); + } + + public boolean isWhitespace() + { + return (glyphType == WHITESPACE); + } +} diff --git a/libjava/classpath/java/awt/font/GlyphVector.java b/libjava/classpath/java/awt/font/GlyphVector.java new file mode 100644 index 0000000..57e2581 --- /dev/null +++ b/libjava/classpath/java/awt/font/GlyphVector.java @@ -0,0 +1,145 @@ +/* GlyphVector.java + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.awt.Font; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +/** + * @author Michael Koch + */ +public abstract class GlyphVector implements Cloneable +{ + public static final int FLAG_COMPLEX_GLYPHS = 8; + public static final int FLAG_HAS_POSITION_ADJUSTMENTS = 2; + public static final int FLAG_HAS_TRANSFORMS = 1; + public static final int FLAG_MASK = 15; + public static final int FLAG_RUN_RTL = 4; + + /** + * Constructs a <code>GlyphVector</code> object. + */ + public GlyphVector () + { + } + + public abstract boolean equals (GlyphVector set); + + public abstract Font getFont (); + + public abstract FontRenderContext getFontRenderContext (); + + public int getGlyphCharIndex (int glyphIndex) + { + throw new Error ("not implemented"); + } + + public int[] getGlyphCharIndices (int beginGlyphIndex, int numEntries, + int[] codeReturn) + { + throw new Error ("not implemented"); + } + + public abstract int getGlyphCode (int glyphIndex); + + public abstract int[] getGlyphCodes (int beginGlyphIndex, int numEntries, + int[] codeReturn); + + public abstract GlyphJustificationInfo getGlyphJustificationInfo + (int glyphIndex); + + public abstract Shape getGlyphLogicalBounds (int glyphIndex); + + public abstract GlyphMetrics getGlyphMetrics (int glyphIndex); + + public abstract Shape getGlyphOutline (int glyphIndex); + + public Shape getGlyphOutline (int glyphIndex, float x, float y) + { + throw new Error ("not implemented"); + } + + public Rectangle getGlyphPixelBounds (int index, FontRenderContext renderFRC, + float x, float y) + { + throw new Error ("not implemented"); + } + + public abstract Point2D getGlyphPosition (int glyphIndex); + + public abstract float[] getGlyphPositions (int beginGlyphIndex, + int numEntries, + float[] positionReturn); + + public abstract AffineTransform getGlyphTransform (int glyphIndex); + + public abstract Shape getGlyphVisualBounds (int glyphIndex); + + public int getLayoutFlags () + { + throw new Error ("not implemented"); + } + + public abstract Rectangle2D getLogicalBounds (); + + public abstract int getNumGlyphs (); + + public abstract Shape getOutline (); + + public abstract Shape getOutline (float x, float y); + + public Rectangle getPixelBounds (FontRenderContext renderFRC, + float x, float y) + { + throw new Error ("not implemented"); + } + + public abstract Rectangle2D getVisualBounds (); + + public abstract void performDefaultLayout (); + + public abstract void setGlyphPosition (int glyphIndex, Point2D newPos); + + public abstract void setGlyphTransform (int glyphIndex, + AffineTransform newTX); +} diff --git a/libjava/classpath/java/awt/font/GraphicAttribute.java b/libjava/classpath/java/awt/font/GraphicAttribute.java new file mode 100644 index 0000000..79eae99 --- /dev/null +++ b/libjava/classpath/java/awt/font/GraphicAttribute.java @@ -0,0 +1,84 @@ +/* GraphicAttribute.java + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; + +/** + * @author Michael Koch + */ +public abstract class GraphicAttribute +{ + public static final int BOTTOM_ALIGNMENT = -2; + public static final int CENTER_BASELINE = 1; + public static final int HANGING_BASELINE = 2; + public static final int ROMAN_BASELINE = 0; + public static final int TOP_ALIGNMENT = -1; + + private int alignment; + + protected GraphicAttribute (int alignment) + { + this.alignment = alignment; + } + + public abstract void draw (Graphics2D graphics, float x, float y); + + public abstract float getAdvance (); + + public final int getAlignment () + { + return alignment; + } + + public abstract float getAscent (); + + public Rectangle2D getBounds () + { + throw new Error ("not implemented"); + } + + public abstract float getDescent (); + + public GlyphJustificationInfo getJustificationInfo () + { + throw new Error ("not implemented"); + } +} diff --git a/libjava/classpath/java/awt/font/ImageGraphicAttribute.java b/libjava/classpath/java/awt/font/ImageGraphicAttribute.java new file mode 100644 index 0000000..77413f9 --- /dev/null +++ b/libjava/classpath/java/awt/font/ImageGraphicAttribute.java @@ -0,0 +1,109 @@ +/* ImageGraphicAttribute.java + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.geom.Rectangle2D; + +/** + * @author Michael Koch + */ +public final class ImageGraphicAttribute extends GraphicAttribute +{ + private Image image; + + public ImageGraphicAttribute (Image image, int alignment) + { + super (alignment); + this.image = image; + } + + public ImageGraphicAttribute (Image image, int alignment, float originX, + float originY) + { + super (alignment); + this.image = image; + + throw new Error ("not implemented"); + } + + public void draw (Graphics2D graphics, float x, float y) + { + throw new Error ("not implemented"); + } + + public boolean equals (Object obj) + { + if (! (obj instanceof ImageGraphicAttribute)) + return false; + + return equals ((ImageGraphicAttribute) obj); + } + + public boolean equals (ImageGraphicAttribute rhs) + { + throw new Error ("not implemented"); + } + + public float getAdvance () + { + throw new Error ("not implemented"); + } + + public float getAscent () + { + throw new Error ("not implemented"); + } + + public Rectangle2D getBounds () + { + throw new Error ("not implemented"); + } + + public float getDescent () + { + throw new Error ("not implemented"); + } + + public int hashCode () + { + throw new Error ("not implemented"); + } +} diff --git a/libjava/classpath/java/awt/font/LineBreakMeasurer.java b/libjava/classpath/java/awt/font/LineBreakMeasurer.java new file mode 100644 index 0000000..0a6a969 --- /dev/null +++ b/libjava/classpath/java/awt/font/LineBreakMeasurer.java @@ -0,0 +1,113 @@ +/* LineBreakMeasurer.java + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.text.AttributedCharacterIterator; +import java.text.BreakIterator; + +public final class LineBreakMeasurer +{ + private AttributedCharacterIterator ci; + private FontRenderContext frc; + private BreakIterator bi; + + /** + * Constructs a <code>LineBreakMeasurer</code> object. + */ + public LineBreakMeasurer (AttributedCharacterIterator text, + FontRenderContext frc) + { + this (text, null, frc); + } + + /** + * Constructs a <code>LineBreakMeasurer</code> object. + */ + public LineBreakMeasurer (AttributedCharacterIterator text, + BreakIterator breakIter, FontRenderContext frc) + { + this.ci = text; + this.bi = breakIter; + this.frc = frc; + } + + public void deleteChar (AttributedCharacterIterator newParagraph, + int deletePos) + { + throw new Error ("not implemented"); + } + + public int getPosition () + { + return ci.getIndex (); + } + + public void insertChar (AttributedCharacterIterator newParagraph, + int insertPos) + { + throw new Error ("not implemented"); + } + + public TextLayout nextLayout (float wrappingWidth) + { + throw new Error ("not implemented"); + } + + public TextLayout nextLayout (float wrappingWidth, int offsetLimit, + boolean requireNextWord) + { + throw new Error ("not implemented"); + } + + public int nextOffset (float wrappingWidth) + { + throw new Error ("not implemented"); + } + + public int nextOffset (float wrappingWidth, int offsetLimit, + boolean requireNextWord) + { + throw new Error ("not implemented"); + } + + public void setPosition (int newPosition) + { + ci.setIndex (newPosition); + } +} diff --git a/libjava/classpath/java/awt/font/LineMetrics.java b/libjava/classpath/java/awt/font/LineMetrics.java new file mode 100644 index 0000000..3c45ad1 --- /dev/null +++ b/libjava/classpath/java/awt/font/LineMetrics.java @@ -0,0 +1,67 @@ +/* LineMetrics.java -- Information about about a line display characteristics + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +/** + * @author Michael Koch + */ +public abstract class LineMetrics +{ + public abstract float getAscent(); + + public abstract int getBaselineIndex(); + + public abstract float[] getBaselineOffsets(); + + public abstract float getDescent(); + + public abstract float getHeight(); + + public abstract float getLeading(); + + public abstract int getNumChars(); + + public abstract float getStrikethroughOffset(); + + public abstract float getStrikethroughThickness(); + + public abstract float getUnderlineOffset(); + + public abstract float getUnderlineThickness(); +} diff --git a/libjava/classpath/java/awt/font/MultipleMaster.java b/libjava/classpath/java/awt/font/MultipleMaster.java new file mode 100644 index 0000000..57417ea --- /dev/null +++ b/libjava/classpath/java/awt/font/MultipleMaster.java @@ -0,0 +1,61 @@ +/* MultipleMaster.java + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.awt.Font; + +/** + * @author Michael Koch + */ +public interface MultipleMaster +{ + Font deriveMMFont (float[] axes); + + Font deriveMMFont (float[] glyphWidths, float avgStemWidth, + float typicalCapHeight, float typicalXHeight, + float italicAngle); + + float[] getDesignAxisDefaults(); + + String[] getDesignAxisNames(); + + float[] getDesignAxisRanges(); + + int getNumDesignAxes(); +} diff --git a/libjava/classpath/java/awt/font/NumericShaper.java b/libjava/classpath/java/awt/font/NumericShaper.java new file mode 100644 index 0000000..efbdcd4 --- /dev/null +++ b/libjava/classpath/java/awt/font/NumericShaper.java @@ -0,0 +1,137 @@ +/* NumericShaper.java + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.io.Serializable; + +/** + * @author Michael Koch + * @since 1.4 + */ +public final class NumericShaper implements Serializable +{ + private static final long serialVersionUID = -8022764705923730308L; + + public static final int ALL_RANGES = 524287; + public static final int ARABIC = 2; + public static final int BENGALI = 16; + public static final int DEVANAGARI = 8; + public static final int EASTERN_ARABIC = 4; + public static final int ETHIOPIC = 65536; + public static final int EUROPEAN = 1; + public static final int GUJARATI = 64; + public static final int GURMUKHI = 32; + public static final int KANNADA = 1024; + public static final int KHMER = 131072; + public static final int LAO = 8192; + public static final int MALAYALAM = 2048; + public static final int MONGOLIAN = 262144; + public static final int MYANMAR = 32768; + public static final int ORIYA = 128; + public static final int TAMIL = 256; + public static final int TELUGU = 512; + public static final int THAI = 4096; + public static final int TIBETAN = 16384; + + private int ranges; + private int context; + + private NumericShaper (int ranges, int context) + { + this.ranges = ranges; + this.context = context; + } + + public boolean equals (Object obj) + { + if (! (obj instanceof NumericShaper)) + return false; + + NumericShaper tmp = (NumericShaper) obj; + + return (ranges == tmp.ranges + && context == tmp.context); + } + + public static NumericShaper getContextualShaper (int ranges) + { + throw new Error ("not implemented"); + } + + public static NumericShaper getContextualShaper (int ranges, + int defaultContext) + { + throw new Error ("not implemented"); + } + + public int getRanges () + { + return ranges; + } + + public static NumericShaper getShaper (int singleRange) + { + throw new Error ("not implemented"); + } + + public int hashCode () + { + throw new Error ("not implemented"); + } + + public boolean isContextual () + { + throw new Error ("not implemented"); + } + + public void shape (char[] text, int start, int count) + { + shape (text, start, count, context); + } + + public void shape (char[] text, int start, int count, int context) + { + throw new Error ("not implemented"); + } + + public String toString () + { + throw new Error ("not implemented"); + } +} diff --git a/libjava/classpath/java/awt/font/OpenType.java b/libjava/classpath/java/awt/font/OpenType.java new file mode 100644 index 0000000..ece3279 --- /dev/null +++ b/libjava/classpath/java/awt/font/OpenType.java @@ -0,0 +1,111 @@ +/* OpenType.java + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +/** + * @author Michael Koch + */ +public interface OpenType +{ + int TAG_ACNT = 1633906292; + int TAG_AVAR = 1635148146; + int TAG_BASE = 1111577413; + int TAG_BDAT = 1650745716; + int TAG_BLOC = 1651273571; + int TAG_BSLN = 1651731566; + int TAG_CFF = 1128678944; + int TAG_CMAP = 1668112752; + int TAG_CVAR = 1668702578; + int TAG_CVT = 1668707360; + int TAG_DSIG = 1146308935; + int TAG_EBDT = 1161970772; + int TAG_EBLC = 1161972803; + int TAG_EBSC = 1161974595; + int TAG_FDSC = 1717859171; + int TAG_FEAT = 1717920116; + int TAG_FMTX = 1718449272; + int TAG_FPGM = 1718642541; + int TAG_FVAR = 1719034226; + int TAG_GASP = 1734439792; + int TAG_GDEF = 1195656518; + int TAG_GLYF = 1735162214; + int TAG_GPOS = 1196445523; + int TAG_GSUB = 1196643650; + int TAG_GVAR = 1735811442; + int TAG_HDMX = 1751412088; + int TAG_HEAD = 1751474532; + int TAG_HHEA = 1751672161; + int TAG_HMTX = 1752003704; + int TAG_JSTF = 1246975046; + int TAG_JUST = 1786082164; + int TAG_KERN = 1801810542; + int TAG_LCAR = 1818452338; + int TAG_LOCA = 1819239265; + int TAG_LTSH = 1280594760; + int TAG_MAXP = 1835104368; + int TAG_MMFX = 1296909912; + int TAG_MMSD = 1296913220; + int TAG_MORT = 1836020340; + int TAG_NAME = 1851878757; + int TAG_OPBD = 1836020340; + int TAG_OS2 = 1330851634; + int TAG_PCLT = 1346587732; + int TAG_POST = 1886352244; + int TAG_PREP = 1886545264; + int TAG_PROP = 1886547824; + int TAG_TRAK = 1953653099; + int TAG_TYP1 = 1954115633; + int TAG_VDMX = 1447316824; + int TAG_VHEA = 1986553185; + int TAG_VMTX = 1986884728; + + byte[] getFontTable (int sfntTag); + + byte[] getFontTable (int sfntTag, int offset, int count); + + byte[] getFontTable (String strSfntTag); + + byte[] getFontTable (String strSfntTag, int offset, int count); + + int getFontTableSize (int sfntTag); + + int getFontTableSize (String strSfntTag); + + int getVersion (); +} diff --git a/libjava/classpath/java/awt/font/ShapeGraphicAttribute.java b/libjava/classpath/java/awt/font/ShapeGraphicAttribute.java new file mode 100644 index 0000000..6d64dec --- /dev/null +++ b/libjava/classpath/java/awt/font/ShapeGraphicAttribute.java @@ -0,0 +1,105 @@ +/* ShapeGraphicAttribute.java + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.Rectangle2D; + +public final class ShapeGraphicAttribute extends GraphicAttribute +{ + public static final boolean FILL = false; + public static final boolean STROKE = true; + + private Shape shape; + private boolean stroke; + + public ShapeGraphicAttribute (Shape shape, int alignment, boolean stroke) + { + super (alignment); + this.shape = shape; + this.stroke = stroke; + } + + public void draw (Graphics2D graphics, float x, float y) + { + throw new Error ("not implemented"); + } + + public boolean equals (Object obj) + { + if (! (obj instanceof ShapeGraphicAttribute)) + return false; + + return equals ((ShapeGraphicAttribute) obj); + } + + public boolean equals (ShapeGraphicAttribute rhs) + { + return (shape.equals (rhs.shape) + && getAlignment () == rhs.getAlignment () + && stroke == rhs.stroke); + } + + public float getAdvance () + { + throw new Error ("not implemented"); + } + + public float getAscent () + { + throw new Error ("not implemented"); + } + + public Rectangle2D getBounds () + { + return shape.getBounds2D (); + } + + public float getDescent () + { + throw new Error ("not implemented"); + } + + public int hashCode () + { + // FIXME: Check what SUN does here + return shape.hashCode (); + } +} diff --git a/libjava/classpath/java/awt/font/TextAttribute.java b/libjava/classpath/java/awt/font/TextAttribute.java new file mode 100644 index 0000000..6f5ed59 --- /dev/null +++ b/libjava/classpath/java/awt/font/TextAttribute.java @@ -0,0 +1,309 @@ +/* TextAttribute.java -- + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.io.InvalidObjectException; +import java.text.AttributedCharacterIterator; + +/** + * Attributes (and associated values) that can be used to define an + * {@link java.text.AttributedString}. + */ +public final class TextAttribute extends AttributedCharacterIterator.Attribute +{ + private static final long serialVersionUID = 7744112784117861702L; + + /** A key for the background paint attribute. */ + public static final TextAttribute BACKGROUND = + new TextAttribute("background"); + + /** A key for the BIDI_EMBEDDING attribute. */ + public static final TextAttribute BIDI_EMBEDDING = + new TextAttribute("bidi_embedding"); + + /** A key for the CHAR_REPLACEMENT attribute. */ + public static final TextAttribute CHAR_REPLACEMENT = + new TextAttribute("char_replacement"); + + /** A key for the FAMILY attribute. */ + public static final TextAttribute FAMILY = new TextAttribute("family"); + + /** A key for the font attribute. */ + public static final TextAttribute FONT = new TextAttribute("font"); + + /** A key for the foreground paint attribute. */ + public static final TextAttribute FOREGROUND = + new TextAttribute("foreground"); + + /** A key for the INPUT_METHOD_HIGHLIGHT attribute. */ + public static final TextAttribute INPUT_METHOD_HIGHLIGHT = + new TextAttribute("input method highlight"); + + /** A key for the INPUT_METHOD_UNDERLINE attribute. */ + public static final TextAttribute INPUT_METHOD_UNDERLINE = + new TextAttribute("input method underline"); + + /** A key for the text justification attribute. */ + public static final TextAttribute JUSTIFICATION = + new TextAttribute("justification"); + + /** + * A value that can be used with the {@link #JUSTIFICATION} attribute to + * indicate full justification of the text. + */ + public static final Float JUSTIFICATION_FULL = new Float(1.0); + + /** + * A value that can be used with the {@link #JUSTIFICATION} attribute to + * indicate no justification of the text. + */ + public static final Float JUSTIFICATION_NONE = new Float(0.0); + + /** A key for the NUMERIC_SHAPING attribute. */ + public static final TextAttribute NUMERIC_SHAPING = + new TextAttribute("numeric_shaping"); + + /** A key for the POSTURE attribute. */ + public static final TextAttribute POSTURE = new TextAttribute("posture"); + + /** A value that can be used with the {@link #POSTURE} attribute. */ + public static final Float POSTURE_OBLIQUE = new Float(0.2); + + /** A value that can be used with the {@link #POSTURE} attribute. */ + public static final Float POSTURE_REGULAR = new Float(0.0); + + /** A key for the RUN_DIRECTION attribute. */ + public static final TextAttribute RUN_DIRECTION = + new TextAttribute("run_direction"); + + /** A value that can be used with the {@link #RUN_DIRECTION} attribute. */ + public static final Boolean RUN_DIRECTION_LTR = Boolean.FALSE; + + /** A value that can be used with the {@link #RUN_DIRECTION} attribute. */ + public static final Boolean RUN_DIRECTION_RTL = Boolean.TRUE; + + /** A key for the text size attribute. */ + public static final TextAttribute SIZE = new TextAttribute("size"); + + /** A key for the STRIKETHROUGH attribute. */ + public static final TextAttribute STRIKETHROUGH = + new TextAttribute("strikethrough"); + + /** A value that can be used with the {@link #STRIKETHROUGH} attribute. */ + public static final Boolean STRIKETHROUGH_ON = Boolean.TRUE; + + /** A key for the SUPERSCRIPT attribute. */ + public static final TextAttribute SUPERSCRIPT = + new TextAttribute("superscript"); + + /** A value that can be used with the {@link #SUPERSCRIPT} attribute. */ + public static final Integer SUPERSCRIPT_SUB = new Integer(-1); + + /** A value that can be used with the {@link #SUPERSCRIPT} attribute. */ + public static final Integer SUPERSCRIPT_SUPER = new Integer(1); + + /** A key for the SWAP_COLORS attribute. */ + public static final TextAttribute SWAP_COLORS = + new TextAttribute("swap_colors"); + + /** A value that can be used with the {@link #SWAP_COLORS} attribute. */ + public static final Boolean SWAP_COLORS_ON = Boolean.TRUE; + + /** A key for the TRANFORM attribute. */ + public static final TextAttribute TRANSFORM = new TextAttribute("transform"); + + /** A key for the UNDERLINE attribute. */ + public static final TextAttribute UNDERLINE = new TextAttribute("underline"); + + /** A value that can be used with the {@link #UNDERLINE} attribute. */ + public static final Integer UNDERLINE_LOW_DASHED = new Integer(5); + + /** A value that can be used with the {@link #UNDERLINE} attribute. */ + public static final Integer UNDERLINE_LOW_DOTTED = new Integer(3); + + /** A value that can be used with the {@link #UNDERLINE} attribute. */ + public static final Integer UNDERLINE_LOW_GRAY = new Integer(4); + + /** A value that can be used with the {@link #UNDERLINE} attribute. */ + public static final Integer UNDERLINE_LOW_ONE_PIXEL = new Integer(1); + + /** A value that can be used with the {@link #UNDERLINE} attribute. */ + public static final Integer UNDERLINE_LOW_TWO_PIXEL = new Integer(2); + + /** A value that can be used with the {@link #UNDERLINE} attribute. */ + public static final Integer UNDERLINE_ON = new Integer(0); + + /** A key for the WEIGHT attribute. */ + public static final TextAttribute WEIGHT = new TextAttribute("weight"); + + /** A value that can be used with the {@link #WEIGHT} attribute. */ + public static final Float WEIGHT_BOLD = new Float(2.0); + + /** A value that can be used with the {@link #WEIGHT} attribute. */ + public static final Float WEIGHT_DEMIBOLD = new Float(1.75); + + /** A value that can be used with the {@link #WEIGHT} attribute. */ + public static final Float WEIGHT_DEMILIGHT = new Float(0.875); + + /** A value that can be used with the {@link #WEIGHT} attribute. */ + public static final Float WEIGHT_EXTRA_LIGHT = new Float(0.5); + + /** A value that can be used with the {@link #WEIGHT} attribute. */ + public static final Float WEIGHT_EXTRABOLD = new Float(2.5); + + /** A value that can be used with the {@link #WEIGHT} attribute. */ + public static final Float WEIGHT_HEAVY = new Float(2.25); + + /** A value that can be used with the {@link #WEIGHT} attribute. */ + public static final Float WEIGHT_LIGHT = new Float(0.75); + + /** A value that can be used with the {@link #WEIGHT} attribute. */ + public static final Float WEIGHT_MEDIUM = new Float(1.5); + + /** A value that can be used with the {@link #WEIGHT} attribute. */ + public static final Float WEIGHT_REGULAR = new Float(1.0); + + /** A value that can be used with the {@link #WEIGHT} attribute. */ + public static final Float WEIGHT_SEMIBOLD = new Float(1.25); + + /** A value that can be used with the {@link #WEIGHT} attribute. */ + public static final Float WEIGHT_ULTRABOLD = new Float(2.75); + + /** A key for the WIDTH attribute. */ + public static final TextAttribute WIDTH = new TextAttribute("width"); + + /** A value that can be used with the {@link #WIDTH} attribute. */ + public static final Float WIDTH_CONDENSED = new Float(0.75); + + /** A value that can be used with the {@link #WIDTH} attribute. */ + public static final Float WIDTH_EXTENDED = new Float(1.5); + + /** A value that can be used with the {@link #WIDTH} attribute. */ + public static final Float WIDTH_REGULAR = new Float(1.0); + + /** A value that can be used with the {@link #WIDTH} attribute. */ + public static final Float WIDTH_SEMI_CONDENSED = new Float(0.875); + + /** A value that can be used with the {@link #WIDTH} attribute. */ + public static final Float WIDTH_SEMI_EXTENDED = new Float(1.25); + + /** + * Creates a new attribute. + * + * @param name the name. + */ + protected TextAttribute(String name) + { + super(name); + } + + /** + * After deserialization, this method ensures that only one instance of + * each attribute is used. + * + * @return The (single) attribute instance. + * + * @throws InvalidObjectException if the attribute is not recognised. + */ + protected Object readResolve() + throws InvalidObjectException + { + if (this.getName().equals("background")) + return BACKGROUND; + + if (this.getName().equals("bidi_embedding")) + return BIDI_EMBEDDING; + + if (this.getName().equals("char_replacement")) + return CHAR_REPLACEMENT; + + if (this.getName().equals("family")) + return FAMILY; + + if (this.getName().equals("font")) + return FONT; + + if (this.getName().equals("foreground")) + return FOREGROUND; + + if (this.getName().equals("input method highlight")) + return INPUT_METHOD_HIGHLIGHT; + + if (this.getName().equals("input method underline")) + return INPUT_METHOD_UNDERLINE; + + if (this.getName().equals("justification")) + return JUSTIFICATION; + + if (this.getName().equals("numeric_shaping")) + return NUMERIC_SHAPING; + + if (this.getName().equals("posture")) + return POSTURE; + + if (this.getName().equals("run_direction")) + return RUN_DIRECTION; + + if (this.getName().equals("size")) + return SIZE; + + if (this.getName().equals("strikethrough")) + return STRIKETHROUGH; + + if (this.getName().equals("superscript")) + return SUPERSCRIPT; + + if (this.getName().equals("swap_colors")) + return SWAP_COLORS; + + if (this.getName().equals("transform")) + return TRANSFORM; + + if (this.getName().equals("underline")) + return UNDERLINE; + + if (this.getName().equals("weight")) + return WEIGHT; + + if (this.getName().equals("width")) + return WIDTH; + + throw new InvalidObjectException("Can't resolve Attribute: " + getName()); + } +} diff --git a/libjava/classpath/java/awt/font/TextHitInfo.java b/libjava/classpath/java/awt/font/TextHitInfo.java new file mode 100644 index 0000000..2b23e19 --- /dev/null +++ b/libjava/classpath/java/awt/font/TextHitInfo.java @@ -0,0 +1,125 @@ +/* TextHitInfo.java -- + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.font; + +/** + * @author John Leuner (jewel@debian.org) + */ +public final class TextHitInfo +{ + private int charIndex; + private boolean leadingEdge; + + TextHitInfo (int charIndex, boolean leadingEdge) + { + this.charIndex = charIndex; + this.leadingEdge = leadingEdge; + } + + public int getCharIndex() + { + return charIndex; + } + + public boolean isLeadingEdge() + { + return leadingEdge; + } + + public int getInsertionIndex() + { + return (leadingEdge ? charIndex : charIndex + 1); + } + + public int hashCode() + { + return charIndex; + } + + public boolean equals(Object obj) + { + if(obj instanceof TextHitInfo) + return this.equals((TextHitInfo) obj); + + return false; + } + + public boolean equals(TextHitInfo hitInfo) + { + return (charIndex == hitInfo.getCharIndex ()) + && (leadingEdge == hitInfo.isLeadingEdge ()); + } + + public static TextHitInfo leading(int charIndex) + { + return new TextHitInfo (charIndex, true); + } + + public static TextHitInfo trailing(int charIndex) + { + return new TextHitInfo (charIndex, false); + } + + public static TextHitInfo beforeOffset(int offset) + { + return new TextHitInfo (offset, false); + } + + public static TextHitInfo afterOffset(int offset) + { + return new TextHitInfo (offset, true); + } + + public TextHitInfo getOtherHit() + { + return (leadingEdge ? trailing (charIndex - 1) : leading (charIndex + 1)); + } + + public TextHitInfo getOffsetHit(int offset) + { + return new TextHitInfo (charIndex + offset, leadingEdge); + } + + public String toString() + { + return "TextHitInfo[" + + charIndex + + (leadingEdge ? "L" : "T" ) + + "]"; + } +} diff --git a/libjava/classpath/java/awt/font/TextLayout.java b/libjava/classpath/java/awt/font/TextLayout.java new file mode 100644 index 0000000..bb64161 --- /dev/null +++ b/libjava/classpath/java/awt/font/TextLayout.java @@ -0,0 +1,332 @@ +/* TextLayout.java -- + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import gnu.java.awt.ClasspathToolkit; +import gnu.java.awt.peer.ClasspathTextLayoutPeer; + +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.Toolkit; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.util.Map; + +/** + * @author Michael Koch + */ +public final class TextLayout implements Cloneable +{ + public static final CaretPolicy DEFAULT_CARET_POLICY = new CaretPolicy (); + ClasspathTextLayoutPeer peer; + + public static class CaretPolicy + { + public CaretPolicy () + { + // Do nothing here. + } + + public TextHitInfo getStrongCaret (TextHitInfo hit1, TextHitInfo hit2, + TextLayout layout) + { + return layout.peer.getStrongCaret(hit1, hit2); + } + } + + public TextLayout (AttributedCharacterIterator text, FontRenderContext frc) + { + AttributedString as = new AttributedString (text); + ClasspathToolkit tk = (ClasspathToolkit)(Toolkit.getDefaultToolkit ()); + peer = tk.getClasspathTextLayoutPeer(as, frc); + } + + public TextLayout (String string, Font font, FontRenderContext frc) + { + AttributedString as = new AttributedString (string); + as.addAttribute (TextAttribute.FONT, font); + ClasspathToolkit tk = (ClasspathToolkit)(Toolkit.getDefaultToolkit ()); + peer = tk.getClasspathTextLayoutPeer(as, frc); + } + + public TextLayout (String string, Map attributes, FontRenderContext frc) + { + AttributedString as = new AttributedString (string, attributes); + ClasspathToolkit tk = (ClasspathToolkit)(Toolkit.getDefaultToolkit ()); + peer = tk.getClasspathTextLayoutPeer(as, frc); + } + + protected Object clone () + { + try + { + TextLayout tl = (TextLayout) super.clone (); + tl.peer = (ClasspathTextLayoutPeer) this.peer.clone(); + return tl; + } + catch (CloneNotSupportedException e) + { + // This should never occur + throw new InternalError (); + } + } + + + public void draw (Graphics2D g2, float x, float y) + { + peer.draw(g2, x, y); + } + + public boolean equals (Object obj) + { + if (! (obj instanceof TextLayout)) + return false; + + return equals ((TextLayout) obj); + } + + public boolean equals (TextLayout tl) + { + return this.peer.equals(tl.peer); + } + + public float getAdvance () + { + return peer.getAdvance(); + } + + public float getAscent () + { + return peer.getAscent(); + } + + public byte getBaseline () + { + return peer.getBaseline(); + } + + public float[] getBaselineOffsets () + { + return peer.getBaselineOffsets(); + } + + public Shape getBlackBoxBounds (int firstEndpoint, int secondEndpoint) + { + return peer.getBlackBoxBounds(firstEndpoint, secondEndpoint); + } + + public Rectangle2D getBounds() + { + return peer.getBounds(); + } + + public float[] getCaretInfo (TextHitInfo hit) + { + return getCaretInfo(hit, getBounds()); + } + + public float[] getCaretInfo (TextHitInfo hit, Rectangle2D bounds) + { + return peer.getCaretInfo(hit, bounds); + } + + public Shape getCaretShape (TextHitInfo hit) + { + return getCaretShape(hit, getBounds()); + } + + public Shape getCaretShape (TextHitInfo hit, Rectangle2D bounds) + { + return peer.getCaretShape(hit, bounds); + } + + public Shape[] getCaretShapes (int offset) + { + return getCaretShapes(offset, getBounds()); + } + + public Shape[] getCaretShapes (int offset, Rectangle2D bounds) + { + return getCaretShapes(offset, getBounds(), DEFAULT_CARET_POLICY); + } + + public Shape[] getCaretShapes (int offset, Rectangle2D bounds, + TextLayout.CaretPolicy policy) + { + return peer.getCaretShapes(offset, bounds, policy); + } + + public int getCharacterCount () + { + return peer.getCharacterCount(); + } + + public byte getCharacterLevel (int index) + { + return peer.getCharacterLevel(index); + } + + public float getDescent () + { + return peer.getDescent(); + } + + public TextLayout getJustifiedLayout (float justificationWidth) + { + return peer.getJustifiedLayout(justificationWidth); + } + + public float getLeading () + { + return peer.getLeading(); + } + + public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint) + { + return getLogicalHighlightShape (firstEndpoint, secondEndpoint, getBounds()); + } + + public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint, + Rectangle2D bounds) + { + return peer.getLogicalHighlightShape(firstEndpoint, secondEndpoint, bounds); + } + + public int[] getLogicalRangesForVisualSelection (TextHitInfo firstEndpoint, + TextHitInfo secondEndpoint) + { + return peer.getLogicalRangesForVisualSelection(firstEndpoint, secondEndpoint); + } + + public TextHitInfo getNextLeftHit (int offset) + { + return getNextLeftHit(offset, DEFAULT_CARET_POLICY); + } + + public TextHitInfo getNextLeftHit (int offset, TextLayout.CaretPolicy policy) + { + return peer.getNextLeftHit(offset, policy); + } + + public TextHitInfo getNextLeftHit (TextHitInfo hit) + { + return getNextLeftHit(hit.getCharIndex()); + } + + public TextHitInfo getNextRightHit (int offset) + { + return getNextRightHit(offset, DEFAULT_CARET_POLICY); + } + + public TextHitInfo getNextRightHit (int offset, TextLayout.CaretPolicy policy) + { + return peer.getNextRightHit(offset, policy); + } + + public TextHitInfo getNextRightHit (TextHitInfo hit) + { + return getNextRightHit(hit.getCharIndex()); + } + + public Shape getOutline (AffineTransform tx) + { + return peer.getOutline(tx); + } + + public float getVisibleAdvance () + { + return peer.getVisibleAdvance(); + } + + public Shape getVisualHighlightShape (TextHitInfo firstEndpoint, + TextHitInfo secondEndpoint) + { + return getVisualHighlightShape(firstEndpoint, secondEndpoint, getBounds()); + } + + public Shape getVisualHighlightShape (TextHitInfo firstEndpoint, + TextHitInfo secondEndpoint, + Rectangle2D bounds) + { + return peer.getVisualHighlightShape(firstEndpoint, secondEndpoint, bounds); + } + + public TextHitInfo getVisualOtherHit (TextHitInfo hit) + { + return peer.getVisualOtherHit(hit); + } + + protected void handleJustify (float justificationWidth) + { + peer.handleJustify(justificationWidth); + } + + public int hashCode () + { + return peer.hashCode(); + } + + public TextHitInfo hitTestChar (float x, float y) + { + return hitTestChar(x, y, getBounds()); + } + + public TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds) + { + return peer.hitTestChar(x, y, bounds); + } + + public boolean isLeftToRight () + { + return peer.isLeftToRight(); + } + + public boolean isVertical () + { + return peer.isVertical(); + } + + public String toString () + { + return peer.toString(); + } +} diff --git a/libjava/classpath/java/awt/font/TextMeasurer.java b/libjava/classpath/java/awt/font/TextMeasurer.java new file mode 100644 index 0000000..7fcdc87 --- /dev/null +++ b/libjava/classpath/java/awt/font/TextMeasurer.java @@ -0,0 +1,97 @@ +/* TextMeasurer.java + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.text.AttributedCharacterIterator; + +/** + * @author Michael Koch + * @since 1.3 + */ +public final class TextMeasurer implements Cloneable +{ + private AttributedCharacterIterator ci; + private FontRenderContext frc; + + public TextMeasurer (AttributedCharacterIterator text, FontRenderContext frc) + { + this.ci = text; + this.frc = frc; + } + + protected Object clone () + { + try + { + return super.clone (); + } + catch (CloneNotSupportedException e) + { + // This may never occur + throw new InternalError (); + } + } + + public void deleteChar (AttributedCharacterIterator newParagraph, + int deletePos) + { + throw new Error ("not implemented"); + } + + public float getAdvanceBetween (int start, int limit) + { + throw new Error ("not implemented"); + } + + public TextLayout getLayout (int start, int limit) + { + throw new Error ("not implemented"); + } + + public int getLineBreakIndex (int start, float maxAdvance) + { + throw new Error ("not implemented"); + } + + public void insertChar (AttributedCharacterIterator newParagraph, + int insertPos) + { + throw new Error ("not implemented"); + } +} diff --git a/libjava/classpath/java/awt/font/TransformAttribute.java b/libjava/classpath/java/awt/font/TransformAttribute.java new file mode 100644 index 0000000..977cafa --- /dev/null +++ b/libjava/classpath/java/awt/font/TransformAttribute.java @@ -0,0 +1,100 @@ +/* TransformAttribute.java -- + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.font; + +import java.awt.geom.AffineTransform; +import java.io.Serializable; + +/** + * This class provides a mechanism for using an {@link AffineTransform} as + * an <i>immutable</i> attribute (for example, in the + * {@link java.text.AttributedString} class). Any transform passed to + * this class is copied before being stored, and any transform handed out + * by this class is a copy of the stored transform. In this way, it is + * not possible to modify the stored transform. + * + * @author Michael Koch + */ +public final class TransformAttribute implements Serializable +{ + private static final long serialVersionUID = 3356247357827709530L; + + private AffineTransform affineTransform; + + /** + * Creates a new attribute that contains a copy of the given transform. + * + * @param transform the transform (<code>null</code> not permitted). + * + * @throws IllegalArgumentException if <code>transform</code> is + * <code>null</code>. + */ + public TransformAttribute (AffineTransform transform) + { + if (transform == null) + { + throw new IllegalArgumentException("Null 'transform' not permitted."); + } + this.affineTransform = new AffineTransform (transform); + } + + /** + * Returns a copy of the transform contained by this attribute. + * + * @return A copy of the transform. + */ + public AffineTransform getTransform () + { + return (AffineTransform) affineTransform.clone(); + } + + /** + * Returns <code>true</code> if the transform contained by this attribute is + * an identity transform, and <code>false</code> otherwise. + * + * @return <code>true</code> if the transform contained by this attribute is + * an identity transform, and <code>false</code> otherwise. + * + * @since 1.4 + */ + public boolean isIdentity () + { + return (affineTransform == null ? false : affineTransform.isIdentity ()); + } +} diff --git a/libjava/classpath/java/awt/font/package.html b/libjava/classpath/java/awt/font/package.html new file mode 100644 index 0000000..8c3c61a --- /dev/null +++ b/libjava/classpath/java/awt/font/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.font package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.font</title></head> + +<body> +<p>Representations of different kind of characters and fonts.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/geom/AffineTransform.java b/libjava/classpath/java/awt/geom/AffineTransform.java new file mode 100644 index 0000000..4d1a4d6 --- /dev/null +++ b/libjava/classpath/java/awt/geom/AffineTransform.java @@ -0,0 +1,1487 @@ +/* AffineTransform.java -- transform coordinates between two 2-D spaces + Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.geom; + +import java.awt.Shape; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; + +/** + * This class represents an affine transformation between two coordinate + * spaces in 2 dimensions. Such a transform preserves the "straightness" + * and "parallelness" of lines. The transform is built from a sequence of + * translations, scales, flips, rotations, and shears. + * + * <p>The transformation can be represented using matrix math on a 3x3 array. + * Given (x,y), the transformation (x',y') can be found by: + * <pre> + * [ x'] [ m00 m01 m02 ] [ x ] [ m00*x + m01*y + m02 ] + * [ y'] = [ m10 m11 m12 ] [ y ] = [ m10*x + m11*y + m12 ] + * [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ] + * </pre> + * The bottom row of the matrix is constant, so a transform can be uniquely + * represented (as in {@link #toString()}) by + * "[[m00, m01, m02], [m10, m11, m12]]". + * + * @author Tom Tromey (tromey@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status partially updated to 1.4, still has some problems + */ +public class AffineTransform implements Cloneable, Serializable +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 1330973210523860834L; + + /** + * The transformation is the identity (x' = x, y' = y). All other transforms + * have either a combination of the appropriate transform flag bits for + * their type, or the type GENERAL_TRANSFORM. + * + * @see #TYPE_TRANSLATION + * @see #TYPE_UNIFORM_SCALE + * @see #TYPE_GENERAL_SCALE + * @see #TYPE_FLIP + * @see #TYPE_QUADRANT_ROTATION + * @see #TYPE_GENERAL_ROTATION + * @see #TYPE_GENERAL_TRANSFORM + * @see #getType() + */ + public static final int TYPE_IDENTITY = 0; + + /** + * The transformation includes a translation - shifting in the x or y + * direction without changing length or angles. + * + * @see #TYPE_IDENTITY + * @see #TYPE_UNIFORM_SCALE + * @see #TYPE_GENERAL_SCALE + * @see #TYPE_FLIP + * @see #TYPE_QUADRANT_ROTATION + * @see #TYPE_GENERAL_ROTATION + * @see #TYPE_GENERAL_TRANSFORM + * @see #getType() + */ + public static final int TYPE_TRANSLATION = 1; + + /** + * The transformation includes a uniform scale - length is scaled in both + * the x and y directions by the same amount, without affecting angles. + * This is mutually exclusive with TYPE_GENERAL_SCALE. + * + * @see #TYPE_IDENTITY + * @see #TYPE_TRANSLATION + * @see #TYPE_GENERAL_SCALE + * @see #TYPE_FLIP + * @see #TYPE_QUADRANT_ROTATION + * @see #TYPE_GENERAL_ROTATION + * @see #TYPE_GENERAL_TRANSFORM + * @see #TYPE_MASK_SCALE + * @see #getType() + */ + public static final int TYPE_UNIFORM_SCALE = 2; + + /** + * The transformation includes a general scale - length is scaled in either + * or both the x and y directions, but by different amounts; without + * affecting angles. This is mutually exclusive with TYPE_UNIFORM_SCALE. + * + * @see #TYPE_IDENTITY + * @see #TYPE_TRANSLATION + * @see #TYPE_UNIFORM_SCALE + * @see #TYPE_FLIP + * @see #TYPE_QUADRANT_ROTATION + * @see #TYPE_GENERAL_ROTATION + * @see #TYPE_GENERAL_TRANSFORM + * @see #TYPE_MASK_SCALE + * @see #getType() + */ + public static final int TYPE_GENERAL_SCALE = 4; + + /** + * This constant checks if either variety of scale transform is performed. + * + * @see #TYPE_UNIFORM_SCALE + * @see #TYPE_GENERAL_SCALE + */ + public static final int TYPE_MASK_SCALE = 6; + + /** + * The transformation includes a flip about an axis, swapping between + * right-handed and left-handed coordinate systems. In a right-handed + * system, the positive x-axis rotates counter-clockwise to the positive + * y-axis; in a left-handed system it rotates clockwise. + * + * @see #TYPE_IDENTITY + * @see #TYPE_TRANSLATION + * @see #TYPE_UNIFORM_SCALE + * @see #TYPE_GENERAL_SCALE + * @see #TYPE_QUADRANT_ROTATION + * @see #TYPE_GENERAL_ROTATION + * @see #TYPE_GENERAL_TRANSFORM + * @see #getType() + */ + public static final int TYPE_FLIP = 64; + + /** + * The transformation includes a rotation of a multiple of 90 degrees (PI/2 + * radians). Angles are rotated, but length is preserved. This is mutually + * exclusive with TYPE_GENERAL_ROTATION. + * + * @see #TYPE_IDENTITY + * @see #TYPE_TRANSLATION + * @see #TYPE_UNIFORM_SCALE + * @see #TYPE_GENERAL_SCALE + * @see #TYPE_FLIP + * @see #TYPE_GENERAL_ROTATION + * @see #TYPE_GENERAL_TRANSFORM + * @see #TYPE_MASK_ROTATION + * @see #getType() + */ + public static final int TYPE_QUADRANT_ROTATION = 8; + + /** + * The transformation includes a rotation by an arbitrary angle. Angles are + * rotated, but length is preserved. This is mutually exclusive with + * TYPE_QUADRANT_ROTATION. + * + * @see #TYPE_IDENTITY + * @see #TYPE_TRANSLATION + * @see #TYPE_UNIFORM_SCALE + * @see #TYPE_GENERAL_SCALE + * @see #TYPE_FLIP + * @see #TYPE_QUADRANT_ROTATION + * @see #TYPE_GENERAL_TRANSFORM + * @see #TYPE_MASK_ROTATION + * @see #getType() + */ + public static final int TYPE_GENERAL_ROTATION = 16; + + /** + * This constant checks if either variety of rotation is performed. + * + * @see #TYPE_QUADRANT_ROTATION + * @see #TYPE_GENERAL_ROTATION + */ + public static final int TYPE_MASK_ROTATION = 24; + + /** + * The transformation is an arbitrary conversion of coordinates which + * could not be decomposed into the other TYPEs. + * + * @see #TYPE_IDENTITY + * @see #TYPE_TRANSLATION + * @see #TYPE_UNIFORM_SCALE + * @see #TYPE_GENERAL_SCALE + * @see #TYPE_FLIP + * @see #TYPE_QUADRANT_ROTATION + * @see #TYPE_GENERAL_ROTATION + * @see #getType() + */ + public static final int TYPE_GENERAL_TRANSFORM = 32; + + /** + * The X coordinate scaling element of the transform matrix. + * + * @serial matrix[0,0] + */ + private double m00; + + /** + * The Y coordinate shearing element of the transform matrix. + * + * @serial matrix[1,0] + */ + private double m10; + + /** + * The X coordinate shearing element of the transform matrix. + * + * @serial matrix[0,1] + */ + private double m01; + + /** + * The Y coordinate scaling element of the transform matrix. + * + * @serial matrix[1,1] + */ + private double m11; + + /** + * The X coordinate translation element of the transform matrix. + * + * @serial matrix[0,2] + */ + private double m02; + + /** + * The Y coordinate translation element of the transform matrix. + * + * @serial matrix[1,2] + */ + private double m12; + + /** The type of this transform. */ + private transient int type; + + /** + * Construct a new identity transform: + * <pre> + * [ 1 0 0 ] + * [ 0 1 0 ] + * [ 0 0 1 ] + * </pre> + */ + public AffineTransform() + { + m00 = m11 = 1; + } + + /** + * Create a new transform which copies the given one. + * + * @param tx the transform to copy + * @throws NullPointerException if tx is null + */ + public AffineTransform(AffineTransform tx) + { + setTransform(tx); + } + + /** + * Construct a transform with the given matrix entries: + * <pre> + * [ m00 m01 m02 ] + * [ m10 m11 m12 ] + * [ 0 0 1 ] + * </pre> + * + * @param m00 the x scaling component + * @param m10 the y shearing component + * @param m01 the x shearing component + * @param m11 the y scaling component + * @param m02 the x translation component + * @param m12 the y translation component + */ + public AffineTransform(float m00, float m10, + float m01, float m11, + float m02, float m12) + { + this.m00 = m00; + this.m10 = m10; + this.m01 = m01; + this.m11 = m11; + this.m02 = m02; + this.m12 = m12; + updateType(); + } + + /** + * Construct a transform from a sequence of float entries. The array must + * have at least 4 entries, which has a translation factor of 0; or 6 + * entries, for specifying all parameters: + * <pre> + * [ f[0] f[2] (f[4]) ] + * [ f[1] f[3] (f[5]) ] + * [ 0 0 1 ] + * </pre> + * + * @param f the matrix to copy from, with at least 4 (6) entries + * @throws NullPointerException if f is null + * @throws ArrayIndexOutOfBoundsException if f is too small + */ + public AffineTransform(float[] f) + { + m00 = f[0]; + m10 = f[1]; + m01 = f[2]; + m11 = f[3]; + if (f.length >= 6) + { + m02 = f[4]; + m12 = f[5]; + } + updateType(); + } + + /** + * Construct a transform with the given matrix entries: + * <pre> + * [ m00 m01 m02 ] + * [ m10 m11 m12 ] + * [ 0 0 1 ] + * </pre> + * + * @param m00 the x scaling component + * @param m10 the y shearing component + * @param m01 the x shearing component + * @param m11 the y scaling component + * @param m02 the x translation component + * @param m12 the y translation component + */ + public AffineTransform(double m00, double m10, double m01, + double m11, double m02, double m12) + { + this.m00 = m00; + this.m10 = m10; + this.m01 = m01; + this.m11 = m11; + this.m02 = m02; + this.m12 = m12; + updateType(); + } + + /** + * Construct a transform from a sequence of double entries. The array must + * have at least 4 entries, which has a translation factor of 0; or 6 + * entries, for specifying all parameters: + * <pre> + * [ d[0] d[2] (d[4]) ] + * [ d[1] d[3] (d[5]) ] + * [ 0 0 1 ] + * </pre> + * + * @param d the matrix to copy from, with at least 4 (6) entries + * @throws NullPointerException if d is null + * @throws ArrayIndexOutOfBoundsException if d is too small + */ + public AffineTransform(double[] d) + { + m00 = d[0]; + m10 = d[1]; + m01 = d[2]; + m11 = d[3]; + if (d.length >= 6) + { + m02 = d[4]; + m12 = d[5]; + } + updateType(); + } + + /** + * Returns a translation transform: + * <pre> + * [ 1 0 tx ] + * [ 0 1 ty ] + * [ 0 0 1 ] + * </pre> + * + * @param tx the x translation distance + * @param ty the y translation distance + * @return the translating transform + */ + public static AffineTransform getTranslateInstance(double tx, double ty) + { + AffineTransform t = new AffineTransform(); + t.setToTranslation(tx, ty); + return t; + } + + /** + * Returns a rotation transform. A positive angle (in radians) rotates + * the positive x-axis to the positive y-axis: + * <pre> + * [ cos(theta) -sin(theta) 0 ] + * [ sin(theta) cos(theta) 0 ] + * [ 0 0 1 ] + * </pre> + * + * @param theta the rotation angle + * @return the rotating transform + */ + public static AffineTransform getRotateInstance(double theta) + { + AffineTransform t = new AffineTransform(); + t.setToRotation(theta); + return t; + } + + /** + * Returns a rotation transform about a point. A positive angle (in radians) + * rotates the positive x-axis to the positive y-axis. This is the same + * as calling: + * <pre> + * AffineTransform tx = new AffineTransform(); + * tx.setToTranslation(x, y); + * tx.rotate(theta); + * tx.translate(-x, -y); + * </pre> + * + * <p>The resulting matrix is: + * <pre> + * [ cos(theta) -sin(theta) x-x*cos+y*sin ] + * [ sin(theta) cos(theta) y-x*sin-y*cos ] + * [ 0 0 1 ] + * </pre> + * + * @param theta the rotation angle + * @param x the x coordinate of the pivot point + * @param y the y coordinate of the pivot point + * @return the rotating transform + */ + public static AffineTransform getRotateInstance(double theta, + double x, double y) + { + AffineTransform t = new AffineTransform(); + t.setToTranslation(x, y); + t.rotate(theta); + t.translate(-x, -y); + return t; + } + + /** + * Returns a scaling transform: + * <pre> + * [ sx 0 0 ] + * [ 0 sy 0 ] + * [ 0 0 1 ] + * </pre> + * + * @param sx the x scaling factor + * @param sy the y scaling factor + * @return the scaling transform + */ + public static AffineTransform getScaleInstance(double sx, double sy) + { + AffineTransform t = new AffineTransform(); + t.setToScale(sx, sy); + return t; + } + + /** + * Returns a shearing transform (points are shifted in the x direction based + * on a factor of their y coordinate, and in the y direction as a factor of + * their x coordinate): + * <pre> + * [ 1 shx 0 ] + * [ shy 1 0 ] + * [ 0 0 1 ] + * </pre> + * + * @param shx the x shearing factor + * @param shy the y shearing factor + * @return the shearing transform + */ + public static AffineTransform getShearInstance(double shx, double shy) + { + AffineTransform t = new AffineTransform(); + t.setToShear(shx, shy); + return t; + } + + /** + * Returns the type of this transform. The result is always valid, although + * it may not be the simplest interpretation (in other words, there are + * sequences of transforms which reduce to something simpler, which this + * does not always detect). The result is either TYPE_GENERAL_TRANSFORM, + * or a bit-wise combination of TYPE_TRANSLATION, the mutually exclusive + * TYPE_*_ROTATIONs, and the mutually exclusive TYPE_*_SCALEs. + * + * @return The type. + * + * @see #TYPE_IDENTITY + * @see #TYPE_TRANSLATION + * @see #TYPE_UNIFORM_SCALE + * @see #TYPE_GENERAL_SCALE + * @see #TYPE_QUADRANT_ROTATION + * @see #TYPE_GENERAL_ROTATION + * @see #TYPE_GENERAL_TRANSFORM + */ + public int getType() + { + return type; + } + + /** + * Return the determinant of this transform matrix. If the determinant is + * non-zero, the transform is invertible; otherwise operations which require + * an inverse throw a NoninvertibleTransformException. A result very near + * zero, due to rounding errors, may indicate that inversion results do not + * carry enough precision to be meaningful. + * + * <p>If this is a uniform scale transformation, the determinant also + * represents the squared value of the scale. Otherwise, it carries little + * additional meaning. The determinant is calculated as: + * <pre> + * | m00 m01 m02 | + * | m10 m11 m12 | = m00 * m11 - m01 * m10 + * | 0 0 1 | + * </pre> + * + * @return the determinant + * @see #createInverse() + */ + public double getDeterminant() + { + return m00 * m11 - m01 * m10; + } + + /** + * Return the matrix of values used in this transform. If the matrix has + * fewer than 6 entries, only the scale and shear factors are returned; + * otherwise the translation factors are copied as well. The resulting + * values are: + * <pre> + * [ d[0] d[2] (d[4]) ] + * [ d[1] d[3] (d[5]) ] + * [ 0 0 1 ] + * </pre> + * + * @param d the matrix to store the results into; with 4 (6) entries + * @throws NullPointerException if d is null + * @throws ArrayIndexOutOfBoundsException if d is too small + */ + public void getMatrix(double[] d) + { + d[0] = m00; + d[1] = m10; + d[2] = m01; + d[3] = m11; + if (d.length >= 6) + { + d[4] = m02; + d[5] = m12; + } + } + + /** + * Returns the X coordinate scaling factor of the matrix. + * + * @return m00 + * @see #getMatrix(double[]) + */ + public double getScaleX() + { + return m00; + } + + /** + * Returns the Y coordinate scaling factor of the matrix. + * + * @return m11 + * @see #getMatrix(double[]) + */ + public double getScaleY() + { + return m11; + } + + /** + * Returns the X coordinate shearing factor of the matrix. + * + * @return m01 + * @see #getMatrix(double[]) + */ + public double getShearX() + { + return m01; + } + + /** + * Returns the Y coordinate shearing factor of the matrix. + * + * @return m10 + * @see #getMatrix(double[]) + */ + public double getShearY() + { + return m10; + } + + /** + * Returns the X coordinate translation factor of the matrix. + * + * @return m02 + * @see #getMatrix(double[]) + */ + public double getTranslateX() + { + return m02; + } + + /** + * Returns the Y coordinate translation factor of the matrix. + * + * @return m12 + * @see #getMatrix(double[]) + */ + public double getTranslateY() + { + return m12; + } + + /** + * Concatenate a translation onto this transform. This is equivalent, but + * more efficient than + * <code>concatenate(AffineTransform.getTranslateInstance(tx, ty))</code>. + * + * @param tx the x translation distance + * @param ty the y translation distance + * @see #getTranslateInstance(double, double) + * @see #concatenate(AffineTransform) + */ + public void translate(double tx, double ty) + { + m02 += tx * m00 + ty * m01; + m12 += tx * m10 + ty * m11; + updateType(); + } + + /** + * Concatenate a rotation onto this transform. This is equivalent, but + * more efficient than + * <code>concatenate(AffineTransform.getRotateInstance(theta))</code>. + * + * @param theta the rotation angle + * @see #getRotateInstance(double) + * @see #concatenate(AffineTransform) + */ + public void rotate(double theta) + { + double c = Math.cos(theta); + double s = Math.sin(theta); + double n00 = m00 * c + m01 * s; + double n01 = m00 * -s + m01 * c; + double n10 = m10 * c + m11 * s; + double n11 = m10 * -s + m11 * c; + m00 = n00; + m01 = n01; + m10 = n10; + m11 = n11; + updateType(); + } + + /** + * Concatenate a rotation about a point onto this transform. This is + * equivalent, but more efficient than + * <code>concatenate(AffineTransform.getRotateInstance(theta, x, y))</code>. + * + * @param theta the rotation angle + * @param x the x coordinate of the pivot point + * @param y the y coordinate of the pivot point + * @see #getRotateInstance(double, double, double) + * @see #concatenate(AffineTransform) + */ + public void rotate(double theta, double x, double y) + { + translate(x, y); + rotate(theta); + translate(-x, -y); + } + + /** + * Concatenate a scale onto this transform. This is equivalent, but more + * efficient than + * <code>concatenate(AffineTransform.getScaleInstance(sx, sy))</code>. + * + * @param sx the x scaling factor + * @param sy the y scaling factor + * @see #getScaleInstance(double, double) + * @see #concatenate(AffineTransform) + */ + public void scale(double sx, double sy) + { + m00 *= sx; + m01 *= sy; + m10 *= sx; + m11 *= sy; + updateType(); + } + + /** + * Concatenate a shearing onto this transform. This is equivalent, but more + * efficient than + * <code>concatenate(AffineTransform.getShearInstance(sx, sy))</code>. + * + * @param shx the x shearing factor + * @param shy the y shearing factor + * @see #getShearInstance(double, double) + * @see #concatenate(AffineTransform) + */ + public void shear(double shx, double shy) + { + double n00 = m00 + (shy * m01); + double n01 = m01 + (shx * m00); + double n10 = m10 + (shy * m11); + double n11 = m11 + (shx * m10); + m00 = n00; + m01 = n01; + m10 = n10; + m11 = n11; + updateType(); + } + + /** + * Reset this transform to the identity (no transformation): + * <pre> + * [ 1 0 0 ] + * [ 0 1 0 ] + * [ 0 0 1 ] + * </pre> + */ + public void setToIdentity() + { + m00 = m11 = 1; + m01 = m02 = m10 = m12 = 0; + type = TYPE_IDENTITY; + } + + /** + * Set this transform to a translation: + * <pre> + * [ 1 0 tx ] + * [ 0 1 ty ] + * [ 0 0 1 ] + * </pre> + * + * @param tx the x translation distance + * @param ty the y translation distance + */ + public void setToTranslation(double tx, double ty) + { + m00 = m11 = 1; + m01 = m10 = 0; + m02 = tx; + m12 = ty; + type = (tx == 0 && ty == 0) ? TYPE_UNIFORM_SCALE : TYPE_TRANSLATION; + } + + /** + * Set this transform to a rotation. A positive angle (in radians) rotates + * the positive x-axis to the positive y-axis: + * <pre> + * [ cos(theta) -sin(theta) 0 ] + * [ sin(theta) cos(theta) 0 ] + * [ 0 0 1 ] + * </pre> + * + * @param theta the rotation angle + */ + public void setToRotation(double theta) + { + double c = Math.cos(theta); + double s = Math.sin(theta); + m00 = c; + m01 = -s; + m02 = 0; + m10 = s; + m11 = c; + m12 = 0; + type = (c == 1 ? TYPE_IDENTITY + : c == 0 || c == -1 ? TYPE_QUADRANT_ROTATION + : TYPE_GENERAL_ROTATION); + } + + /** + * Set this transform to a rotation about a point. A positive angle (in + * radians) rotates the positive x-axis to the positive y-axis. This is the + * same as calling: + * <pre> + * tx.setToTranslation(x, y); + * tx.rotate(theta); + * tx.translate(-x, -y); + * </pre> + * + * <p>The resulting matrix is: + * <pre> + * [ cos(theta) -sin(theta) x-x*cos+y*sin ] + * [ sin(theta) cos(theta) y-x*sin-y*cos ] + * [ 0 0 1 ] + * </pre> + * + * @param theta the rotation angle + * @param x the x coordinate of the pivot point + * @param y the y coordinate of the pivot point + */ + public void setToRotation(double theta, double x, double y) + { + double c = Math.cos(theta); + double s = Math.sin(theta); + m00 = c; + m01 = -s; + m02 = x - x * c + y * s; + m10 = s; + m11 = c; + m12 = y - x * s - y * c; + updateType(); + } + + /** + * Set this transform to a scale: + * <pre> + * [ sx 0 0 ] + * [ 0 sy 0 ] + * [ 0 0 1 ] + * </pre> + * + * @param sx the x scaling factor + * @param sy the y scaling factor + */ + public void setToScale(double sx, double sy) + { + m00 = sx; + m01 = m02 = m10 = m12 = 0; + m11 = sy; + type = (sx != sy ? TYPE_GENERAL_SCALE + : sx == 1 ? TYPE_IDENTITY : TYPE_UNIFORM_SCALE); + } + + /** + * Set this transform to a shear (points are shifted in the x direction based + * on a factor of their y coordinate, and in the y direction as a factor of + * their x coordinate): + * <pre> + * [ 1 shx 0 ] + * [ shy 1 0 ] + * [ 0 0 1 ] + * </pre> + * + * @param shx the x shearing factor + * @param shy the y shearing factor + */ + public void setToShear(double shx, double shy) + { + m00 = m11 = 1; + m01 = shx; + m10 = shy; + m02 = m12 = 0; + updateType(); + } + + /** + * Set this transform to a copy of the given one. + * + * @param tx the transform to copy + * @throws NullPointerException if tx is null + */ + public void setTransform(AffineTransform tx) + { + m00 = tx.m00; + m01 = tx.m01; + m02 = tx.m02; + m10 = tx.m10; + m11 = tx.m11; + m12 = tx.m12; + type = tx.type; + } + + /** + * Set this transform to the given values: + * <pre> + * [ m00 m01 m02 ] + * [ m10 m11 m12 ] + * [ 0 0 1 ] + * </pre> + * + * @param m00 the x scaling component + * @param m10 the y shearing component + * @param m01 the x shearing component + * @param m11 the y scaling component + * @param m02 the x translation component + * @param m12 the y translation component + */ + public void setTransform(double m00, double m10, double m01, + double m11, double m02, double m12) + { + this.m00 = m00; + this.m10 = m10; + this.m01 = m01; + this.m11 = m11; + this.m02 = m02; + this.m12 = m12; + updateType(); + } + + /** + * Set this transform to the result of performing the original version of + * this followed by tx. This is commonly used when chaining transformations + * from one space to another. In matrix form: + * <pre> + * [ this ] = [ this ] x [ tx ] + * </pre> + * + * @param tx the transform to concatenate + * @throws NullPointerException if tx is null + * @see #preConcatenate(AffineTransform) + */ + public void concatenate(AffineTransform tx) + { + double n00 = m00 * tx.m00 + m01 * tx.m10; + double n01 = m00 * tx.m01 + m01 * tx.m11; + double n02 = m00 * tx.m02 + m01 * tx.m12 + m02; + double n10 = m10 * tx.m00 + m11 * tx.m10; + double n11 = m10 * tx.m01 + m11 * tx.m11; + double n12 = m10 * tx.m02 + m11 * tx.m12 + m12; + m00 = n00; + m01 = n01; + m02 = n02; + m10 = n10; + m11 = n11; + m12 = n12; + updateType(); + } + + /** + * Set this transform to the result of performing tx followed by the + * original version of this. This is less common than normal concatenation, + * but can still be used to chain transformations from one space to another. + * In matrix form: + * <pre> + * [ this ] = [ tx ] x [ this ] + * </pre> + * + * @param tx the transform to concatenate + * @throws NullPointerException if tx is null + * @see #concatenate(AffineTransform) + */ + public void preConcatenate(AffineTransform tx) + { + double n00 = tx.m00 * m00 + tx.m01 * m10; + double n01 = tx.m00 * m01 + tx.m01 * m11; + double n02 = tx.m00 * m02 + tx.m01 * m12 + tx.m02; + double n10 = tx.m10 * m00 + tx.m11 * m10; + double n11 = tx.m10 * m01 + tx.m11 * m11; + double n12 = tx.m10 * m02 + tx.m11 * m12 + tx.m12; + m00 = n00; + m01 = n01; + m02 = n02; + m10 = n10; + m11 = n11; + m12 = n12; + updateType(); + } + + /** + * Returns a transform, which if concatenated to this one, will result in + * the identity transform. This is useful for undoing transformations, but + * is only possible if the original transform has an inverse (ie. does not + * map multiple points to the same line or point). A transform exists only + * if getDeterminant() has a non-zero value. + * + * The inverse is calculated as: + * + * <pre> + * + * Let A be the matrix for which we want to find the inverse: + * + * A = [ m00 m01 m02 ] + * [ m10 m11 m12 ] + * [ 0 0 1 ] + * + * + * 1 + * inverse (A) = --- x adjoint(A) + * det + * + * + * + * = 1 [ m11 -m01 m01*m12-m02*m11 ] + * --- x [ -m10 m00 -m00*m12+m10*m02 ] + * det [ 0 0 m00*m11-m10*m01 ] + * + * + * + * = [ m11/det -m01/det m01*m12-m02*m11/det ] + * [ -m10/det m00/det -m00*m12+m10*m02/det ] + * [ 0 0 1 ] + * + * + * </pre> + * + * + * + * @return a new inverse transform + * @throws NoninvertibleTransformException if inversion is not possible + * @see #getDeterminant() + */ + public AffineTransform createInverse() + throws NoninvertibleTransformException + { + double det = getDeterminant(); + if (det == 0) + throw new NoninvertibleTransformException("can't invert transform"); + + double im00 = m11 / det; + double im10 = -m10 / det; + double im01 = -m01 / det; + double im11 = m00 / det; + double im02 = (m01 * m12 - m02 * m11) / det; + double im12 = (-m00 * m12 + m10 * m02) / det; + + return new AffineTransform (im00, im10, im01, im11, im02, im12); + } + + /** + * Perform this transformation on the given source point, and store the + * result in the destination (creating it if necessary). It is safe for + * src and dst to be the same. + * + * @param src the source point + * @param dst the destination, or null + * @return the transformation of src, in dst if it was non-null + * @throws NullPointerException if src is null + */ + public Point2D transform(Point2D src, Point2D dst) + { + if (dst == null) + dst = new Point2D.Double(); + double x = src.getX(); + double y = src.getY(); + double nx = m00 * x + m01 * y + m02; + double ny = m10 * x + m11 * y + m12; + dst.setLocation(nx, ny); + return dst; + } + + /** + * Perform this transformation on an array of points, storing the results + * in another (possibly same) array. This will not create a destination + * array, but will create points for the null entries of the destination. + * The transformation is done sequentially. While having a single source + * and destination point be the same is safe, you should be aware that + * duplicate references to the same point in the source, and having the + * source overlap the destination, may result in your source points changing + * from a previous transform before it is their turn to be evaluated. + * + * @param src the array of source points + * @param srcOff the starting offset into src + * @param dst the array of destination points (may have null entries) + * @param dstOff the starting offset into dst + * @param num the number of points to transform + * @throws NullPointerException if src or dst is null, or src has null + * entries + * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded + * @throws ArrayStoreException if new points are incompatible with dst + */ + public void transform(Point2D[] src, int srcOff, + Point2D[] dst, int dstOff, int num) + { + while (--num >= 0) + dst[dstOff] = transform(src[srcOff++], dst[dstOff++]); + } + + /** + * Perform this transformation on an array of points, in (x,y) pairs, + * storing the results in another (possibly same) array. This will not + * create a destination array. All sources are copied before the + * transformation, so that no result will overwrite a point that has not yet + * been evaluated. + * + * @param srcPts the array of source points + * @param srcOff the starting offset into src + * @param dstPts the array of destination points + * @param dstOff the starting offset into dst + * @param num the number of points to transform + * @throws NullPointerException if src or dst is null + * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded + */ + public void transform(float[] srcPts, int srcOff, + float[] dstPts, int dstOff, int num) + { + if (srcPts == dstPts && dstOff > srcOff + && num > 1 && srcOff + 2 * num > dstOff) + { + float[] f = new float[2 * num]; + System.arraycopy(srcPts, srcOff, f, 0, 2 * num); + srcPts = f; + } + while (--num >= 0) + { + float x = srcPts[srcOff++]; + float y = srcPts[srcOff++]; + dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02); + dstPts[dstOff++] = (float) (m10 * x + m11 * y + m12); + } + } + + /** + * Perform this transformation on an array of points, in (x,y) pairs, + * storing the results in another (possibly same) array. This will not + * create a destination array. All sources are copied before the + * transformation, so that no result will overwrite a point that has not yet + * been evaluated. + * + * @param srcPts the array of source points + * @param srcOff the starting offset into src + * @param dstPts the array of destination points + * @param dstOff the starting offset into dst + * @param num the number of points to transform + * @throws NullPointerException if src or dst is null + * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded + */ + public void transform(double[] srcPts, int srcOff, + double[] dstPts, int dstOff, int num) + { + if (srcPts == dstPts && dstOff > srcOff + && num > 1 && srcOff + 2 * num > dstOff) + { + double[] d = new double[2 * num]; + System.arraycopy(srcPts, srcOff, d, 0, 2 * num); + srcPts = d; + } + while (--num >= 0) + { + double x = srcPts[srcOff++]; + double y = srcPts[srcOff++]; + dstPts[dstOff++] = m00 * x + m01 * y + m02; + dstPts[dstOff++] = m10 * x + m11 * y + m12; + } + } + + /** + * Perform this transformation on an array of points, in (x,y) pairs, + * storing the results in another array. This will not create a destination + * array. + * + * @param srcPts the array of source points + * @param srcOff the starting offset into src + * @param dstPts the array of destination points + * @param dstOff the starting offset into dst + * @param num the number of points to transform + * @throws NullPointerException if src or dst is null + * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded + */ + public void transform(float[] srcPts, int srcOff, + double[] dstPts, int dstOff, int num) + { + while (--num >= 0) + { + float x = srcPts[srcOff++]; + float y = srcPts[srcOff++]; + dstPts[dstOff++] = m00 * x + m01 * y + m02; + dstPts[dstOff++] = m10 * x + m11 * y + m12; + } + } + + /** + * Perform this transformation on an array of points, in (x,y) pairs, + * storing the results in another array. This will not create a destination + * array. + * + * @param srcPts the array of source points + * @param srcOff the starting offset into src + * @param dstPts the array of destination points + * @param dstOff the starting offset into dst + * @param num the number of points to transform + * @throws NullPointerException if src or dst is null + * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded + */ + public void transform(double[] srcPts, int srcOff, + float[] dstPts, int dstOff, int num) + { + while (--num >= 0) + { + double x = srcPts[srcOff++]; + double y = srcPts[srcOff++]; + dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02); + dstPts[dstOff++] = (float) (m10 * x + m11 * y + m12); + } + } + + /** + * Perform the inverse of this transformation on the given source point, + * and store the result in the destination (creating it if necessary). It + * is safe for src and dst to be the same. + * + * @param src the source point + * @param dst the destination, or null + * @return the inverse transformation of src, in dst if it was non-null + * @throws NullPointerException if src is null + * @throws NoninvertibleTransformException if the inverse does not exist + * @see #getDeterminant() + */ + public Point2D inverseTransform(Point2D src, Point2D dst) + throws NoninvertibleTransformException + { + return createInverse().transform(src, dst); + } + + /** + * Perform the inverse of this transformation on an array of points, in + * (x,y) pairs, storing the results in another (possibly same) array. This + * will not create a destination array. All sources are copied before the + * transformation, so that no result will overwrite a point that has not yet + * been evaluated. + * + * @param srcPts the array of source points + * @param srcOff the starting offset into src + * @param dstPts the array of destination points + * @param dstOff the starting offset into dst + * @param num the number of points to transform + * @throws NullPointerException if src or dst is null + * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded + * @throws NoninvertibleTransformException if the inverse does not exist + * @see #getDeterminant() + */ + public void inverseTransform(double[] srcPts, int srcOff, + double[] dstPts, int dstOff, int num) + throws NoninvertibleTransformException + { + createInverse().transform(srcPts, srcOff, dstPts, dstOff, num); + } + + /** + * Perform this transformation, less any translation, on the given source + * point, and store the result in the destination (creating it if + * necessary). It is safe for src and dst to be the same. The reduced + * transform is equivalent to: + * <pre> + * [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ] + * [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ] + * </pre> + * + * @param src the source point + * @param dst the destination, or null + * @return the delta transformation of src, in dst if it was non-null + * @throws NullPointerException if src is null + */ + public Point2D deltaTransform(Point2D src, Point2D dst) + { + if (dst == null) + dst = new Point2D.Double(); + double x = src.getX(); + double y = src.getY(); + double nx = m00 * x + m01 * y; + double ny = m10 * x + m11 * y; + dst.setLocation(nx, ny); + return dst; + } + + /** + * Perform this transformation, less any translation, on an array of points, + * in (x,y) pairs, storing the results in another (possibly same) array. + * This will not create a destination array. All sources are copied before + * the transformation, so that no result will overwrite a point that has + * not yet been evaluated. The reduced transform is equivalent to: + * <pre> + * [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ] + * [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ] + * </pre> + * + * @param srcPts the array of source points + * @param srcOff the starting offset into src + * @param dstPts the array of destination points + * @param dstOff the starting offset into dst + * @param num the number of points to transform + * @throws NullPointerException if src or dst is null + * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded + */ + public void deltaTransform(double[] srcPts, int srcOff, + double[] dstPts, int dstOff, + int num) + { + if (srcPts == dstPts && dstOff > srcOff + && num > 1 && srcOff + 2 * num > dstOff) + { + double[] d = new double[2 * num]; + System.arraycopy(srcPts, srcOff, d, 0, 2 * num); + srcPts = d; + } + while (--num >= 0) + { + double x = srcPts[srcOff++]; + double y = srcPts[srcOff++]; + dstPts[dstOff++] = m00 * x + m01 * y; + dstPts[dstOff++] = m10 * x + m11 * y; + } + } + + /** + * Return a new Shape, based on the given one, where the path of the shape + * has been transformed by this transform. Notice that this uses GeneralPath, + * which only stores points in float precision. + * + * @param src the shape source to transform + * @return the shape, transformed by this, <code>null</code> if src is + * <code>null</code>. + * @see GeneralPath#transform(AffineTransform) + */ + public Shape createTransformedShape(Shape src) + { + if(src == null) + return null; + GeneralPath p = new GeneralPath(src); + p.transform(this); + return p; + } + + /** + * Returns a string representation of the transform, in the format: + * <code>"AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], [" + * + m10 + ", " + m11 + ", " + m12 + "]]"</code>. + * + * @return the string representation + */ + public String toString() + { + return "AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], [" + + m10 + ", " + m11 + ", " + m12 + "]]"; + } + + /** + * Tests if this transformation is the identity: + * <pre> + * [ 1 0 0 ] + * [ 0 1 0 ] + * [ 0 0 1 ] + * </pre> + * + * @return true if this is the identity transform + */ + public boolean isIdentity() + { + // Rather than rely on type, check explicitly. + return (m00 == 1 && m01 == 0 && m02 == 0 + && m10 == 0 && m11 == 1 && m12 == 0); + } + + /** + * Create a new transform of the same run-time type, with the same + * transforming properties as this one. + * + * @return the clone + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // Impossible + } + } + + /** + * Return the hashcode for this transformation. The formula is not + * documented, but appears to be the same as: + * <pre> + * long l = Double.doubleToLongBits(getScaleX()); + * l = l * 31 + Double.doubleToLongBits(getShearY()); + * l = l * 31 + Double.doubleToLongBits(getShearX()); + * l = l * 31 + Double.doubleToLongBits(getScaleY()); + * l = l * 31 + Double.doubleToLongBits(getTranslateX()); + * l = l * 31 + Double.doubleToLongBits(getTranslateY()); + * return (int) ((l >> 32) ^ l); + * </pre> + * + * @return the hashcode + */ + public int hashCode() + { + long l = Double.doubleToLongBits(m00); + l = l * 31 + Double.doubleToLongBits(m10); + l = l * 31 + Double.doubleToLongBits(m01); + l = l * 31 + Double.doubleToLongBits(m11); + l = l * 31 + Double.doubleToLongBits(m02); + l = l * 31 + Double.doubleToLongBits(m12); + return (int) ((l >> 32) ^ l); + } + + /** + * Compares two transforms for equality. This returns true if they have the + * same matrix values. + * + * @param obj the transform to compare + * @return true if it is equal + */ + public boolean equals(Object obj) + { + if (! (obj instanceof AffineTransform)) + return false; + AffineTransform t = (AffineTransform) obj; + return (m00 == t.m00 && m01 == t.m01 && m02 == t.m02 + && m10 == t.m10 && m11 == t.m11 && m12 == t.m12); + } + + /** + * Helper to decode the type from the matrix. This is not guaranteed + * to find the optimal type, but at least it will be valid. + */ + private void updateType() + { + double det = getDeterminant(); + if (det == 0) + { + type = TYPE_GENERAL_TRANSFORM; + return; + } + // Scale (includes rotation by PI) or translation. + if (m01 == 0 && m10 == 0) + { + if (m00 == m11) + type = m00 == 1 ? TYPE_IDENTITY : TYPE_UNIFORM_SCALE; + else + type = TYPE_GENERAL_SCALE; + if (m02 != 0 || m12 != 0) + type |= TYPE_TRANSLATION; + } + // Rotation. + else if (m00 == m11 && m01 == -m10) + { + type = m00 == 0 ? TYPE_QUADRANT_ROTATION : TYPE_GENERAL_ROTATION; + if (det != 1) + type |= TYPE_UNIFORM_SCALE; + if (m02 != 0 || m12 != 0) + type |= TYPE_TRANSLATION; + } + else + type = TYPE_GENERAL_TRANSFORM; + } + + /** + * Reads a transform from an object stream. + * + * @param s the stream to read from + * @throws ClassNotFoundException if there is a problem deserializing + * @throws IOException if there is a problem deserializing + */ + private void readObject(ObjectInputStream s) + throws ClassNotFoundException, IOException + { + s.defaultReadObject(); + updateType(); + } +} // class AffineTransform diff --git a/libjava/classpath/java/awt/geom/Arc2D.java b/libjava/classpath/java/awt/geom/Arc2D.java new file mode 100644 index 0000000..eff34a0 --- /dev/null +++ b/libjava/classpath/java/awt/geom/Arc2D.java @@ -0,0 +1,1399 @@ +/* Arc2D.java -- represents an arc in 2-D space + Copyright (C) 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.geom; + +import java.util.NoSuchElementException; + + +/** + * This class represents all arcs (segments of an ellipse in 2-D space). The + * arcs are defined by starting angle and extent (arc length) in degrees, as + * opposed to radians (like the rest of Java), and can be open, chorded, or + * wedge shaped. The angles are skewed according to the ellipse, so that 45 + * degrees always points to the upper right corner (positive x, negative y) + * of the bounding rectangle. A positive extent draws a counterclockwise arc, + * and while the angle can be any value, the path iterator only traverses the + * first 360 degrees. Storage is up to the subclasses. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @author Sven de Marothy (sven@physto.se) + * @since 1.2 + */ +public abstract class Arc2D extends RectangularShape +{ + /** + * An open arc, with no segment connecting the endpoints. This type of + * arc still contains the same points as a chorded version. + */ + public static final int OPEN = 0; + + /** + * A closed arc with a single segment connecting the endpoints (a chord). + */ + public static final int CHORD = 1; + + /** + * A closed arc with two segments, one from each endpoint, meeting at the + * center of the ellipse. + */ + public static final int PIE = 2; + + /** The closure type of this arc. This is package-private to avoid an + * accessor method. */ + int type; + + /** + * Create a new arc, with the specified closure type. + * + * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}. + * @throws IllegalArgumentException if type is invalid + */ + protected Arc2D(int type) + { + if (type < OPEN || type > PIE) + throw new IllegalArgumentException(); + this.type = type; + } + + /** + * Get the starting angle of the arc in degrees. + * + * @return the starting angle + * @see #setAngleStart(double) + */ + public abstract double getAngleStart(); + + /** + * Get the extent angle of the arc in degrees. + * + * @return the extent angle + * @see #setAngleExtent(double) + */ + public abstract double getAngleExtent(); + + /** + * Return the closure type of the arc. + * + * @return the closure type + * @see #OPEN + * @see #CHORD + * @see #PIE + * @see #setArcType(int) + */ + public int getArcType() + { + return type; + } + + /** + * Returns the starting point of the arc. + * + * @return the start point + */ + public Point2D getStartPoint() + { + double angle = Math.toRadians(getAngleStart()); + double rx = getWidth() / 2; + double ry = getHeight() / 2; + double x = getX() + rx + rx * Math.cos(angle); + double y = getY() + ry - ry * Math.sin(angle); + return new Point2D.Double(x, y); + } + + /** + * Returns the ending point of the arc. + * + * @return the end point + */ + public Point2D getEndPoint() + { + double angle = Math.toRadians(getAngleStart() + getAngleExtent()); + double rx = getWidth() / 2; + double ry = getHeight() / 2; + double x = getX() + rx + rx * Math.cos(angle); + double y = getY() + ry - ry * Math.sin(angle); + return new Point2D.Double(x, y); + } + + /** + * Set the parameters of the arc. The angles are in degrees, and a positive + * extent sweeps counterclockwise (from the positive x-axis to the negative + * y-axis). + * + * @param x the new x coordinate of the upper left of the bounding box + * @param y the new y coordinate of the upper left of the bounding box + * @param w the new width of the bounding box + * @param h the new height of the bounding box + * @param start the start angle, in degrees + * @param extent the arc extent, in degrees + * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + */ + public abstract void setArc(double x, double y, double w, double h, + double start, double extent, int type); + + /** + * Set the parameters of the arc. The angles are in degrees, and a positive + * extent sweeps counterclockwise (from the positive x-axis to the negative + * y-axis). + * + * @param p the upper left point of the bounding box + * @param d the dimensions of the bounding box + * @param start the start angle, in degrees + * @param extent the arc extent, in degrees + * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + * @throws NullPointerException if p or d is null + */ + public void setArc(Point2D p, Dimension2D d, double start, double extent, + int type) + { + setArc(p.getX(), p.getY(), d.getWidth(), d.getHeight(), start, extent, type); + } + + /** + * Set the parameters of the arc. The angles are in degrees, and a positive + * extent sweeps counterclockwise (from the positive x-axis to the negative + * y-axis). + * + * @param r the new bounding box + * @param start the start angle, in degrees + * @param extent the arc extent, in degrees + * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + * @throws NullPointerException if r is null + */ + public void setArc(Rectangle2D r, double start, double extent, int type) + { + setArc(r.getX(), r.getY(), r.getWidth(), r.getHeight(), start, extent, type); + } + + /** + * Set the parameters of the arc from the given one. + * + * @param a the arc to copy + * @throws NullPointerException if a is null + */ + public void setArc(Arc2D a) + { + setArc(a.getX(), a.getY(), a.getWidth(), a.getHeight(), a.getAngleStart(), + a.getAngleExtent(), a.getArcType()); + } + + /** + * Set the parameters of the arc. The angles are in degrees, and a positive + * extent sweeps counterclockwise (from the positive x-axis to the negative + * y-axis). This controls the center point and radius, so the arc will be + * circular. + * + * @param x the x coordinate of the center of the circle + * @param y the y coordinate of the center of the circle + * @param r the radius of the circle + * @param start the start angle, in degrees + * @param extent the arc extent, in degrees + * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + */ + public void setArcByCenter(double x, double y, double r, double start, + double extent, int type) + { + setArc(x - r, y - r, r + r, r + r, start, extent, type); + } + + /** + * Sets the parameters of the arc by finding the tangents of two lines, and + * using the specified radius. The arc will be circular, will begin on the + * tangent point of the line extending from p1 to p2, and will end on the + * tangent point of the line extending from p2 to p3. + * + * XXX What happens if the points are colinear, or the radius negative? + * + * @param p1 the first point + * @param p2 the tangent line intersection point + * @param p3 the third point + * @param r the radius of the arc + * @throws NullPointerException if any point is null + */ + public void setArcByTangent(Point2D p1, Point2D p2, Point2D p3, double r) + { + if ((p2.getX() - p1.getX()) * (p3.getY() - p1.getY()) + - (p3.getX() - p1.getX()) * (p2.getY() - p1.getY()) > 0) + { + Point2D p = p3; + p3 = p1; + p1 = p; + } + + // normalized tangent vectors + double dx1 = (p1.getX() - p2.getX()) / p1.distance(p2); + double dy1 = (p1.getY() - p2.getY()) / p1.distance(p2); + double dx2 = (p2.getX() - p3.getX()) / p3.distance(p2); + double dy2 = (p2.getY() - p3.getY()) / p3.distance(p2); + double theta1 = Math.atan2(dx1, dy1); + double theta2 = Math.atan2(dx2, dy2); + + double dx = r * Math.cos(theta2) - r * Math.cos(theta1); + double dy = -r * Math.sin(theta2) + r * Math.sin(theta1); + + if (theta1 < 0) + theta1 += 2 * Math.PI; + if (theta2 < 0) + theta2 += 2 * Math.PI; + if (theta2 < theta1) + theta2 += 2 * Math.PI; + + // Vectors of the lines, not normalized, note we change + // the direction of line 2. + dx1 = p1.getX() - p2.getX(); + dy1 = p1.getY() - p2.getY(); + dx2 = p3.getX() - p2.getX(); + dy2 = p3.getY() - p2.getY(); + + // Calculate the tangent point to the second line + double t2 = -(dx1 * dy - dy1 * dx) / (dx2 * dy1 - dx1 * dy2); + double x2 = t2 * (p3.getX() - p2.getX()) + p2.getX(); + double y2 = t2 * (p3.getY() - p2.getY()) + p2.getY(); + + // calculate the center point + double x = x2 - r * Math.cos(theta2); + double y = y2 + r * Math.sin(theta2); + + setArc(x - r, y - r, 2 * r, 2 * r, Math.toDegrees(theta1), + Math.toDegrees(theta2 - theta1), getArcType()); + } + + /** + * Set the start, in degrees. + * + * @param start the new start angle + * @see #getAngleStart() + */ + public abstract void setAngleStart(double start); + + /** + * Set the extent, in degrees. + * + * @param extent the new extent angle + * @see #getAngleExtent() + */ + public abstract void setAngleExtent(double extent); + + /** + * Sets the starting angle to the angle of the given point relative to + * the center of the arc. The extent remains constant; in other words, + * this rotates the arc. + * + * @param p the new start point + * @throws NullPointerException if p is null + * @see #getStartPoint() + * @see #getAngleStart() + */ + public void setAngleStart(Point2D p) + { + // Normalize. + double x = p.getX() - (getX() + getWidth() / 2); + double y = p.getY() - (getY() + getHeight() / 2); + setAngleStart(Math.toDegrees(Math.atan2(-y, x))); + } + + /** + * Sets the starting and extent angles to those of the given points + * relative to the center of the arc. The arc will be non-empty, and will + * extend counterclockwise. + * + * @param x1 the first x coordinate + * @param y1 the first y coordinate + * @param x2 the second x coordinate + * @param y2 the second y coordinate + * @see #setAngleStart(Point2D) + */ + public void setAngles(double x1, double y1, double x2, double y2) + { + // Normalize the points. + double mx = getX(); + double my = getY(); + double mw = getWidth(); + double mh = getHeight(); + x1 = x1 - (mx + mw / 2); + y1 = y1 - (my + mh / 2); + x2 = x2 - (mx + mw / 2); + y2 = y2 - (my + mh / 2); + double start = Math.toDegrees(Math.atan2(-y1, x1)); + double extent = Math.toDegrees(Math.atan2(-y2, x2)) - start; + if (extent < 0) + extent += 360; + setAngleStart(start); + setAngleExtent(extent); + } + + /** + * Sets the starting and extent angles to those of the given points + * relative to the center of the arc. The arc will be non-empty, and will + * extend counterclockwise. + * + * @param p1 the first point + * @param p2 the second point + * @throws NullPointerException if either point is null + * @see #setAngleStart(Point2D) + */ + public void setAngles(Point2D p1, Point2D p2) + { + setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY()); + } + + /** + * Set the closure type of this arc. + * + * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + * @see #getArcType() + */ + public void setArcType(int type) + { + if (type < OPEN || type > PIE) + throw new IllegalArgumentException(); + this.type = type; + } + + /** + * Sets the location and bounds of the ellipse of which this arc is a part. + * + * @param x the new x coordinate + * @param y the new y coordinate + * @param w the new width + * @param h the new height + * @see #getFrame() + */ + public void setFrame(double x, double y, double w, double h) + { + setArc(x, y, w, h, getAngleStart(), getAngleExtent(), type); + } + + /** + * Gets the bounds of the arc. This is much tighter than + * <code>getBounds</code>, as it takes into consideration the start and + * end angles, and the center point of a pie wedge, rather than just the + * overall ellipse. + * + * @return the bounds of the arc + * @see #getBounds() + */ + public Rectangle2D getBounds2D() + { + double extent = getAngleExtent(); + if (Math.abs(extent) >= 360) + return makeBounds(getX(), getY(), getWidth(), getHeight()); + + // Find the minimal bounding box. This determined by its extrema, + // which are the center, the endpoints of the arc, and any local + // maximum contained by the arc. + double rX = getWidth() / 2; + double rY = getHeight() / 2; + double centerX = getX() + rX; + double centerY = getY() + rY; + + Point2D p1 = getStartPoint(); + Rectangle2D result = makeBounds(p1.getX(), p1.getY(), 0, 0); + result.add(getEndPoint()); + + if (type == PIE) + result.add(centerX, centerY); + if (containsAngle(0)) + result.add(centerX + rX, centerY); + if (containsAngle(90)) + result.add(centerX, centerY - rY); + if (containsAngle(180)) + result.add(centerX - rX, centerY); + if (containsAngle(270)) + result.add(centerX, centerY + rY); + + return result; + } + + /** + * Construct a bounding box in a precision appropriate for the subclass. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + * @return the rectangle for use in getBounds2D + */ + protected abstract Rectangle2D makeBounds(double x, double y, double w, + double h); + + /** + * Tests if the given angle, in degrees, is included in the arc. + * All angles are normalized to be between 0 and 360 degrees. + * + * @param a the angle to test + * @return true if it is contained + */ + public boolean containsAngle(double a) + { + double start = getAngleStart(); + double extent = getAngleExtent(); + double end = start + extent; + + if (extent == 0) + return false; + + if (extent >= 360 || extent <= -360) + return true; + + if (extent < 0) + { + end = start; + start += extent; + } + + start %= 360; + while (start < 0) + start += 360; + + end %= 360; + while (end < start) + end += 360; + + a %= 360; + while (a < start) + a += 360; + + return a >= start && a < end; // starting angle included, ending angle not + } + + /** + * Determines if the arc contains the given point. If the bounding box + * is empty, then this will return false. + * + * The area considered 'inside' an arc of type OPEN is the same as the + * area inside an equivalent filled CHORD-type arc. The area considered + * 'inside' a CHORD-type arc is the same as the filled area. + * + * @param x the x coordinate to test + * @param y the y coordinate to test + * @return true if the point is inside the arc + */ + public boolean contains(double x, double y) + { + double w = getWidth(); + double h = getHeight(); + double extent = getAngleExtent(); + if (w <= 0 || h <= 0 || extent == 0) + return false; + + double mx = getX() + w / 2; + double my = getY() + h / 2; + double dx = (x - mx) * 2 / w; + double dy = (y - my) * 2 / h; + if ((dx * dx + dy * dy) >= 1.0) + return false; + + double angle = Math.toDegrees(Math.atan2(-dy, dx)); + if (getArcType() == PIE) + return containsAngle(angle); + + double a1 = Math.toRadians(getAngleStart()); + double a2 = Math.toRadians(getAngleStart() + extent); + double x1 = mx + getWidth() * Math.cos(a1) / 2; + double y1 = my - getHeight() * Math.sin(a1) / 2; + double x2 = mx + getWidth() * Math.cos(a2) / 2; + double y2 = my - getHeight() * Math.sin(a2) / 2; + double sgn = ((x2 - x1) * (my - y1) - (mx - x1) * (y2 - y1)) * ((x2 - x1) * (y + - y1) - (x - x1) * (y2 - y1)); + + if (Math.abs(extent) > 180) + { + if (containsAngle(angle)) + return true; + return sgn > 0; + } + else + { + if (! containsAngle(angle)) + return false; + return sgn < 0; + } + } + + /** + * Tests if a given rectangle intersects the area of the arc. + * + * For a definition of the 'inside' area, see the contains() method. + * @see #contains(double, double) + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @return true if the two shapes share common points + */ + public boolean intersects(double x, double y, double w, double h) + { + double extent = getAngleExtent(); + if (extent == 0) + return false; + + if (contains(x, y) || contains(x, y + h) || contains(x + w, y) + || contains(x + w, y + h)) + return true; + + Rectangle2D rect = new Rectangle2D.Double(x, y, w, h); + + double a = getWidth() / 2.0; + double b = getHeight() / 2.0; + + double mx = getX() + a; + double my = getY() + b; + double x1 = mx + a * Math.cos(Math.toRadians(getAngleStart())); + double y1 = my - b * Math.sin(Math.toRadians(getAngleStart())); + double x2 = mx + a * Math.cos(Math.toRadians(getAngleStart() + extent)); + double y2 = my - b * Math.sin(Math.toRadians(getAngleStart() + extent)); + + if (getArcType() != CHORD) + { + // check intersections against the pie radii + if (rect.intersectsLine(mx, my, x1, y1)) + return true; + if (rect.intersectsLine(mx, my, x2, y2)) + return true; + } + else// check the chord + if (rect.intersectsLine(x1, y1, x2, y2)) + return true; + + // Check the Arc segment against the four edges + double dx; + + // Check the Arc segment against the four edges + double dy; + dy = y - my; + dx = a * Math.sqrt(1 - ((dy * dy) / (b * b))); + if (! java.lang.Double.isNaN(dx)) + { + if (mx + dx >= x && mx + dx <= x + w + && containsAngle(Math.toDegrees(Math.atan2(-dy, dx)))) + return true; + if (mx - dx >= x && mx - dx <= x + w + && containsAngle(Math.toDegrees(Math.atan2(-dy, -dx)))) + return true; + } + dy = (y + h) - my; + dx = a * Math.sqrt(1 - ((dy * dy) / (b * b))); + if (! java.lang.Double.isNaN(dx)) + { + if (mx + dx >= x && mx + dx <= x + w + && containsAngle(Math.toDegrees(Math.atan2(-dy, dx)))) + return true; + if (mx - dx >= x && mx - dx <= x + w + && containsAngle(Math.toDegrees(Math.atan2(-dy, -dx)))) + return true; + } + dx = x - mx; + dy = b * Math.sqrt(1 - ((dx * dx) / (a * a))); + if (! java.lang.Double.isNaN(dy)) + { + if (my + dy >= y && my + dy <= y + h + && containsAngle(Math.toDegrees(Math.atan2(-dy, dx)))) + return true; + if (my - dy >= y && my - dy <= y + h + && containsAngle(Math.toDegrees(Math.atan2(dy, dx)))) + return true; + } + + dx = (x + w) - mx; + dy = b * Math.sqrt(1 - ((dx * dx) / (a * a))); + if (! java.lang.Double.isNaN(dy)) + { + if (my + dy >= y && my + dy <= y + h + && containsAngle(Math.toDegrees(Math.atan2(-dy, dx)))) + return true; + if (my - dy >= y && my - dy <= y + h + && containsAngle(Math.toDegrees(Math.atan2(dy, dx)))) + return true; + } + + // Check whether the arc is contained within the box + if (rect.contains(mx, my)) + return true; + + return false; + } + + /** + * Tests if a given rectangle is contained in the area of the arc. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @return true if the arc contains the rectangle + */ + public boolean contains(double x, double y, double w, double h) + { + double extent = getAngleExtent(); + if (extent == 0) + return false; + + if (! (contains(x, y) && contains(x, y + h) && contains(x + w, y) + && contains(x + w, y + h))) + return false; + + Rectangle2D rect = new Rectangle2D.Double(x, y, w, h); + + double a = getWidth() / 2.0; + double b = getHeight() / 2.0; + + double mx = getX() + a; + double my = getY() + b; + double x1 = mx + a * Math.cos(Math.toRadians(getAngleStart())); + double y1 = my - b * Math.sin(Math.toRadians(getAngleStart())); + double x2 = mx + a * Math.cos(Math.toRadians(getAngleStart() + extent)); + double y2 = my - b * Math.sin(Math.toRadians(getAngleStart() + extent)); + if (getArcType() != CHORD) + { + // check intersections against the pie radii + if (rect.intersectsLine(mx, my, x1, y1)) + return false; + + if (rect.intersectsLine(mx, my, x2, y2)) + return false; + } + else if (rect.intersectsLine(x1, y1, x2, y2)) + return false; + return true; + } + + /** + * Tests if a given rectangle is contained in the area of the arc. + * + * @param r the rectangle + * @return true if the arc contains the rectangle + */ + public boolean contains(Rectangle2D r) + { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Returns an iterator over this arc, with an optional transformation. + * This iterator is threadsafe, so future modifications to the arc do not + * affect the iteration. + * + * @param at the transformation, or null + * @return a path iterator + */ + public PathIterator getPathIterator(AffineTransform at) + { + return new ArcIterator(this, at); + } + + /** + * This class is used to iterate over an arc. Since ellipses are a subclass + * of arcs, this is used by Ellipse2D as well. + * + * @author Eric Blake (ebb9@email.byu.edu) + */ + static final class ArcIterator implements PathIterator + { + /** The current iteration. */ + private int current; + + /** The last iteration. */ + private final int limit; + + /** The optional transformation. */ + private final AffineTransform xform; + + /** The x coordinate of the bounding box. */ + private final double x; + + /** The y coordinate of the bounding box. */ + private final double y; + + /** The width of the bounding box. */ + private final double w; + + /** The height of the bounding box. */ + private final double h; + + /** The start angle, in radians (not degrees). */ + private final double start; + + /** The extent angle, in radians (not degrees). */ + private final double extent; + + /** The arc closure type. */ + private final int type; + + /** + * Construct a new iterator over an arc. + * + * @param a the arc + * @param xform the transform + */ + public ArcIterator(Arc2D a, AffineTransform xform) + { + this.xform = xform; + x = a.getX(); + y = a.getY(); + w = a.getWidth(); + h = a.getHeight(); + double start = a.getAngleStart() * (Math.PI / 180); + double extent = a.getAngleExtent() * (Math.PI / 180); + + if (extent < 0) + { + extent = -extent; + start = 2 * Math.PI - extent + start; + } + this.start = start; + this.extent = extent; + + type = a.type; + if (w < 0 || h < 0) + limit = -1; + else if (extent == 0) + limit = type; + else if (extent <= Math.PI / 2.0) + limit = type + 1; + else if (extent <= Math.PI) + limit = type + 2; + else if (extent <= 3.0 * (Math.PI / 2.0)) + limit = type + 3; + else + limit = type + 4; + } + + /** + * Construct a new iterator over an ellipse. + * + * @param e the ellipse + * @param xform the transform + */ + public ArcIterator(Ellipse2D e, AffineTransform xform) + { + this.xform = xform; + x = e.getX(); + y = e.getY(); + w = e.getWidth(); + h = e.getHeight(); + start = 0; + extent = 2 * Math.PI; + type = CHORD; + limit = (w < 0 || h < 0) ? -1 : 5; + } + + /** + * Return the winding rule. + * + * @return {@link PathIterator#WIND_NON_ZERO} + */ + public int getWindingRule() + { + return WIND_NON_ZERO; + } + + /** + * Test if the iteration is complete. + * + * @return true if more segments exist + */ + public boolean isDone() + { + return current > limit; + } + + /** + * Advance the iterator. + */ + public void next() + { + current++; + } + + /** + * Put the current segment into the array, and return the segment type. + * + * @param coords an array of 6 elements + * @return the segment type + * @throws NullPointerException if coords is null + * @throws ArrayIndexOutOfBoundsException if coords is too small + */ + public int currentSegment(float[] coords) + { + double[] double_coords = new double[6]; + int code = currentSegment(double_coords); + for (int i = 0; i < 6; ++i) + coords[i] = (float) double_coords[i]; + return code; + } + + /** + * Put the current segment into the array, and return the segment type. + * + * @param coords an array of 6 elements + * @return the segment type + * @throws NullPointerException if coords is null + * @throws ArrayIndexOutOfBoundsException if coords is too small + */ + public int currentSegment(double[] coords) + { + double rx = w / 2; + double ry = h / 2; + double xmid = x + rx; + double ymid = y + ry; + + if (current > limit) + throw new NoSuchElementException("arc iterator out of bounds"); + + if (current == 0) + { + coords[0] = xmid + rx * Math.cos(start); + coords[1] = ymid - ry * Math.sin(start); + if (xform != null) + xform.transform(coords, 0, coords, 0, 1); + return SEG_MOVETO; + } + + if (type != OPEN && current == limit) + return SEG_CLOSE; + + if ((current == limit - 1) && (type == PIE)) + { + coords[0] = xmid; + coords[1] = ymid; + if (xform != null) + xform.transform(coords, 0, coords, 0, 1); + return SEG_LINETO; + } + + // note that this produces a cubic approximation of the arc segment, + // not a true ellipsoid. there's no ellipsoid path segment code, + // unfortunately. the cubic approximation looks about right, though. + double kappa = (Math.sqrt(2.0) - 1.0) * (4.0 / 3.0); + double quad = (Math.PI / 2.0); + + double curr_begin = start + (current - 1) * quad; + double curr_extent = Math.min((start + extent) - curr_begin, quad); + double portion_of_a_quadrant = curr_extent / quad; + + double x0 = xmid + rx * Math.cos(curr_begin); + double y0 = ymid - ry * Math.sin(curr_begin); + + double x1 = xmid + rx * Math.cos(curr_begin + curr_extent); + double y1 = ymid - ry * Math.sin(curr_begin + curr_extent); + + AffineTransform trans = new AffineTransform(); + double[] cvec = new double[2]; + double len = kappa * portion_of_a_quadrant; + double angle = curr_begin; + + // in a hypothetical "first quadrant" setting, our first control + // vector would be sticking up, from [1,0] to [1,kappa]. + // + // let us recall however that in java2d, y coords are upside down + // from what one would consider "normal" first quadrant rules, so we + // will *subtract* the y value of this control vector from our first + // point. + cvec[0] = 0; + cvec[1] = len; + trans.scale(rx, ry); + trans.rotate(angle); + trans.transform(cvec, 0, cvec, 0, 1); + coords[0] = x0 + cvec[0]; + coords[1] = y0 - cvec[1]; + + // control vector #2 would, ideally, be sticking out and to the + // right, in a first quadrant arc segment. again, subtraction of y. + cvec[0] = 0; + cvec[1] = -len; + trans.rotate(curr_extent); + trans.transform(cvec, 0, cvec, 0, 1); + coords[2] = x1 + cvec[0]; + coords[3] = y1 - cvec[1]; + + // end point + coords[4] = x1; + coords[5] = y1; + + if (xform != null) + xform.transform(coords, 0, coords, 0, 3); + + return SEG_CUBICTO; + } + } // class ArcIterator + + /** + * This class implements an arc in double precision. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + */ + public static class Double extends Arc2D + { + /** The x coordinate of the box bounding the ellipse of this arc. */ + public double x; + + /** The y coordinate of the box bounding the ellipse of this arc. */ + public double y; + + /** The width of the box bounding the ellipse of this arc. */ + public double width; + + /** The height of the box bounding the ellipse of this arc. */ + public double height; + + /** The start angle of this arc, in degrees. */ + public double start; + + /** The extent angle of this arc, in degrees. */ + public double extent; + + /** + * Create a new, open arc at (0,0) with 0 extent. + */ + public Double() + { + super(OPEN); + } + + /** + * Create a new arc of the given type at (0,0) with 0 extent. + * + * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + */ + public Double(int type) + { + super(type); + } + + /** + * Create a new arc with the given dimensions. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + * @param start the start angle, in degrees + * @param extent the extent, in degrees + * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + */ + public Double(double x, double y, double w, double h, double start, + double extent, int type) + { + super(type); + this.x = x; + this.y = y; + width = w; + height = h; + this.start = start; + this.extent = extent; + } + + /** + * Create a new arc with the given dimensions. + * + * @param r the bounding box + * @param start the start angle, in degrees + * @param extent the extent, in degrees + * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + * @throws NullPointerException if r is null + */ + public Double(Rectangle2D r, double start, double extent, int type) + { + super(type); + x = r.getX(); + y = r.getY(); + width = r.getWidth(); + height = r.getHeight(); + this.start = start; + this.extent = extent; + } + + /** + * Return the x coordinate of the bounding box. + * + * @return the value of x + */ + public double getX() + { + return x; + } + + /** + * Return the y coordinate of the bounding box. + * + * @return the value of y + */ + public double getY() + { + return y; + } + + /** + * Return the width of the bounding box. + * + * @return the value of width + */ + public double getWidth() + { + return width; + } + + /** + * Return the height of the bounding box. + * + * @return the value of height + */ + public double getHeight() + { + return height; + } + + /** + * Return the start angle of the arc, in degrees. + * + * @return the value of start + */ + public double getAngleStart() + { + return start; + } + + /** + * Return the extent of the arc, in degrees. + * + * @return the value of extent + */ + public double getAngleExtent() + { + return extent; + } + + /** + * Tests if the arc contains points. + * + * @return true if the arc has no interior + */ + public boolean isEmpty() + { + return width <= 0 || height <= 0; + } + + /** + * Sets the arc to the given dimensions. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + * @param start the start angle, in degrees + * @param extent the extent, in degrees + * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + */ + public void setArc(double x, double y, double w, double h, double start, + double extent, int type) + { + this.x = x; + this.y = y; + width = w; + height = h; + this.start = start; + this.extent = extent; + setArcType(type); + } + + /** + * Sets the start angle of the arc. + * + * @param start the new start angle + */ + public void setAngleStart(double start) + { + this.start = start; + } + + /** + * Sets the extent angle of the arc. + * + * @param extent the new extent angle + */ + public void setAngleExtent(double extent) + { + this.extent = extent; + } + + /** + * Creates a tight bounding box given dimensions that more precise than + * the bounding box of the ellipse. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + */ + protected Rectangle2D makeBounds(double x, double y, double w, double h) + { + return new Rectangle2D.Double(x, y, w, h); + } + } // class Double + + /** + * This class implements an arc in float precision. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + */ + public static class Float extends Arc2D + { + /** The x coordinate of the box bounding the ellipse of this arc. */ + public float x; + + /** The y coordinate of the box bounding the ellipse of this arc. */ + public float y; + + /** The width of the box bounding the ellipse of this arc. */ + public float width; + + /** The height of the box bounding the ellipse of this arc. */ + public float height; + + /** The start angle of this arc, in degrees. */ + public float start; + + /** The extent angle of this arc, in degrees. */ + public float extent; + + /** + * Create a new, open arc at (0,0) with 0 extent. + */ + public Float() + { + super(OPEN); + } + + /** + * Create a new arc of the given type at (0,0) with 0 extent. + * + * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + */ + public Float(int type) + { + super(type); + } + + /** + * Create a new arc with the given dimensions. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + * @param start the start angle, in degrees + * @param extent the extent, in degrees + * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + */ + public Float(float x, float y, float w, float h, float start, + float extent, int type) + { + super(type); + this.x = x; + this.y = y; + width = w; + height = h; + this.start = start; + this.extent = extent; + } + + /** + * Create a new arc with the given dimensions. + * + * @param r the bounding box + * @param start the start angle, in degrees + * @param extent the extent, in degrees + * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + * @throws NullPointerException if r is null + */ + public Float(Rectangle2D r, float start, float extent, int type) + { + super(type); + x = (float) r.getX(); + y = (float) r.getY(); + width = (float) r.getWidth(); + height = (float) r.getHeight(); + this.start = start; + this.extent = (float) extent; + } + + /** + * Return the x coordinate of the bounding box. + * + * @return the value of x + */ + public double getX() + { + return x; + } + + /** + * Return the y coordinate of the bounding box. + * + * @return the value of y + */ + public double getY() + { + return y; + } + + /** + * Return the width of the bounding box. + * + * @return the value of width + */ + public double getWidth() + { + return width; + } + + /** + * Return the height of the bounding box. + * + * @return the value of height + */ + public double getHeight() + { + return height; + } + + /** + * Return the start angle of the arc, in degrees. + * + * @return the value of start + */ + public double getAngleStart() + { + return start; + } + + /** + * Return the extent of the arc, in degrees. + * + * @return the value of extent + */ + public double getAngleExtent() + { + return extent; + } + + /** + * Tests if the arc contains points. + * + * @return true if the arc has no interior + */ + public boolean isEmpty() + { + return width <= 0 || height <= 0; + } + + /** + * Sets the arc to the given dimensions. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + * @param start the start angle, in degrees + * @param extent the extent, in degrees + * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} + * @throws IllegalArgumentException if type is invalid + */ + public void setArc(double x, double y, double w, double h, double start, + double extent, int type) + { + this.x = (float) x; + this.y = (float) y; + width = (float) w; + height = (float) h; + this.start = (float) start; + this.extent = (float) extent; + setArcType(type); + } + + /** + * Sets the start angle of the arc. + * + * @param start the new start angle + */ + public void setAngleStart(double start) + { + this.start = (float) start; + } + + /** + * Sets the extent angle of the arc. + * + * @param extent the new extent angle + */ + public void setAngleExtent(double extent) + { + this.extent = (float) extent; + } + + /** + * Creates a tight bounding box given dimensions that more precise than + * the bounding box of the ellipse. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + */ + protected Rectangle2D makeBounds(double x, double y, double w, double h) + { + return new Rectangle2D.Float((float) x, (float) y, (float) w, (float) h); + } + } // class Float +} // class Arc2D diff --git a/libjava/classpath/java/awt/geom/Area.java b/libjava/classpath/java/awt/geom/Area.java new file mode 100644 index 0000000..7a0fac4 --- /dev/null +++ b/libjava/classpath/java/awt/geom/Area.java @@ -0,0 +1,3312 @@ +/* Area.java -- represents a shape built by constructive area geometry + Copyright (C) 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.geom; + +import java.awt.Rectangle; +import java.awt.Shape; +import java.util.Vector; + + +/** + * The Area class represents any area for the purpose of + * Constructive Area Geometry (CAG) manipulations. CAG manipulations + * work as an area-wise form of boolean logic, where the basic operations are: + * <P><li>Add (in boolean algebra: A <B>or</B> B)<BR> + * <li>Subtract (in boolean algebra: A <B>and</B> (<B>not</B> B) )<BR> + * <li>Intersect (in boolean algebra: A <B>and</B> B)<BR> + * <li>Exclusive Or <BR> + * <img src="doc-files/Area-1.png" width="342" height="302" + * alt="Illustration of CAG operations" /><BR> + * Above is an illustration of the CAG operations on two ring shapes.<P> + * + * The contains and intersects() methods are also more accurate than the + * specification of #Shape requires.<P> + * + * Please note that constructing an Area can be slow + * (Self-intersection resolving is proportional to the square of + * the number of segments).<P> + * @see #add(Area) + * @see #subtract(Area) + * @see #intersect(Area) + * @see #exclusiveOr(Area) + * + * @author Sven de Marothy (sven@physto.se) + * + * @since 1.2 + * @status Works, but could be faster and more reliable. + */ +public class Area implements Shape, Cloneable +{ + /** + * General numerical precision + */ + private static final double EPSILON = 1E-11; + + /** + * recursive subdivision epsilon - (see getRecursionDepth) + */ + private static final double RS_EPSILON = 1E-13; + + /** + * Snap distance - points within this distance are considered equal + */ + private static final double PE_EPSILON = 1E-11; + + /** + * Segment vectors containing solid areas and holes + * This is package-private to avoid an accessor method. + */ + Vector solids; + + /** + * Segment vectors containing solid areas and holes + * This is package-private to avoid an accessor method. + */ + Vector holes; + + /** + * Vector (temporary) storing curve-curve intersections + */ + private Vector cc_intersections; + + /** + * Winding rule WIND_NON_ZERO used, after construction, + * this is irrelevant. + */ + private int windingRule; + + /** + * Constructs an empty Area + */ + public Area() + { + solids = new Vector(); + holes = new Vector(); + } + + /** + * Constructs an Area from any given Shape. <P> + * + * If the Shape is self-intersecting, the created Area will consist + * of non-self-intersecting subpaths, and any inner paths which + * are found redundant in accordance with the Shape's winding rule + * will not be included. + * + * @param s the shape (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>s</code> is <code>null</code>. + */ + public Area(Shape s) + { + this(); + + Vector p = makeSegment(s); + + // empty path + if (p == null) + return; + + // delete empty paths + for (int i = 0; i < p.size(); i++) + if (((Segment) p.elementAt(i)).getSignedArea() == 0.0) + p.remove(i--); + + /* + * Resolve self intersecting paths into non-intersecting + * solids and holes. + * Algorithm is as follows: + * 1: Create nodes at all self intersections + * 2: Put all segments into a list + * 3: Grab a segment, follow it, change direction at each node, + * removing segments from the list in the process + * 4: Repeat (3) until no segments remain in the list + * 5: Remove redundant paths and sort into solids and holes + */ + Vector paths = new Vector(); + Segment v; + + for (int i = 0; i < p.size(); i++) + { + Segment path = (Segment) p.elementAt(i); + createNodesSelf(path); + } + + if (p.size() > 1) + { + for (int i = 0; i < p.size() - 1; i++) + for (int j = i + 1; j < p.size(); j++) + { + Segment path1 = (Segment) p.elementAt(i); + Segment path2 = (Segment) p.elementAt(j); + createNodes(path1, path2); + } + } + + // we have intersecting points. + Vector segments = new Vector(); + + for (int i = 0; i < p.size(); i++) + { + Segment path = v = (Segment) p.elementAt(i); + do + { + segments.add(v); + v = v.next; + } + while (v != path); + } + + paths = weilerAtherton(segments); + deleteRedundantPaths(paths); + } + + /** + * Performs an add (union) operation on this area with another Area.<BR> + * @param area - the area to be unioned with this one + */ + public void add(Area area) + { + if (equals(area)) + return; + if (area.isEmpty()) + return; + + Area B = (Area) area.clone(); + + Vector pathA = new Vector(); + Vector pathB = new Vector(); + pathA.addAll(solids); + pathA.addAll(holes); + pathB.addAll(B.solids); + pathB.addAll(B.holes); + + int nNodes = 0; + + for (int i = 0; i < pathA.size(); i++) + { + Segment a = (Segment) pathA.elementAt(i); + for (int j = 0; j < pathB.size(); j++) + { + Segment b = (Segment) pathB.elementAt(j); + nNodes += createNodes(a, b); + } + } + + Vector paths = new Vector(); + Segment v; + + // we have intersecting points. + Vector segments = new Vector(); + + // In a union operation, we keep all + // segments of A oustide B and all B outside A + for (int i = 0; i < pathA.size(); i++) + { + v = (Segment) pathA.elementAt(i); + Segment path = v; + do + { + if (v.isSegmentOutside(area)) + segments.add(v); + v = v.next; + } + while (v != path); + } + + for (int i = 0; i < pathB.size(); i++) + { + v = (Segment) pathB.elementAt(i); + Segment path = v; + do + { + if (v.isSegmentOutside(this)) + segments.add(v); + v = v.next; + } + while (v != path); + } + + paths = weilerAtherton(segments); + deleteRedundantPaths(paths); + } + + /** + * Performs a subtraction operation on this Area.<BR> + * @param area the area to be subtracted from this area. + * @throws NullPointerException if <code>area</code> is <code>null</code>. + */ + public void subtract(Area area) + { + if (isEmpty() || area.isEmpty()) + return; + + if (equals(area)) + { + reset(); + return; + } + + Vector pathA = new Vector(); + Area B = (Area) area.clone(); + pathA.addAll(solids); + pathA.addAll(holes); + + // reverse the directions of B paths. + setDirection(B.holes, true); + setDirection(B.solids, false); + + Vector pathB = new Vector(); + pathB.addAll(B.solids); + pathB.addAll(B.holes); + + int nNodes = 0; + + // create nodes + for (int i = 0; i < pathA.size(); i++) + { + Segment a = (Segment) pathA.elementAt(i); + for (int j = 0; j < pathB.size(); j++) + { + Segment b = (Segment) pathB.elementAt(j); + nNodes += createNodes(a, b); + } + } + + Vector paths = new Vector(); + + // we have intersecting points. + Vector segments = new Vector(); + + // In a subtraction operation, we keep all + // segments of A oustide B and all B within A + // We outsideness-test only one segment in each path + // and the segments before and after any node + for (int i = 0; i < pathA.size(); i++) + { + Segment v = (Segment) pathA.elementAt(i); + Segment path = v; + if (v.isSegmentOutside(area) && v.node == null) + segments.add(v); + boolean node = false; + do + { + if ((v.node != null || node)) + { + node = (v.node != null); + if (v.isSegmentOutside(area)) + segments.add(v); + } + v = v.next; + } + while (v != path); + } + + for (int i = 0; i < pathB.size(); i++) + { + Segment v = (Segment) pathB.elementAt(i); + Segment path = v; + if (! v.isSegmentOutside(this) && v.node == null) + segments.add(v); + v = v.next; + boolean node = false; + do + { + if ((v.node != null || node)) + { + node = (v.node != null); + if (! v.isSegmentOutside(this)) + segments.add(v); + } + v = v.next; + } + while (v != path); + } + + paths = weilerAtherton(segments); + deleteRedundantPaths(paths); + } + + /** + * Performs an intersection operation on this Area.<BR> + * @param area - the area to be intersected with this area. + * @throws NullPointerException if <code>area</code> is <code>null</code>. + */ + public void intersect(Area area) + { + if (isEmpty() || area.isEmpty()) + { + reset(); + return; + } + if (equals(area)) + return; + + Vector pathA = new Vector(); + Area B = (Area) area.clone(); + pathA.addAll(solids); + pathA.addAll(holes); + + Vector pathB = new Vector(); + pathB.addAll(B.solids); + pathB.addAll(B.holes); + + int nNodes = 0; + + // create nodes + for (int i = 0; i < pathA.size(); i++) + { + Segment a = (Segment) pathA.elementAt(i); + for (int j = 0; j < pathB.size(); j++) + { + Segment b = (Segment) pathB.elementAt(j); + nNodes += createNodes(a, b); + } + } + + Vector paths = new Vector(); + + // we have intersecting points. + Vector segments = new Vector(); + + // In an intersection operation, we keep all + // segments of A within B and all B within A + // (The rest must be redundant) + // We outsideness-test only one segment in each path + // and the segments before and after any node + for (int i = 0; i < pathA.size(); i++) + { + Segment v = (Segment) pathA.elementAt(i); + Segment path = v; + if (! v.isSegmentOutside(area) && v.node == null) + segments.add(v); + boolean node = false; + do + { + if ((v.node != null || node)) + { + node = (v.node != null); + if (! v.isSegmentOutside(area)) + segments.add(v); + } + v = v.next; + } + while (v != path); + } + + for (int i = 0; i < pathB.size(); i++) + { + Segment v = (Segment) pathB.elementAt(i); + Segment path = v; + if (! v.isSegmentOutside(this) && v.node == null) + segments.add(v); + v = v.next; + boolean node = false; + do + { + if ((v.node != null || node)) + { + node = (v.node != null); + if (! v.isSegmentOutside(this)) + segments.add(v); + } + v = v.next; + } + while (v != path); + } + + paths = weilerAtherton(segments); + deleteRedundantPaths(paths); + } + + /** + * Performs an exclusive-or operation on this Area.<BR> + * @param area - the area to be XORed with this area. + * @throws NullPointerException if <code>area</code> is <code>null</code>. + */ + public void exclusiveOr(Area area) + { + if (area.isEmpty()) + return; + + if (isEmpty()) + { + Area B = (Area) area.clone(); + solids = B.solids; + holes = B.holes; + return; + } + if (equals(area)) + { + reset(); + return; + } + + Vector pathA = new Vector(); + + Area B = (Area) area.clone(); + Vector pathB = new Vector(); + pathA.addAll(solids); + pathA.addAll(holes); + + // reverse the directions of B paths. + setDirection(B.holes, true); + setDirection(B.solids, false); + pathB.addAll(B.solids); + pathB.addAll(B.holes); + + int nNodes = 0; + + for (int i = 0; i < pathA.size(); i++) + { + Segment a = (Segment) pathA.elementAt(i); + for (int j = 0; j < pathB.size(); j++) + { + Segment b = (Segment) pathB.elementAt(j); + nNodes += createNodes(a, b); + } + } + + Vector paths = new Vector(); + Segment v; + + // we have intersecting points. + Vector segments = new Vector(); + + // In an XOR operation, we operate on all segments + for (int i = 0; i < pathA.size(); i++) + { + v = (Segment) pathA.elementAt(i); + Segment path = v; + do + { + segments.add(v); + v = v.next; + } + while (v != path); + } + + for (int i = 0; i < pathB.size(); i++) + { + v = (Segment) pathB.elementAt(i); + Segment path = v; + do + { + segments.add(v); + v = v.next; + } + while (v != path); + } + + paths = weilerAtherton(segments); + deleteRedundantPaths(paths); + } + + /** + * Clears the Area object, creating an empty area. + */ + public void reset() + { + solids = new Vector(); + holes = new Vector(); + } + + /** + * Returns whether this area encloses any area. + * @return true if the object encloses any area. + */ + public boolean isEmpty() + { + if (solids.size() == 0) + return true; + + double totalArea = 0; + for (int i = 0; i < solids.size(); i++) + totalArea += Math.abs(((Segment) solids.elementAt(i)).getSignedArea()); + for (int i = 0; i < holes.size(); i++) + totalArea -= Math.abs(((Segment) holes.elementAt(i)).getSignedArea()); + if (totalArea <= EPSILON) + return true; + + return false; + } + + /** + * Determines whether the Area consists entirely of line segments + * @return true if the Area lines-only, false otherwise + */ + public boolean isPolygonal() + { + for (int i = 0; i < holes.size(); i++) + if (! ((Segment) holes.elementAt(i)).isPolygonal()) + return false; + for (int i = 0; i < solids.size(); i++) + if (! ((Segment) solids.elementAt(i)).isPolygonal()) + return false; + return true; + } + + /** + * Determines if the Area is rectangular.<P> + * + * This is strictly qualified. An area is considered rectangular if:<BR> + * <li>It consists of a single polygonal path.<BR> + * <li>It is oriented parallel/perpendicular to the xy axis<BR> + * <li>It must be exactly rectangular, i.e. small errors induced by + * transformations may cause a false result, although the area is + * visibly rectangular.<P> + * @return true if the above criteria are met, false otherwise + */ + public boolean isRectangular() + { + if (isEmpty()) + return true; + + if (holes.size() != 0 || solids.size() != 1) + return false; + + Segment path = (Segment) solids.elementAt(0); + if (! path.isPolygonal()) + return false; + + int nCorners = 0; + Segment s = path; + do + { + Segment s2 = s.next; + double d1 = (s.P2.getX() - s.P1.getX())*(s2.P2.getX() - s2.P1.getX())/ + ((s.P1.distance(s.P2)) * (s2.P1.distance(s2.P2))); + double d2 = (s.P2.getY() - s.P1.getY())*(s2.P2.getY() - s2.P1.getY())/ + ((s.P1.distance(s.P2)) * (s2.P1.distance(s2.P2))); + double dotproduct = d1 + d2; + + // For some reason, only rectangles on the XY axis count. + if (d1 != 0 && d2 != 0) + return false; + + if (Math.abs(dotproduct) == 0) // 90 degree angle + nCorners++; + else if ((Math.abs(1.0 - dotproduct) > 0)) // 0 degree angle? + return false; // if not, return false + + s = s.next; + } + while (s != path); + + return nCorners == 4; + } + + /** + * Returns whether the Area consists of more than one simple + * (non self-intersecting) subpath. + * + * @return true if the Area consists of none or one simple subpath, + * false otherwise. + */ + public boolean isSingular() + { + return (holes.size() == 0 && solids.size() <= 1); + } + + /** + * Returns the bounding box of the Area.<P> Unlike the CubicCurve2D and + * QuadraticCurve2D classes, this method will return the tightest possible + * bounding box, evaluating the extreme points of each curved segment.<P> + * @return the bounding box + */ + public Rectangle2D getBounds2D() + { + if (solids.size() == 0) + return new Rectangle2D.Double(0.0, 0.0, 0.0, 0.0); + + double xmin; + double xmax; + double ymin; + double ymax; + xmin = xmax = ((Segment) solids.elementAt(0)).P1.getX(); + ymin = ymax = ((Segment) solids.elementAt(0)).P1.getY(); + + for (int path = 0; path < solids.size(); path++) + { + Rectangle2D r = ((Segment) solids.elementAt(path)).getPathBounds(); + xmin = Math.min(r.getMinX(), xmin); + ymin = Math.min(r.getMinY(), ymin); + xmax = Math.max(r.getMaxX(), xmax); + ymax = Math.max(r.getMaxY(), ymax); + } + + return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin))); + } + + /** + * Returns the bounds of this object in Rectangle format. + * Please note that this may lead to loss of precision. + * + * @return The bounds. + * @see #getBounds2D() + */ + public Rectangle getBounds() + { + return getBounds2D().getBounds(); + } + + /** + * Create a new area of the same run-time type with the same contents as + * this one. + * + * @return the clone + */ + public Object clone() + { + try + { + Area clone = new Area(); + for (int i = 0; i < solids.size(); i++) + clone.solids.add(((Segment) solids.elementAt(i)).cloneSegmentList()); + for (int i = 0; i < holes.size(); i++) + clone.holes.add(((Segment) holes.elementAt(i)).cloneSegmentList()); + return clone; + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // Impossible + } + } + + /** + * Compares two Areas. + * + * @param area the area to compare against this area (<code>null</code> + * permitted). + * @return <code>true</code> if the areas are equal, and <code>false</code> + * otherwise. + */ + public boolean equals(Area area) + { + if (area == null) + return false; + + if (! getBounds2D().equals(area.getBounds2D())) + return false; + + if (solids.size() != area.solids.size() + || holes.size() != area.holes.size()) + return false; + + Vector pathA = new Vector(); + pathA.addAll(solids); + pathA.addAll(holes); + Vector pathB = new Vector(); + pathB.addAll(area.solids); + pathB.addAll(area.holes); + + int nPaths = pathA.size(); + boolean[][] match = new boolean[2][nPaths]; + + for (int i = 0; i < nPaths; i++) + { + for (int j = 0; j < nPaths; j++) + { + Segment p1 = (Segment) pathA.elementAt(i); + Segment p2 = (Segment) pathB.elementAt(j); + if (! match[0][i] && ! match[1][j]) + if (p1.pathEquals(p2)) + match[0][i] = match[1][j] = true; + } + } + + boolean result = true; + for (int i = 0; i < nPaths; i++) + result = result && match[0][i] && match[1][i]; + return result; + } + + /** + * Transforms this area by the AffineTransform at. + * + * @param at the transform. + */ + public void transform(AffineTransform at) + { + for (int i = 0; i < solids.size(); i++) + ((Segment) solids.elementAt(i)).transformSegmentList(at); + for (int i = 0; i < holes.size(); i++) + ((Segment) holes.elementAt(i)).transformSegmentList(at); + + // Note that the orientation is not invariant under inversion + if ((at.getType() & AffineTransform.TYPE_FLIP) != 0) + { + setDirection(holes, false); + setDirection(solids, true); + } + } + + /** + * Returns a new Area equal to this one, transformed + * by the AffineTransform at. + * @param at the transform. + * @return the transformed area + * @throws NullPointerException if <code>at</code> is <code>null</code>. + */ + public Area createTransformedArea(AffineTransform at) + { + Area a = (Area) clone(); + a.transform(at); + return a; + } + + /** + * Determines if the point (x,y) is contained within this Area. + * + * @param x the x-coordinate of the point. + * @param y the y-coordinate of the point. + * @return true if the point is contained, false otherwise. + */ + public boolean contains(double x, double y) + { + int n = 0; + for (int i = 0; i < solids.size(); i++) + if (((Segment) solids.elementAt(i)).contains(x, y)) + n++; + + for (int i = 0; i < holes.size(); i++) + if (((Segment) holes.elementAt(i)).contains(x, y)) + n--; + + return (n != 0); + } + + /** + * Determines if the Point2D p is contained within this Area. + * + * @param p the point. + * @return <code>true</code> if the point is contained, <code>false</code> + * otherwise. + * @throws NullPointerException if <code>p</code> is <code>null</code>. + */ + public boolean contains(Point2D p) + { + return contains(p.getX(), p.getY()); + } + + /** + * Determines if the rectangle specified by (x,y) as the upper-left + * and with width w and height h is completely contained within this Area, + * returns false otherwise.<P> + * + * This method should always produce the correct results, unlike for other + * classes in geom. + * + * @param x the x-coordinate of the rectangle. + * @param y the y-coordinate of the rectangle. + * @param w the width of the the rectangle. + * @param h the height of the rectangle. + * @return <code>true</code> if the rectangle is considered contained + */ + public boolean contains(double x, double y, double w, double h) + { + LineSegment[] l = new LineSegment[4]; + l[0] = new LineSegment(x, y, x + w, y); + l[1] = new LineSegment(x, y + h, x + w, y + h); + l[2] = new LineSegment(x, y, x, y + h); + l[3] = new LineSegment(x + w, y, x + w, y + h); + + // Since every segment in the area must a contour + // between inside/outside segments, ANY intersection + // will mean the rectangle is not entirely contained. + for (int i = 0; i < 4; i++) + { + for (int path = 0; path < solids.size(); path++) + { + Segment v; + Segment start; + start = v = (Segment) solids.elementAt(path); + do + { + if (l[i].hasIntersections(v)) + return false; + v = v.next; + } + while (v != start); + } + for (int path = 0; path < holes.size(); path++) + { + Segment v; + Segment start; + start = v = (Segment) holes.elementAt(path); + do + { + if (l[i].hasIntersections(v)) + return false; + v = v.next; + } + while (v != start); + } + } + + // Is any point inside? + if (! contains(x, y)) + return false; + + // Final hoop: Is the rectangle non-intersecting and inside, + // but encloses a hole? + Rectangle2D r = new Rectangle2D.Double(x, y, w, h); + for (int path = 0; path < holes.size(); path++) + if (! ((Segment) holes.elementAt(path)).isSegmentOutside(r)) + return false; + + return true; + } + + /** + * Determines if the Rectangle2D specified by r is completely contained + * within this Area, returns false otherwise.<P> + * + * This method should always produce the correct results, unlike for other + * classes in geom. + * + * @param r the rectangle. + * @return <code>true</code> if the rectangle is considered contained + * + * @throws NullPointerException if <code>r</code> is <code>null</code>. + */ + public boolean contains(Rectangle2D r) + { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Determines if the rectangle specified by (x,y) as the upper-left + * and with width w and height h intersects any part of this Area. + * + * @param x the x-coordinate for the rectangle. + * @param y the y-coordinate for the rectangle. + * @param w the width of the rectangle. + * @param h the height of the rectangle. + * @return <code>true</code> if the rectangle intersects the area, + * <code>false</code> otherwise. + */ + public boolean intersects(double x, double y, double w, double h) + { + if (solids.size() == 0) + return false; + + LineSegment[] l = new LineSegment[4]; + l[0] = new LineSegment(x, y, x + w, y); + l[1] = new LineSegment(x, y + h, x + w, y + h); + l[2] = new LineSegment(x, y, x, y + h); + l[3] = new LineSegment(x + w, y, x + w, y + h); + + // Return true on any intersection + for (int i = 0; i < 4; i++) + { + for (int path = 0; path < solids.size(); path++) + { + Segment v; + Segment start; + start = v = (Segment) solids.elementAt(path); + do + { + if (l[i].hasIntersections(v)) + return true; + v = v.next; + } + while (v != start); + } + for (int path = 0; path < holes.size(); path++) + { + Segment v; + Segment start; + start = v = (Segment) holes.elementAt(path); + do + { + if (l[i].hasIntersections(v)) + return true; + v = v.next; + } + while (v != start); + } + } + + // Non-intersecting, Is any point inside? + if (contains(x + w * 0.5, y + h * 0.5)) + return true; + + // What if the rectangle encloses the whole shape? + Point2D p = ((Segment) solids.elementAt(0)).getMidPoint(); + if ((new Rectangle2D.Double(x, y, w, h)).contains(p)) + return true; + return false; + } + + /** + * Determines if the Rectangle2D specified by r intersects any + * part of this Area. + * @param r the rectangle to test intersection with (<code>null</code> + * not permitted). + * @return <code>true</code> if the rectangle intersects the area, + * <code>false</code> otherwise. + * @throws NullPointerException if <code>r</code> is <code>null</code>. + */ + public boolean intersects(Rectangle2D r) + { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Returns a PathIterator object defining the contour of this Area, + * transformed by at. + * + * @param at the transform. + * @return A path iterator. + */ + public PathIterator getPathIterator(AffineTransform at) + { + return (new AreaIterator(at)); + } + + /** + * Returns a flattened PathIterator object defining the contour of this + * Area, transformed by at and with a defined flatness. + * + * @param at the transform. + * @param flatness the flatness. + * @return A path iterator. + */ + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return new FlatteningPathIterator(getPathIterator(at), flatness); + } + + //--------------------------------------------------------------------- + // Non-public methods and classes + + /** + * Private pathiterator object. + */ + private class AreaIterator implements PathIterator + { + private Vector segments; + private int index; + private AffineTransform at; + + // Simple compound type for segments + class IteratorSegment + { + int type; + double[] coords; + + IteratorSegment() + { + coords = new double[6]; + } + } + + /** + * The contructor here does most of the work, + * creates a vector of IteratorSegments, which can + * readily be returned + */ + public AreaIterator(AffineTransform at) + { + this.at = at; + index = 0; + segments = new Vector(); + Vector allpaths = new Vector(); + allpaths.addAll(solids); + allpaths.addAll(holes); + + for (int i = 0; i < allpaths.size(); i++) + { + Segment v = (Segment) allpaths.elementAt(i); + Segment start = v; + + IteratorSegment is = new IteratorSegment(); + is.type = SEG_MOVETO; + is.coords[0] = start.P1.getX(); + is.coords[1] = start.P1.getY(); + segments.add(is); + + do + { + is = new IteratorSegment(); + is.type = v.pathIteratorFormat(is.coords); + segments.add(is); + v = v.next; + } + while (v != start); + + is = new IteratorSegment(); + is.type = SEG_CLOSE; + segments.add(is); + } + } + + public int currentSegment(double[] coords) + { + IteratorSegment s = (IteratorSegment) segments.elementAt(index); + if (at != null) + at.transform(s.coords, 0, coords, 0, 3); + else + for (int i = 0; i < 6; i++) + coords[i] = s.coords[i]; + return (s.type); + } + + public int currentSegment(float[] coords) + { + IteratorSegment s = (IteratorSegment) segments.elementAt(index); + double[] d = new double[6]; + if (at != null) + { + at.transform(s.coords, 0, d, 0, 3); + for (int i = 0; i < 6; i++) + coords[i] = (float) d[i]; + } + else + for (int i = 0; i < 6; i++) + coords[i] = (float) s.coords[i]; + return (s.type); + } + + // Note that the winding rule should not matter here, + // EVEN_ODD is chosen because it renders faster. + public int getWindingRule() + { + return (PathIterator.WIND_EVEN_ODD); + } + + public boolean isDone() + { + return (index >= segments.size()); + } + + public void next() + { + index++; + } + } + + /** + * Performs the fundamental task of the Weiler-Atherton algorithm, + * traverse a list of segments, for each segment: + * Follow it, removing segments from the list and switching paths + * at each node. Do so until the starting segment is reached. + * + * Returns a Vector of the resulting paths. + */ + private Vector weilerAtherton(Vector segments) + { + Vector paths = new Vector(); + while (segments.size() > 0) + { + // Iterate over the path + Segment start = (Segment) segments.elementAt(0); + Segment s = start; + do + { + segments.remove(s); + if (s.node != null) + { // switch over + s.next = s.node; + s.node = null; + } + s = s.next; // continue + } + while (s != start); + + paths.add(start); + } + return paths; + } + + /** + * A small wrapper class to store intersection points + */ + private class Intersection + { + Point2D p; // the 2D point of intersection + double ta; // the parametric value on a + double tb; // the parametric value on b + Segment seg; // segment placeholder for node setting + + public Intersection(Point2D p, double ta, double tb) + { + this.p = p; + this.ta = ta; + this.tb = tb; + } + } + + /** + * Returns the recursion depth necessary to approximate the + * curve by line segments within the error RS_EPSILON. + * + * This is done with Wang's formula: + * L0 = max{0<=i<=N-2}(|xi - 2xi+1 + xi+2|,|yi - 2yi+1 + yi+2|) + * r0 = log4(sqrt(2)*N*(N-1)*L0/8e) + * Where e is the maximum distance error (RS_EPSILON) + */ + private int getRecursionDepth(CubicSegment curve) + { + double x0 = curve.P1.getX(); + double y0 = curve.P1.getY(); + + double x1 = curve.cp1.getX(); + double y1 = curve.cp1.getY(); + + double x2 = curve.cp2.getX(); + double y2 = curve.cp2.getY(); + + double x3 = curve.P2.getX(); + double y3 = curve.P2.getY(); + + double L0 = Math.max(Math.max(Math.abs(x0 - 2 * x1 + x2), + Math.abs(x1 - 2 * x2 + x3)), + Math.max(Math.abs(y0 - 2 * y1 + y2), + Math.abs(y1 - 2 * y2 + y3))); + + double f = Math.sqrt(2) * 6.0 * L0 / (8.0 * RS_EPSILON); + + int r0 = (int) Math.ceil(Math.log(f) / Math.log(4.0)); + return (r0); + } + + /** + * Performs recursive subdivision: + * @param c1 - curve 1 + * @param c2 - curve 2 + * @param depth1 - recursion depth of curve 1 + * @param depth2 - recursion depth of curve 2 + * @param t1 - global parametric value of the first curve's starting point + * @param t2 - global parametric value of the second curve's starting point + * @param w1 - global parametric length of curve 1 + * @param c1 - global parametric length of curve 2 + * + * The final four parameters are for keeping track of the parametric + * value of the curve. For a full curve t = 0, w = 1, w is halved with + * each subdivision. + */ + private void recursiveSubdivide(CubicCurve2D c1, CubicCurve2D c2, + int depth1, int depth2, double t1, + double t2, double w1, double w2) + { + boolean flat1 = depth1 <= 0; + boolean flat2 = depth2 <= 0; + + if (flat1 && flat2) + { + double xlk = c1.getP2().getX() - c1.getP1().getX(); + double ylk = c1.getP2().getY() - c1.getP1().getY(); + + double xnm = c2.getP2().getX() - c2.getP1().getX(); + double ynm = c2.getP2().getY() - c2.getP1().getY(); + + double xmk = c2.getP1().getX() - c1.getP1().getX(); + double ymk = c2.getP1().getY() - c1.getP1().getY(); + double det = xnm * ylk - ynm * xlk; + + if (det + 1.0 == 1.0) + return; + + double detinv = 1.0 / det; + double s = (xnm * ymk - ynm * xmk) * detinv; + double t = (xlk * ymk - ylk * xmk) * detinv; + if ((s < 0.0) || (s > 1.0) || (t < 0.0) || (t > 1.0)) + return; + + double[] temp = new double[2]; + temp[0] = t1 + s * w1; + temp[1] = t2 + t * w1; + cc_intersections.add(temp); + return; + } + + CubicCurve2D.Double c11 = new CubicCurve2D.Double(); + CubicCurve2D.Double c12 = new CubicCurve2D.Double(); + CubicCurve2D.Double c21 = new CubicCurve2D.Double(); + CubicCurve2D.Double c22 = new CubicCurve2D.Double(); + + if (! flat1 && ! flat2) + { + depth1--; + depth2--; + w1 = w1 * 0.5; + w2 = w2 * 0.5; + c1.subdivide(c11, c12); + c2.subdivide(c21, c22); + if (c11.getBounds2D().intersects(c21.getBounds2D())) + recursiveSubdivide(c11, c21, depth1, depth2, t1, t2, w1, w2); + if (c11.getBounds2D().intersects(c22.getBounds2D())) + recursiveSubdivide(c11, c22, depth1, depth2, t1, t2 + w2, w1, w2); + if (c12.getBounds2D().intersects(c21.getBounds2D())) + recursiveSubdivide(c12, c21, depth1, depth2, t1 + w1, t2, w1, w2); + if (c12.getBounds2D().intersects(c22.getBounds2D())) + recursiveSubdivide(c12, c22, depth1, depth2, t1 + w1, t2 + w2, w1, w2); + return; + } + + if (! flat1) + { + depth1--; + c1.subdivide(c11, c12); + w1 = w1 * 0.5; + if (c11.getBounds2D().intersects(c2.getBounds2D())) + recursiveSubdivide(c11, c2, depth1, depth2, t1, t2, w1, w2); + if (c12.getBounds2D().intersects(c2.getBounds2D())) + recursiveSubdivide(c12, c2, depth1, depth2, t1 + w1, t2, w1, w2); + return; + } + + depth2--; + c2.subdivide(c21, c22); + w2 = w2 * 0.5; + if (c1.getBounds2D().intersects(c21.getBounds2D())) + recursiveSubdivide(c1, c21, depth1, depth2, t1, t2, w1, w2); + if (c1.getBounds2D().intersects(c22.getBounds2D())) + recursiveSubdivide(c1, c22, depth1, depth2, t1, t2 + w2, w1, w2); + } + + /** + * Returns a set of interesections between two Cubic segments + * Or null if no intersections were found. + * + * The method used to find the intersection is recursive midpoint + * subdivision. Outline description: + * + * 1) Check if the bounding boxes of the curves intersect, + * 2) If so, divide the curves in the middle and test the bounding + * boxes again, + * 3) Repeat until a maximum recursion depth has been reached, where + * the intersecting curves can be approximated by line segments. + * + * This is a reasonably accurate method, although the recursion depth + * is typically around 20, the bounding-box tests allow for significant + * pruning of the subdivision tree. + * + * This is package-private to avoid an accessor method. + */ + Intersection[] cubicCubicIntersect(CubicSegment curve1, CubicSegment curve2) + { + Rectangle2D r1 = curve1.getBounds(); + Rectangle2D r2 = curve2.getBounds(); + + if (! r1.intersects(r2)) + return null; + + cc_intersections = new Vector(); + recursiveSubdivide(curve1.getCubicCurve2D(), curve2.getCubicCurve2D(), + getRecursionDepth(curve1), getRecursionDepth(curve2), + 0.0, 0.0, 1.0, 1.0); + + if (cc_intersections.size() == 0) + return null; + + Intersection[] results = new Intersection[cc_intersections.size()]; + for (int i = 0; i < cc_intersections.size(); i++) + { + double[] temp = (double[]) cc_intersections.elementAt(i); + results[i] = new Intersection(curve1.evaluatePoint(temp[0]), temp[0], + temp[1]); + } + cc_intersections = null; + return (results); + } + + /** + * Returns the intersections between a line and a quadratic bezier + * Or null if no intersections are found1 + * This is done through combining the line's equation with the + * parametric form of the Bezier and solving the resulting quadratic. + * This is package-private to avoid an accessor method. + */ + Intersection[] lineQuadIntersect(LineSegment l, QuadSegment c) + { + double[] y = new double[3]; + double[] x = new double[3]; + double[] r = new double[3]; + int nRoots; + double x0 = c.P1.getX(); + double y0 = c.P1.getY(); + double x1 = c.cp.getX(); + double y1 = c.cp.getY(); + double x2 = c.P2.getX(); + double y2 = c.P2.getY(); + + double lx0 = l.P1.getX(); + double ly0 = l.P1.getY(); + double lx1 = l.P2.getX(); + double ly1 = l.P2.getY(); + double dx = lx1 - lx0; + double dy = ly1 - ly0; + + // form r(t) = y(t) - x(t) for the bezier + y[0] = y0; + y[1] = 2 * (y1 - y0); + y[2] = (y2 - 2 * y1 + y0); + + x[0] = x0; + x[1] = 2 * (x1 - x0); + x[2] = (x2 - 2 * x1 + x0); + + // a point, not a line + if (dy == 0 && dx == 0) + return null; + + // line on y axis + if (dx == 0 || (dy / dx) > 1.0) + { + double k = dx / dy; + x[0] -= lx0; + y[0] -= ly0; + y[0] *= k; + y[1] *= k; + y[2] *= k; + } + else + { + double k = dy / dx; + x[0] -= lx0; + y[0] -= ly0; + x[0] *= k; + x[1] *= k; + x[2] *= k; + } + + for (int i = 0; i < 3; i++) + r[i] = y[i] - x[i]; + + if ((nRoots = QuadCurve2D.solveQuadratic(r)) > 0) + { + Intersection[] temp = new Intersection[nRoots]; + int intersections = 0; + for (int i = 0; i < nRoots; i++) + { + double t = r[i]; + if (t >= 0.0 && t <= 1.0) + { + Point2D p = c.evaluatePoint(t); + + // if the line is on an axis, snap the point to that axis. + if (dx == 0) + p.setLocation(lx0, p.getY()); + if (dy == 0) + p.setLocation(p.getX(), ly0); + + if (p.getX() <= Math.max(lx0, lx1) + && p.getX() >= Math.min(lx0, lx1) + && p.getY() <= Math.max(ly0, ly1) + && p.getY() >= Math.min(ly0, ly1)) + { + double lineparameter = p.distance(l.P1) / l.P2.distance(l.P1); + temp[i] = new Intersection(p, lineparameter, t); + intersections++; + } + } + else + temp[i] = null; + } + if (intersections == 0) + return null; + + Intersection[] rValues = new Intersection[intersections]; + + for (int i = 0; i < nRoots; i++) + if (temp[i] != null) + rValues[--intersections] = temp[i]; + return (rValues); + } + return null; + } + + /** + * Returns the intersections between a line and a cubic segment + * This is done through combining the line's equation with the + * parametric form of the Bezier and solving the resulting quadratic. + * This is package-private to avoid an accessor method. + */ + Intersection[] lineCubicIntersect(LineSegment l, CubicSegment c) + { + double[] y = new double[4]; + double[] x = new double[4]; + double[] r = new double[4]; + int nRoots; + double x0 = c.P1.getX(); + double y0 = c.P1.getY(); + double x1 = c.cp1.getX(); + double y1 = c.cp1.getY(); + double x2 = c.cp2.getX(); + double y2 = c.cp2.getY(); + double x3 = c.P2.getX(); + double y3 = c.P2.getY(); + + double lx0 = l.P1.getX(); + double ly0 = l.P1.getY(); + double lx1 = l.P2.getX(); + double ly1 = l.P2.getY(); + double dx = lx1 - lx0; + double dy = ly1 - ly0; + + // form r(t) = y(t) - x(t) for the bezier + y[0] = y0; + y[1] = 3 * (y1 - y0); + y[2] = 3 * (y2 + y0 - 2 * y1); + y[3] = y3 - 3 * y2 + 3 * y1 - y0; + + x[0] = x0; + x[1] = 3 * (x1 - x0); + x[2] = 3 * (x2 + x0 - 2 * x1); + x[3] = x3 - 3 * x2 + 3 * x1 - x0; + + // a point, not a line + if (dy == 0 && dx == 0) + return null; + + // line on y axis + if (dx == 0 || (dy / dx) > 1.0) + { + double k = dx / dy; + x[0] -= lx0; + y[0] -= ly0; + y[0] *= k; + y[1] *= k; + y[2] *= k; + y[3] *= k; + } + else + { + double k = dy / dx; + x[0] -= lx0; + y[0] -= ly0; + x[0] *= k; + x[1] *= k; + x[2] *= k; + x[3] *= k; + } + for (int i = 0; i < 4; i++) + r[i] = y[i] - x[i]; + + if ((nRoots = CubicCurve2D.solveCubic(r)) > 0) + { + Intersection[] temp = new Intersection[nRoots]; + int intersections = 0; + for (int i = 0; i < nRoots; i++) + { + double t = r[i]; + if (t >= 0.0 && t <= 1.0) + { + // if the line is on an axis, snap the point to that axis. + Point2D p = c.evaluatePoint(t); + if (dx == 0) + p.setLocation(lx0, p.getY()); + if (dy == 0) + p.setLocation(p.getX(), ly0); + + if (p.getX() <= Math.max(lx0, lx1) + && p.getX() >= Math.min(lx0, lx1) + && p.getY() <= Math.max(ly0, ly1) + && p.getY() >= Math.min(ly0, ly1)) + { + double lineparameter = p.distance(l.P1) / l.P2.distance(l.P1); + temp[i] = new Intersection(p, lineparameter, t); + intersections++; + } + } + else + temp[i] = null; + } + + if (intersections == 0) + return null; + + Intersection[] rValues = new Intersection[intersections]; + for (int i = 0; i < nRoots; i++) + if (temp[i] != null) + rValues[--intersections] = temp[i]; + return (rValues); + } + return null; + } + + /** + * Returns the intersection between two lines, or null if there is no + * intersection. + * This is package-private to avoid an accessor method. + */ + Intersection linesIntersect(LineSegment a, LineSegment b) + { + Point2D P1 = a.P1; + Point2D P2 = a.P2; + Point2D P3 = b.P1; + Point2D P4 = b.P2; + + if (! Line2D.linesIntersect(P1.getX(), P1.getY(), P2.getX(), P2.getY(), + P3.getX(), P3.getY(), P4.getX(), P4.getY())) + return null; + + double x1 = P1.getX(); + double y1 = P1.getY(); + double rx = P2.getX() - x1; + double ry = P2.getY() - y1; + + double x2 = P3.getX(); + double y2 = P3.getY(); + double sx = P4.getX() - x2; + double sy = P4.getY() - y2; + + double determinant = sx * ry - sy * rx; + double nom = (sx * (y2 - y1) + sy * (x1 - x2)); + + // Parallel lines don't intersect. At least we pretend they don't. + if (Math.abs(determinant) < EPSILON) + return null; + + nom = nom / determinant; + + if (nom == 0.0) + return null; + if (nom == 1.0) + return null; + + Point2D p = new Point2D.Double(x1 + nom * rx, y1 + nom * ry); + + return new Intersection(p, p.distance(P1) / P1.distance(P2), + p.distance(P3) / P3.distance(P4)); + } + + /** + * Determines if two points are equal, within an error margin + * 'snap distance' + * This is package-private to avoid an accessor method. + */ + boolean pointEquals(Point2D a, Point2D b) + { + return (a.equals(b) || a.distance(b) < PE_EPSILON); + } + + /** + * Helper method + * Turns a shape into a Vector of Segments + */ + private Vector makeSegment(Shape s) + { + Vector paths = new Vector(); + PathIterator pi = s.getPathIterator(null); + double[] coords = new double[6]; + Segment subpath = null; + Segment current = null; + double cx; + double cy; + double subpathx; + double subpathy; + cx = cy = subpathx = subpathy = 0.0; + + this.windingRule = pi.getWindingRule(); + + while (! pi.isDone()) + { + Segment v; + switch (pi.currentSegment(coords)) + { + case PathIterator.SEG_MOVETO: + if (subpath != null) + { // close existing open path + current.next = new LineSegment(cx, cy, subpathx, subpathy); + current = current.next; + current.next = subpath; + } + subpath = null; + subpathx = cx = coords[0]; + subpathy = cy = coords[1]; + break; + + // replace 'close' with a line-to. + case PathIterator.SEG_CLOSE: + if (subpath != null && (subpathx != cx || subpathy != cy)) + { + current.next = new LineSegment(cx, cy, subpathx, subpathy); + current = current.next; + current.next = subpath; + cx = subpathx; + cy = subpathy; + subpath = null; + } + else if (subpath != null) + { + current.next = subpath; + subpath = null; + } + break; + case PathIterator.SEG_LINETO: + if (cx != coords[0] || cy != coords[1]) + { + v = new LineSegment(cx, cy, coords[0], coords[1]); + if (subpath == null) + { + subpath = current = v; + paths.add(subpath); + } + else + { + current.next = v; + current = current.next; + } + cx = coords[0]; + cy = coords[1]; + } + break; + case PathIterator.SEG_QUADTO: + v = new QuadSegment(cx, cy, coords[0], coords[1], coords[2], + coords[3]); + if (subpath == null) + { + subpath = current = v; + paths.add(subpath); + } + else + { + current.next = v; + current = current.next; + } + cx = coords[2]; + cy = coords[3]; + break; + case PathIterator.SEG_CUBICTO: + v = new CubicSegment(cx, cy, coords[0], coords[1], coords[2], + coords[3], coords[4], coords[5]); + if (subpath == null) + { + subpath = current = v; + paths.add(subpath); + } + else + { + current.next = v; + current = current.next; + } + + // check if the cubic is self-intersecting + double[] lpts = ((CubicSegment) v).getLoop(); + if (lpts != null) + { + // if it is, break off the loop into its own path. + v.subdivideInsert(lpts[0]); + v.next.subdivideInsert((lpts[1] - lpts[0]) / (1.0 - lpts[0])); + + CubicSegment loop = (CubicSegment) v.next; + v.next = loop.next; + loop.next = loop; + + v.P2 = v.next.P1 = loop.P2 = loop.P1; // snap points + paths.add(loop); + current = v.next; + } + + cx = coords[4]; + cy = coords[5]; + break; + } + pi.next(); + } + + if (subpath != null) + { // close any open path + if (subpathx != cx || subpathy != cy) + { + current.next = new LineSegment(cx, cy, subpathx, subpathy); + current = current.next; + current.next = subpath; + } + else + current.next = subpath; + } + + if (paths.size() == 0) + return (null); + + return (paths); + } + + /** + * Find the intersections of two separate closed paths, + * A and B, split the segments at the intersection points, + * and create nodes pointing from one to the other + */ + private int createNodes(Segment A, Segment B) + { + int nNodes = 0; + + Segment a = A; + Segment b = B; + + do + { + do + { + nNodes += a.splitIntersections(b); + b = b.next; + } + while (b != B); + + a = a.next; // move to the next segment + } + while (a != A); // until one wrap. + + return (nNodes); + } + + /** + * Find the intersections of a path with itself. + * Splits the segments at the intersection points, + * and create nodes pointing from one to the other. + */ + private int createNodesSelf(Segment A) + { + int nNodes = 0; + Segment a = A; + + if (A.next == A) + return 0; + + do + { + Segment b = a.next; + do + { + if (b != a) // necessary + nNodes += a.splitIntersections(b); + b = b.next; + } + while (b != A); + a = a.next; // move to the next segment + } + while (a != A); // until one wrap. + + return (nNodes); + } + + /** + * Deletes paths which are redundant from a list, (i.e. solid areas within + * solid areas) Clears any nodes. Sorts the remaining paths into solids + * and holes, sets their orientation and sets the solids and holes lists. + */ + private void deleteRedundantPaths(Vector paths) + { + int npaths = paths.size(); + + int[][] contains = new int[npaths][npaths]; + int[][] windingNumbers = new int[npaths][2]; + int neg; + Rectangle2D[] bb = new Rectangle2D[npaths]; // path bounding boxes + + neg = ((windingRule == PathIterator.WIND_NON_ZERO) ? -1 : 1); + + for (int i = 0; i < npaths; i++) + bb[i] = ((Segment) paths.elementAt(i)).getPathBounds(); + + // Find which path contains which, assign winding numbers + for (int i = 0; i < npaths; i++) + { + Segment pathA = (Segment) paths.elementAt(i); + pathA.nullNodes(); // remove any now-redundant nodes, in case. + int windingA = pathA.hasClockwiseOrientation() ? 1 : neg; + + for (int j = 0; j < npaths; j++) + if (i != j) + { + Segment pathB = (Segment) paths.elementAt(j); + + // A contains B + if (bb[i].intersects(bb[j])) + { + Segment s = pathB.next; + while (s.P1.getY() == s.P2.getY() && s != pathB) + s = s.next; + Point2D p = s.getMidPoint(); + if (pathA.contains(p.getX(), p.getY())) + contains[i][j] = windingA; + } + else + // A does not contain B + contains[i][j] = 0; + } + else + contains[i][j] = windingA; // i == j + } + + for (int i = 0; i < npaths; i++) + { + windingNumbers[i][0] = 0; + for (int j = 0; j < npaths; j++) + windingNumbers[i][0] += contains[j][i]; + windingNumbers[i][1] = contains[i][i]; + } + + Vector solids = new Vector(); + Vector holes = new Vector(); + + if (windingRule == PathIterator.WIND_NON_ZERO) + { + for (int i = 0; i < npaths; i++) + { + if (windingNumbers[i][0] == 0) + holes.add(paths.elementAt(i)); + else if (windingNumbers[i][0] - windingNumbers[i][1] == 0 + && Math.abs(windingNumbers[i][0]) == 1) + solids.add(paths.elementAt(i)); + } + } + else + { + windingRule = PathIterator.WIND_NON_ZERO; + for (int i = 0; i < npaths; i++) + { + if ((windingNumbers[i][0] & 1) == 0) + holes.add(paths.elementAt(i)); + else if ((windingNumbers[i][0] & 1) == 1) + solids.add(paths.elementAt(i)); + } + } + + setDirection(holes, false); + setDirection(solids, true); + this.holes = holes; + this.solids = solids; + } + + /** + * Sets the winding direction of a Vector of paths + * @param clockwise gives the direction, + * true = clockwise, false = counter-clockwise + */ + private void setDirection(Vector paths, boolean clockwise) + { + Segment v; + for (int i = 0; i < paths.size(); i++) + { + v = (Segment) paths.elementAt(i); + if (clockwise != v.hasClockwiseOrientation()) + v.reverseAll(); + } + } + + /** + * Class representing a linked-list of vertices forming a closed polygon, + * convex or concave, without holes. + */ + private abstract class Segment implements Cloneable + { + // segment type, PathIterator segment types are used. + Point2D P1; + Point2D P2; + Segment next; + Segment node; + + Segment() + { + P1 = P2 = null; + node = next = null; + } + + /** + * Reverses the direction of a single segment + */ + abstract void reverseCoords(); + + /** + * Returns the segment's midpoint + */ + abstract Point2D getMidPoint(); + + /** + * Returns the bounding box of this segment + */ + abstract Rectangle2D getBounds(); + + /** + * Transforms a single segment + */ + abstract void transform(AffineTransform at); + + /** + * Returns the PathIterator type of a segment + */ + abstract int getType(); + + /** + */ + abstract int splitIntersections(Segment b); + + /** + * Returns the PathIterator coords of a segment + */ + abstract int pathIteratorFormat(double[] coords); + + /** + * Returns the number of intersections on the positive X axis, + * with the origin at (x,y), used for contains()-testing + * + * (Although that could be done by the line-intersect methods, + * a dedicated method is better to guarantee consitent handling + * of endpoint-special-cases) + */ + abstract int rayCrossing(double x, double y); + + /** + * Subdivides the segment at parametric value t, inserting + * the new segment into the linked list after this, + * such that this becomes [0,t] and this.next becomes [t,1] + */ + abstract void subdivideInsert(double t); + + /** + * Returns twice the area of a curve, relative the P1-P2 line + * Used for area calculations. + */ + abstract double curveArea(); + + /** + * Compare two segments. + */ + abstract boolean equals(Segment b); + + /** + * Determines if this path of segments contains the point (x,y) + */ + boolean contains(double x, double y) + { + Segment v = this; + int crossings = 0; + do + { + int n = v.rayCrossing(x, y); + crossings += n; + v = v.next; + } + while (v != this); + return ((crossings & 1) == 1); + } + + /** + * Nulls all nodes of the path. Clean up any 'hairs'. + */ + void nullNodes() + { + Segment v = this; + do + { + v.node = null; + v = v.next; + } + while (v != this); + } + + /** + * Transforms each segment in the closed path + */ + void transformSegmentList(AffineTransform at) + { + Segment v = this; + do + { + v.transform(at); + v = v.next; + } + while (v != this); + } + + /** + * Determines the winding direction of the path + * By the sign of the area. + */ + boolean hasClockwiseOrientation() + { + return (getSignedArea() > 0.0); + } + + /** + * Returns the bounds of this path + */ + public Rectangle2D getPathBounds() + { + double xmin; + double xmax; + double ymin; + double ymax; + xmin = xmax = P1.getX(); + ymin = ymax = P1.getY(); + + Segment v = this; + do + { + Rectangle2D r = v.getBounds(); + xmin = Math.min(r.getMinX(), xmin); + ymin = Math.min(r.getMinY(), ymin); + xmax = Math.max(r.getMaxX(), xmax); + ymax = Math.max(r.getMaxY(), ymax); + v = v.next; + } + while (v != this); + + return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin))); + } + + /** + * Calculates twice the signed area of the path; + */ + double getSignedArea() + { + Segment s; + double area = 0.0; + + s = this; + do + { + area += s.curveArea(); + + area += s.P1.getX() * s.next.P1.getY() + - s.P1.getY() * s.next.P1.getX(); + s = s.next; + } + while (s != this); + + return area; + } + + /** + * Reverses the orientation of the whole polygon + */ + void reverseAll() + { + reverseCoords(); + Segment v = next; + Segment former = this; + while (v != this) + { + v.reverseCoords(); + Segment vnext = v.next; + v.next = former; + former = v; + v = vnext; + } + next = former; + } + + /** + * Inserts a Segment after this one + */ + void insert(Segment v) + { + Segment n = next; + next = v; + v.next = n; + } + + /** + * Returns if this segment path is polygonal + */ + boolean isPolygonal() + { + Segment v = this; + do + { + if (! (v instanceof LineSegment)) + return false; + v = v.next; + } + while (v != this); + return true; + } + + /** + * Clones this path + */ + Segment cloneSegmentList() throws CloneNotSupportedException + { + Vector list = new Vector(); + Segment v = next; + + while (v != this) + { + list.add(v); + v = v.next; + } + + Segment clone = (Segment) this.clone(); + v = clone; + for (int i = 0; i < list.size(); i++) + { + clone.next = (Segment) ((Segment) list.elementAt(i)).clone(); + clone = clone.next; + } + clone.next = v; + return v; + } + + /** + * Creates a node between this segment and segment b + * at the given intersection + * @return the number of nodes created (0 or 1) + */ + int createNode(Segment b, Intersection i) + { + Point2D p = i.p; + if ((pointEquals(P1, p) || pointEquals(P2, p)) + && (pointEquals(b.P1, p) || pointEquals(b.P2, p))) + return 0; + + subdivideInsert(i.ta); + b.subdivideInsert(i.tb); + + // snap points + b.P2 = b.next.P1 = P2 = next.P1 = i.p; + + node = b.next; + b.node = next; + return 1; + } + + /** + * Creates multiple nodes from a list of intersections, + * This must be done in the order of ascending parameters, + * and the parameters must be recalculated in accordance + * with each split. + * @return the number of nodes created + */ + protected int createNodes(Segment b, Intersection[] x) + { + Vector v = new Vector(); + for (int i = 0; i < x.length; i++) + { + Point2D p = x[i].p; + if (! ((pointEquals(P1, p) || pointEquals(P2, p)) + && (pointEquals(b.P1, p) || pointEquals(b.P2, p)))) + v.add(x[i]); + } + + int nNodes = v.size(); + Intersection[] A = new Intersection[nNodes]; + Intersection[] B = new Intersection[nNodes]; + for (int i = 0; i < nNodes; i++) + A[i] = B[i] = (Intersection) v.elementAt(i); + + // Create two lists sorted by the parameter + // Bubble sort, OK I suppose, since the number of intersections + // cannot be larger than 9 (cubic-cubic worst case) anyway + for (int i = 0; i < nNodes - 1; i++) + { + for (int j = i + 1; j < nNodes; j++) + { + if (A[i].ta > A[j].ta) + { + Intersection swap = A[i]; + A[i] = A[j]; + A[j] = swap; + } + if (B[i].tb > B[j].tb) + { + Intersection swap = B[i]; + B[i] = B[j]; + B[j] = swap; + } + } + } + // subdivide a + Segment s = this; + for (int i = 0; i < nNodes; i++) + { + s.subdivideInsert(A[i].ta); + + // renormalize the parameters + for (int j = i + 1; j < nNodes; j++) + A[j].ta = (A[j].ta - A[i].ta) / (1.0 - A[i].ta); + + A[i].seg = s; + s = s.next; + } + + // subdivide b, set nodes + s = b; + for (int i = 0; i < nNodes; i++) + { + s.subdivideInsert(B[i].tb); + + for (int j = i + 1; j < nNodes; j++) + B[j].tb = (B[j].tb - B[i].tb) / (1.0 - B[i].tb); + + // set nodes + B[i].seg.node = s.next; // node a -> b + s.node = B[i].seg.next; // node b -> a + + // snap points + B[i].seg.P2 = B[i].seg.next.P1 = s.P2 = s.next.P1 = B[i].p; + s = s.next; + } + return nNodes; + } + + /** + * Determines if two paths are equal. + * Colinear line segments are ignored in the comparison. + */ + boolean pathEquals(Segment B) + { + if (! getPathBounds().equals(B.getPathBounds())) + return false; + + Segment startA = getTopLeft(); + Segment startB = B.getTopLeft(); + Segment a = startA; + Segment b = startB; + do + { + if (! a.equals(b)) + return false; + + if (a instanceof LineSegment) + a = ((LineSegment) a).lastCoLinear(); + if (b instanceof LineSegment) + b = ((LineSegment) b).lastCoLinear(); + + a = a.next; + b = b.next; + } + while (a != startA && b != startB); + return true; + } + + /** + * Return the segment with the top-leftmost first point + */ + Segment getTopLeft() + { + Segment v = this; + Segment tl = this; + do + { + if (v.P1.getY() < tl.P1.getY()) + tl = v; + else if (v.P1.getY() == tl.P1.getY()) + { + if (v.P1.getX() < tl.P1.getX()) + tl = v; + } + v = v.next; + } + while (v != this); + return tl; + } + + /** + * Returns if the path has a segment outside a shape + */ + boolean isSegmentOutside(Shape shape) + { + return ! shape.contains(getMidPoint()); + } + } // class Segment + + private class LineSegment extends Segment + { + public LineSegment(double x1, double y1, double x2, double y2) + { + super(); + P1 = new Point2D.Double(x1, y1); + P2 = new Point2D.Double(x2, y2); + } + + public LineSegment(Point2D p1, Point2D p2) + { + super(); + P1 = (Point2D) p1.clone(); + P2 = (Point2D) p2.clone(); + } + + /** + * Clones this segment + */ + public Object clone() + { + return new LineSegment(P1, P2); + } + + /** + * Transforms the segment + */ + void transform(AffineTransform at) + { + P1 = at.transform(P1, null); + P2 = at.transform(P2, null); + } + + /** + * Swap start and end points + */ + void reverseCoords() + { + Point2D p = P1; + P1 = P2; + P2 = p; + } + + /** + * Returns the segment's midpoint + */ + Point2D getMidPoint() + { + return (new Point2D.Double(0.5 * (P1.getX() + P2.getX()), + 0.5 * (P1.getY() + P2.getY()))); + } + + /** + * Returns twice the area of a curve, relative the P1-P2 line + * Obviously, a line does not enclose any area besides the line + */ + double curveArea() + { + return 0; + } + + /** + * Returns the PathIterator type of a segment + */ + int getType() + { + return (PathIterator.SEG_LINETO); + } + + /** + * Subdivides the segment at parametric value t, inserting + * the new segment into the linked list after this, + * such that this becomes [0,t] and this.next becomes [t,1] + */ + void subdivideInsert(double t) + { + Point2D p = new Point2D.Double((P2.getX() - P1.getX()) * t + P1.getX(), + (P2.getY() - P1.getY()) * t + P1.getY()); + insert(new LineSegment(p, P2)); + P2 = p; + next.node = node; + node = null; + } + + /** + * Determines if two line segments are strictly colinear + */ + boolean isCoLinear(LineSegment b) + { + double x1 = P1.getX(); + double y1 = P1.getY(); + double x2 = P2.getX(); + double y2 = P2.getY(); + double x3 = b.P1.getX(); + double y3 = b.P1.getY(); + double x4 = b.P2.getX(); + double y4 = b.P2.getY(); + + if ((y1 - y3) * (x4 - x3) - (x1 - x3) * (y4 - y3) != 0.0) + return false; + + return ((x2 - x1) * (y4 - y3) - (y2 - y1) * (x4 - x3) == 0.0); + } + + /** + * Return the last segment colinear with this one. + * Used in comparing paths. + */ + Segment lastCoLinear() + { + Segment prev = this; + Segment v = next; + + while (v instanceof LineSegment) + { + if (isCoLinear((LineSegment) v)) + { + prev = v; + v = v.next; + } + else + return prev; + } + return prev; + } + + /** + * Compare two segments. + * We must take into account that the lines may be broken into colinear + * subsegments and ignore them. + */ + boolean equals(Segment b) + { + if (! (b instanceof LineSegment)) + return false; + Point2D p1 = P1; + Point2D p3 = b.P1; + + if (! p1.equals(p3)) + return false; + + Point2D p2 = lastCoLinear().P2; + Point2D p4 = ((LineSegment) b).lastCoLinear().P2; + return (p2.equals(p4)); + } + + /** + * Returns a line segment + */ + int pathIteratorFormat(double[] coords) + { + coords[0] = P2.getX(); + coords[1] = P2.getY(); + return (PathIterator.SEG_LINETO); + } + + /** + * Returns if the line has intersections. + */ + boolean hasIntersections(Segment b) + { + if (b instanceof LineSegment) + return (linesIntersect(this, (LineSegment) b) != null); + + if (b instanceof QuadSegment) + return (lineQuadIntersect(this, (QuadSegment) b) != null); + + if (b instanceof CubicSegment) + return (lineCubicIntersect(this, (CubicSegment) b) != null); + + return false; + } + + /** + * Splits intersections into nodes, + * This one handles line-line, line-quadratic, line-cubic + */ + int splitIntersections(Segment b) + { + if (b instanceof LineSegment) + { + Intersection i = linesIntersect(this, (LineSegment) b); + + if (i == null) + return 0; + + return createNode(b, i); + } + + Intersection[] x = null; + + if (b instanceof QuadSegment) + x = lineQuadIntersect(this, (QuadSegment) b); + + if (b instanceof CubicSegment) + x = lineCubicIntersect(this, (CubicSegment) b); + + if (x == null) + return 0; + + if (x.length == 1) + return createNode(b, (Intersection) x[0]); + + return createNodes(b, x); + } + + /** + * Returns the bounding box of this segment + */ + Rectangle2D getBounds() + { + return (new Rectangle2D.Double(Math.min(P1.getX(), P2.getX()), + Math.min(P1.getY(), P2.getY()), + Math.abs(P1.getX() - P2.getX()), + Math.abs(P1.getY() - P2.getY()))); + } + + /** + * Returns the number of intersections on the positive X axis, + * with the origin at (x,y), used for contains()-testing + */ + int rayCrossing(double x, double y) + { + double x0 = P1.getX() - x; + double y0 = P1.getY() - y; + double x1 = P2.getX() - x; + double y1 = P2.getY() - y; + + if (y0 * y1 > 0) + return 0; + + if (x0 < 0 && x1 < 0) + return 0; + + if (y0 == 0.0) + y0 -= EPSILON; + + if (y1 == 0.0) + y1 -= EPSILON; + + if (Line2D.linesIntersect(x0, y0, x1, y1, + EPSILON, 0.0, Double.MAX_VALUE, 0.0)) + return 1; + return 0; + } + } // class LineSegment + + /** + * Quadratic Bezier curve segment + * + * Note: Most peers don't support quadratics directly, so it might make + * sense to represent them as cubics internally and just be done with it. + * I think we should be peer-agnostic, however, and stay faithful to the + * input geometry types as far as possible. + */ + private class QuadSegment extends Segment + { + Point2D cp; // control point + + /** + * Constructor, takes the coordinates of the start, control, + * and end point, respectively. + */ + QuadSegment(double x1, double y1, double cx, double cy, double x2, + double y2) + { + super(); + P1 = new Point2D.Double(x1, y1); + P2 = new Point2D.Double(x2, y2); + cp = new Point2D.Double(cx, cy); + } + + /** + * Clones this segment + */ + public Object clone() + { + return new QuadSegment(P1.getX(), P1.getY(), cp.getX(), cp.getY(), + P2.getX(), P2.getY()); + } + + /** + * Returns twice the area of a curve, relative the P1-P2 line + * + * The area formula can be derived by using Green's formula in the + * plane on the parametric form of the bezier. + */ + double curveArea() + { + double x0 = P1.getX(); + double y0 = P1.getY(); + double x1 = cp.getX(); + double y1 = cp.getY(); + double x2 = P2.getX(); + double y2 = P2.getY(); + + double P = (y2 - 2 * y1 + y0); + double Q = 2 * (y1 - y0); + + double A = (x2 - 2 * x1 + x0); + double B = 2 * (x1 - x0); + + double area = (B * P - A * Q) / 3.0; + return (area); + } + + /** + * Compare two segments. + */ + boolean equals(Segment b) + { + if (! (b instanceof QuadSegment)) + return false; + + return (P1.equals(b.P1) && cp.equals(((QuadSegment) b).cp) + && P2.equals(b.P2)); + } + + /** + * Returns a Point2D corresponding to the parametric value t + * of the curve + */ + Point2D evaluatePoint(double t) + { + double x0 = P1.getX(); + double y0 = P1.getY(); + double x1 = cp.getX(); + double y1 = cp.getY(); + double x2 = P2.getX(); + double y2 = P2.getY(); + + return new Point2D.Double(t * t * (x2 - 2 * x1 + x0) + 2 * t * (x1 - x0) + + x0, + t * t * (y2 - 2 * y1 + y0) + 2 * t * (y1 - y0) + + y0); + } + + /** + * Returns the bounding box of this segment + */ + Rectangle2D getBounds() + { + double x0 = P1.getX(); + double y0 = P1.getY(); + double x1 = cp.getX(); + double y1 = cp.getY(); + double x2 = P2.getX(); + double y2 = P2.getY(); + double r0; + double r1; + + double xmax = Math.max(x0, x2); + double ymax = Math.max(y0, y2); + double xmin = Math.min(x0, x2); + double ymin = Math.min(y0, y2); + + r0 = 2 * (y1 - y0); + r1 = 2 * (y2 - 2 * y1 + y0); + if (r1 != 0.0) + { + double t = -r0 / r1; + if (t > 0.0 && t < 1.0) + { + double y = evaluatePoint(t).getY(); + ymax = Math.max(y, ymax); + ymin = Math.min(y, ymin); + } + } + r0 = 2 * (x1 - x0); + r1 = 2 * (x2 - 2 * x1 + x0); + if (r1 != 0.0) + { + double t = -r0 / r1; + if (t > 0.0 && t < 1.0) + { + double x = evaluatePoint(t).getY(); + xmax = Math.max(x, xmax); + xmin = Math.min(x, xmin); + } + } + + return (new Rectangle2D.Double(xmin, ymin, xmax - xmin, ymax - ymin)); + } + + /** + * Returns a cubic segment corresponding to this curve + */ + CubicSegment getCubicSegment() + { + double x1 = P1.getX() + 2.0 * (cp.getX() - P1.getX()) / 3.0; + double y1 = P1.getY() + 2.0 * (cp.getY() - P1.getY()) / 3.0; + double x2 = cp.getX() + (P2.getX() - cp.getX()) / 3.0; + double y2 = cp.getY() + (P2.getY() - cp.getY()) / 3.0; + + return new CubicSegment(P1.getX(), P1.getY(), x1, y1, x2, y2, P2.getX(), + P2.getY()); + } + + /** + * Returns the segment's midpoint + */ + Point2D getMidPoint() + { + return evaluatePoint(0.5); + } + + /** + * Returns the PathIterator type of a segment + */ + int getType() + { + return (PathIterator.SEG_QUADTO); + } + + /** + * Returns the PathIterator coords of a segment + */ + int pathIteratorFormat(double[] coords) + { + coords[0] = cp.getX(); + coords[1] = cp.getY(); + coords[2] = P2.getX(); + coords[3] = P2.getY(); + return (PathIterator.SEG_QUADTO); + } + + /** + * Returns the number of intersections on the positive X axis, + * with the origin at (x,y), used for contains()-testing + */ + int rayCrossing(double x, double y) + { + double x0 = P1.getX() - x; + double y0 = P1.getY() - y; + double x1 = cp.getX() - x; + double y1 = cp.getY() - y; + double x2 = P2.getX() - x; + double y2 = P2.getY() - y; + double[] r = new double[3]; + int nRoots; + int nCrossings = 0; + + /* check if curve may intersect X+ axis. */ + if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0) && (y0 * y1 <= 0 || y1 * y2 <= 0)) + { + if (y0 == 0.0) + y0 -= EPSILON; + if (y2 == 0.0) + y2 -= EPSILON; + + r[0] = y0; + r[1] = 2 * (y1 - y0); + r[2] = (y2 - 2 * y1 + y0); + + nRoots = QuadCurve2D.solveQuadratic(r); + for (int i = 0; i < nRoots; i++) + if (r[i] > 0.0f && r[i] < 1.0f) + { + double t = r[i]; + if (t * t * (x2 - 2 * x1 + x0) + 2 * t * (x1 - x0) + x0 > 0.0) + nCrossings++; + } + } + return nCrossings; + } + + /** + * Swap start and end points + */ + void reverseCoords() + { + Point2D temp = P1; + P1 = P2; + P2 = temp; + } + + /** + * Splits intersections into nodes, + * This one handles quadratic-quadratic only, + * Quadratic-line is passed on to the LineSegment class, + * Quadratic-cubic is passed on to the CubicSegment class + */ + int splitIntersections(Segment b) + { + if (b instanceof LineSegment) + return (b.splitIntersections(this)); + + if (b instanceof CubicSegment) + return (b.splitIntersections(this)); + + if (b instanceof QuadSegment) + { + // Use the cubic-cubic intersection routine for quads as well, + // Since a quadratic can be exactly described as a cubic, this + // should not be a problem; + // The recursion depth will be the same in any case. + Intersection[] x = cubicCubicIntersect(getCubicSegment(), + ((QuadSegment) b) + .getCubicSegment()); + if (x == null) + return 0; + + if (x.length == 1) + return createNode(b, (Intersection) x[0]); + + return createNodes(b, x); + } + return 0; + } + + /** + * Subdivides the segment at parametric value t, inserting + * the new segment into the linked list after this, + * such that this becomes [0,t] and this.next becomes [t,1] + */ + void subdivideInsert(double t) + { + double x0 = P1.getX(); + double y0 = P1.getY(); + double x1 = cp.getX(); + double y1 = cp.getY(); + double x2 = P2.getX(); + double y2 = P2.getY(); + + double p10x = x0 + t * (x1 - x0); + double p10y = y0 + t * (y1 - y0); + double p11x = x1 + t * (x2 - x1); + double p11y = y1 + t * (y2 - y1); + double p20x = p10x + t * (p11x - p10x); + double p20y = p10y + t * (p11y - p10y); + + insert(new QuadSegment(p20x, p20y, p11x, p11y, x2, y2)); + P2 = next.P1; + cp.setLocation(p10x, p10y); + + next.node = node; + node = null; + } + + /** + * Transforms the segment + */ + void transform(AffineTransform at) + { + P1 = at.transform(P1, null); + P2 = at.transform(P2, null); + cp = at.transform(cp, null); + } + } // class QuadSegment + + /** + * Cubic Bezier curve segment + */ + private class CubicSegment extends Segment + { + Point2D cp1; // control points + Point2D cp2; // control points + + /** + * Constructor - takes coordinates of the starting point, + * first control point, second control point and end point, + * respecively. + */ + public CubicSegment(double x1, double y1, double c1x, double c1y, + double c2x, double c2y, double x2, double y2) + { + super(); + P1 = new Point2D.Double(x1, y1); + P2 = new Point2D.Double(x2, y2); + cp1 = new Point2D.Double(c1x, c1y); + cp2 = new Point2D.Double(c2x, c2y); + } + + /** + * Clones this segment + */ + public Object clone() + { + return new CubicSegment(P1.getX(), P1.getY(), cp1.getX(), cp1.getY(), + cp2.getX(), cp2.getY(), P2.getX(), P2.getY()); + } + + /** + * Returns twice the area of a curve, relative the P1-P2 line + * + * The area formula can be derived by using Green's formula in the + * plane on the parametric form of the bezier. + */ + double curveArea() + { + double x0 = P1.getX(); + double y0 = P1.getY(); + double x1 = cp1.getX(); + double y1 = cp1.getY(); + double x2 = cp2.getX(); + double y2 = cp2.getY(); + double x3 = P2.getX(); + double y3 = P2.getY(); + + double P = y3 - 3 * y2 + 3 * y1 - y0; + double Q = 3 * (y2 + y0 - 2 * y1); + double R = 3 * (y1 - y0); + + double A = x3 - 3 * x2 + 3 * x1 - x0; + double B = 3 * (x2 + x0 - 2 * x1); + double C = 3 * (x1 - x0); + + double area = (B * P - A * Q) / 5.0 + (C * P - A * R) / 2.0 + + (C * Q - B * R) / 3.0; + + return (area); + } + + /** + * Compare two segments. + */ + boolean equals(Segment b) + { + if (! (b instanceof CubicSegment)) + return false; + + return (P1.equals(b.P1) && cp1.equals(((CubicSegment) b).cp1) + && cp2.equals(((CubicSegment) b).cp2) && P2.equals(b.P2)); + } + + /** + * Returns a Point2D corresponding to the parametric value t + * of the curve + */ + Point2D evaluatePoint(double t) + { + double x0 = P1.getX(); + double y0 = P1.getY(); + double x1 = cp1.getX(); + double y1 = cp1.getY(); + double x2 = cp2.getX(); + double y2 = cp2.getY(); + double x3 = P2.getX(); + double y3 = P2.getY(); + + return new Point2D.Double(-(t * t * t) * (x0 - 3 * x1 + 3 * x2 - x3) + + 3 * t * t * (x0 - 2 * x1 + x2) + + 3 * t * (x1 - x0) + x0, + -(t * t * t) * (y0 - 3 * y1 + 3 * y2 - y3) + + 3 * t * t * (y0 - 2 * y1 + y2) + + 3 * t * (y1 - y0) + y0); + } + + /** + * Returns the bounding box of this segment + */ + Rectangle2D getBounds() + { + double x0 = P1.getX(); + double y0 = P1.getY(); + double x1 = cp1.getX(); + double y1 = cp1.getY(); + double x2 = cp2.getX(); + double y2 = cp2.getY(); + double x3 = P2.getX(); + double y3 = P2.getY(); + double[] r = new double[3]; + + double xmax = Math.max(x0, x3); + double ymax = Math.max(y0, y3); + double xmin = Math.min(x0, x3); + double ymin = Math.min(y0, y3); + + r[0] = 3 * (y1 - y0); + r[1] = 6.0 * (y2 + y0 - 2 * y1); + r[2] = 3.0 * (y3 - 3 * y2 + 3 * y1 - y0); + + int n = QuadCurve2D.solveQuadratic(r); + for (int i = 0; i < n; i++) + { + double t = r[i]; + if (t > 0 && t < 1.0) + { + double y = evaluatePoint(t).getY(); + ymax = Math.max(y, ymax); + ymin = Math.min(y, ymin); + } + } + + r[0] = 3 * (x1 - x0); + r[1] = 6.0 * (x2 + x0 - 2 * x1); + r[2] = 3.0 * (x3 - 3 * x2 + 3 * x1 - x0); + n = QuadCurve2D.solveQuadratic(r); + for (int i = 0; i < n; i++) + { + double t = r[i]; + if (t > 0 && t < 1.0) + { + double x = evaluatePoint(t).getX(); + xmax = Math.max(x, xmax); + xmin = Math.min(x, xmin); + } + } + return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin))); + } + + /** + * Returns a CubicCurve2D object corresponding to this segment. + */ + CubicCurve2D getCubicCurve2D() + { + return new CubicCurve2D.Double(P1.getX(), P1.getY(), cp1.getX(), + cp1.getY(), cp2.getX(), cp2.getY(), + P2.getX(), P2.getY()); + } + + /** + * Returns the parametric points of self-intersection if the cubic + * is self-intersecting, null otherwise. + */ + double[] getLoop() + { + double x0 = P1.getX(); + double y0 = P1.getY(); + double x1 = cp1.getX(); + double y1 = cp1.getY(); + double x2 = cp2.getX(); + double y2 = cp2.getY(); + double x3 = P2.getX(); + double y3 = P2.getY(); + double[] r = new double[4]; + double k; + double R; + double T; + double A; + double B; + double[] results = new double[2]; + + R = x3 - 3 * x2 + 3 * x1 - x0; + T = y3 - 3 * y2 + 3 * y1 - y0; + + // A qudratic + if (R == 0.0 && T == 0.0) + return null; + + // true cubic + if (R != 0.0 && T != 0.0) + { + A = 3 * (x2 + x0 - 2 * x1) / R; + B = 3 * (x1 - x0) / R; + + double P = 3 * (y2 + y0 - 2 * y1) / T; + double Q = 3 * (y1 - y0) / T; + + if (A == P || Q == B) + return null; + + k = (Q - B) / (A - P); + } + else + { + if (R == 0.0) + { + // quadratic in x + k = -(3 * (x1 - x0)) / (3 * (x2 + x0 - 2 * x1)); + A = 3 * (y2 + y0 - 2 * y1) / T; + B = 3 * (y1 - y0) / T; + } + else + { + // quadratic in y + k = -(3 * (y1 - y0)) / (3 * (y2 + y0 - 2 * y1)); + A = 3 * (x2 + x0 - 2 * x1) / R; + B = 3 * (x1 - x0) / R; + } + } + + r[0] = -k * k * k - A * k * k - B * k; + r[1] = 3 * k * k + 2 * k * A + 2 * B; + r[2] = -3 * k; + r[3] = 2; + + int n = CubicCurve2D.solveCubic(r); + if (n != 3) + return null; + + // sort r + double t; + for (int i = 0; i < 2; i++) + for (int j = i + 1; j < 3; j++) + if (r[j] < r[i]) + { + t = r[i]; + r[i] = r[j]; + r[j] = t; + } + + if (Math.abs(r[0] + r[2] - k) < 1E-13) + if (r[0] >= 0.0 && r[0] <= 1.0 && r[2] >= 0.0 && r[2] <= 1.0) + if (evaluatePoint(r[0]).distance(evaluatePoint(r[2])) < PE_EPSILON * 10) + { // we snap the points anyway + results[0] = r[0]; + results[1] = r[2]; + return (results); + } + return null; + } + + /** + * Returns the segment's midpoint + */ + Point2D getMidPoint() + { + return evaluatePoint(0.5); + } + + /** + * Returns the PathIterator type of a segment + */ + int getType() + { + return (PathIterator.SEG_CUBICTO); + } + + /** + * Returns the PathIterator coords of a segment + */ + int pathIteratorFormat(double[] coords) + { + coords[0] = cp1.getX(); + coords[1] = cp1.getY(); + coords[2] = cp2.getX(); + coords[3] = cp2.getY(); + coords[4] = P2.getX(); + coords[5] = P2.getY(); + return (PathIterator.SEG_CUBICTO); + } + + /** + * Returns the number of intersections on the positive X axis, + * with the origin at (x,y), used for contains()-testing + */ + int rayCrossing(double x, double y) + { + double x0 = P1.getX() - x; + double y0 = P1.getY() - y; + double x1 = cp1.getX() - x; + double y1 = cp1.getY() - y; + double x2 = cp2.getX() - x; + double y2 = cp2.getY() - y; + double x3 = P2.getX() - x; + double y3 = P2.getY() - y; + double[] r = new double[4]; + int nRoots; + int nCrossings = 0; + + /* check if curve may intersect X+ axis. */ + if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0 || x3 > 0.0) + && (y0 * y1 <= 0 || y1 * y2 <= 0 || y2 * y3 <= 0)) + { + if (y0 == 0.0) + y0 -= EPSILON; + if (y3 == 0.0) + y3 -= EPSILON; + + r[0] = y0; + r[1] = 3 * (y1 - y0); + r[2] = 3 * (y2 + y0 - 2 * y1); + r[3] = y3 - 3 * y2 + 3 * y1 - y0; + + if ((nRoots = CubicCurve2D.solveCubic(r)) > 0) + for (int i = 0; i < nRoots; i++) + { + if (r[i] > 0.0 && r[i] < 1.0) + { + double t = r[i]; + if (-(t * t * t) * (x0 - 3 * x1 + 3 * x2 - x3) + + 3 * t * t * (x0 - 2 * x1 + x2) + 3 * t * (x1 - x0) + + x0 > 0.0) + nCrossings++; + } + } + } + return nCrossings; + } + + /** + * Swap start and end points + */ + void reverseCoords() + { + Point2D p = P1; + P1 = P2; + P2 = p; + p = cp1; // swap control points + cp1 = cp2; + cp2 = p; + } + + /** + * Splits intersections into nodes, + * This one handles cubic-cubic and cubic-quadratic intersections + */ + int splitIntersections(Segment b) + { + if (b instanceof LineSegment) + return (b.splitIntersections(this)); + + Intersection[] x = null; + + if (b instanceof QuadSegment) + x = cubicCubicIntersect(this, ((QuadSegment) b).getCubicSegment()); + + if (b instanceof CubicSegment) + x = cubicCubicIntersect(this, (CubicSegment) b); + + if (x == null) + return 0; + + if (x.length == 1) + return createNode(b, x[0]); + + return createNodes(b, x); + } + + /** + * Subdivides the segment at parametric value t, inserting + * the new segment into the linked list after this, + * such that this becomes [0,t] and this.next becomes [t,1] + */ + void subdivideInsert(double t) + { + CubicSegment s = (CubicSegment) clone(); + double p1x = (s.cp1.getX() - s.P1.getX()) * t + s.P1.getX(); + double p1y = (s.cp1.getY() - s.P1.getY()) * t + s.P1.getY(); + + double px = (s.cp2.getX() - s.cp1.getX()) * t + s.cp1.getX(); + double py = (s.cp2.getY() - s.cp1.getY()) * t + s.cp1.getY(); + + s.cp2.setLocation((s.P2.getX() - s.cp2.getX()) * t + s.cp2.getX(), + (s.P2.getY() - s.cp2.getY()) * t + s.cp2.getY()); + + s.cp1.setLocation((s.cp2.getX() - px) * t + px, + (s.cp2.getY() - py) * t + py); + + double p2x = (px - p1x) * t + p1x; + double p2y = (py - p1y) * t + p1y; + + double p3x = (s.cp1.getX() - p2x) * t + p2x; + double p3y = (s.cp1.getY() - p2y) * t + p2y; + s.P1.setLocation(p3x, p3y); + + // insert new curve + insert(s); + + // set this curve + cp1.setLocation(p1x, p1y); + cp2.setLocation(p2x, p2y); + P2 = s.P1; + next.node = node; + node = null; + } + + /** + * Transforms the segment + */ + void transform(AffineTransform at) + { + P1 = at.transform(P1, null); + P2 = at.transform(P2, null); + cp1 = at.transform(cp1, null); + cp2 = at.transform(cp2, null); + } + } // class CubicSegment +} // class Area diff --git a/libjava/classpath/java/awt/geom/CubicCurve2D.java b/libjava/classpath/java/awt/geom/CubicCurve2D.java new file mode 100644 index 0000000..50c3811 --- /dev/null +++ b/libjava/classpath/java/awt/geom/CubicCurve2D.java @@ -0,0 +1,1724 @@ +/* CubicCurve2D.java -- represents a parameterized cubic curve in 2-D space + Copyright (C) 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.geom; + +import java.awt.Rectangle; +import java.awt.Shape; +import java.util.NoSuchElementException; + + +/** + * A two-dimensional curve that is parameterized with a cubic + * function. + * + * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" + * alt="A drawing of a CubicCurve2D" /> + * + * @author Eric Blake (ebb9@email.byu.edu) + * @author Graydon Hoare (graydon@redhat.com) + * @author Sascha Brawer (brawer@dandelis.ch) + * @author Sven de Marothy (sven@physto.se) + * + * @since 1.2 + */ +public abstract class CubicCurve2D implements Shape, Cloneable +{ + private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0; + private static final double EPSILON = 1E-10; + + /** + * Constructs a new CubicCurve2D. Typical users will want to + * construct instances of a subclass, such as {@link + * CubicCurve2D.Float} or {@link CubicCurve2D.Double}. + */ + protected CubicCurve2D() + { + } + + /** + * Returns the <i>x</i> coordinate of the curve’s start + * point. + */ + public abstract double getX1(); + + /** + * Returns the <i>y</i> coordinate of the curve’s start + * point. + */ + public abstract double getY1(); + + /** + * Returns the curve’s start point. + */ + public abstract Point2D getP1(); + + /** + * Returns the <i>x</i> coordinate of the curve’s first + * control point. + */ + public abstract double getCtrlX1(); + + /** + * Returns the <i>y</i> coordinate of the curve’s first + * control point. + */ + public abstract double getCtrlY1(); + + /** + * Returns the curve’s first control point. + */ + public abstract Point2D getCtrlP1(); + + /** + * Returns the <i>x</i> coordinate of the curve’s second + * control point. + */ + public abstract double getCtrlX2(); + + /** + * Returns the <i>y</i> coordinate of the curve’s second + * control point. + */ + public abstract double getCtrlY2(); + + /** + * Returns the curve’s second control point. + */ + public abstract Point2D getCtrlP2(); + + /** + * Returns the <i>x</i> coordinate of the curve’s end + * point. + */ + public abstract double getX2(); + + /** + * Returns the <i>y</i> coordinate of the curve’s end + * point. + */ + public abstract double getY2(); + + /** + * Returns the curve’s end point. + */ + public abstract Point2D getP2(); + + /** + * Changes the curve geometry, separately specifying each coordinate + * value. + * + * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" + * alt="A drawing of a CubicCurve2D" /> + * + * @param x1 the <i>x</i> coordinate of the curve’s new start + * point. + * + * @param y1 the <i>y</i> coordinate of the curve’s new start + * point. + * + * @param cx1 the <i>x</i> coordinate of the curve’s new + * first control point. + * + * @param cy1 the <i>y</i> coordinate of the curve’s new + * first control point. + * + * @param cx2 the <i>x</i> coordinate of the curve’s new + * second control point. + * + * @param cy2 the <i>y</i> coordinate of the curve’s new + * second control point. + * + * @param x2 the <i>x</i> coordinate of the curve’s new end + * point. + * + * @param y2 the <i>y</i> coordinate of the curve’s new end + * point. + */ + public abstract void setCurve(double x1, double y1, double cx1, double cy1, + double cx2, double cy2, double x2, double y2); + + /** + * Changes the curve geometry, specifying coordinate values in an + * array. + * + * @param coords an array containing the new coordinate values. The + * <i>x</i> coordinate of the new start point is located at + * <code>coords[offset]</code>, its <i>y</i> coordinate at + * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the + * new first control point is located at <code>coords[offset + + * 2]</code>, its <i>y</i> coordinate at <code>coords[offset + + * 3]</code>. The <i>x</i> coordinate of the new second control + * point is located at <code>coords[offset + 4]</code>, its <i>y</i> + * coordinate at <code>coords[offset + 5]</code>. The <i>x</i> + * coordinate of the new end point is located at <code>coords[offset + * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset + + * 7]</code>. + * + * @param offset the offset of the first coordinate value in + * <code>coords</code>. + */ + public void setCurve(double[] coords, int offset) + { + setCurve(coords[offset++], coords[offset++], coords[offset++], + coords[offset++], coords[offset++], coords[offset++], + coords[offset++], coords[offset++]); + } + + /** + * Changes the curve geometry, specifying coordinate values in + * separate Point objects. + * + * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" + * alt="A drawing of a CubicCurve2D" /> + * + * <p>The curve does not keep any reference to the passed point + * objects. Therefore, a later change to <code>p1</code>, + * <code>c1</code>, <code>c2</code> or <code>p2</code> will not + * affect the curve geometry. + * + * @param p1 the new start point. + * @param c1 the new first control point. + * @param c2 the new second control point. + * @param p2 the new end point. + */ + public void setCurve(Point2D p1, Point2D c1, Point2D c2, Point2D p2) + { + setCurve(p1.getX(), p1.getY(), c1.getX(), c1.getY(), c2.getX(), c2.getY(), + p2.getX(), p2.getY()); + } + + /** + * Changes the curve geometry, specifying coordinate values in an + * array of Point objects. + * + * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" + * alt="A drawing of a CubicCurve2D" /> + * + * <p>The curve does not keep references to the passed point + * objects. Therefore, a later change to the <code>pts</code> array + * or any of its elements will not affect the curve geometry. + * + * @param pts an array containing the points. The new start point + * is located at <code>pts[offset]</code>, the new first control + * point at <code>pts[offset + 1]</code>, the new second control + * point at <code>pts[offset + 2]</code>, and the new end point + * at <code>pts[offset + 3]</code>. + * + * @param offset the offset of the start point in <code>pts</code>. + */ + public void setCurve(Point2D[] pts, int offset) + { + setCurve(pts[offset].getX(), pts[offset++].getY(), pts[offset].getX(), + pts[offset++].getY(), pts[offset].getX(), pts[offset++].getY(), + pts[offset].getX(), pts[offset++].getY()); + } + + /** + * Changes the curve geometry to that of another curve. + * + * @param c the curve whose coordinates will be copied. + */ + public void setCurve(CubicCurve2D c) + { + setCurve(c.getX1(), c.getY1(), c.getCtrlX1(), c.getCtrlY1(), + c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2()); + } + + /** + * Calculates the squared flatness of a cubic curve, directly + * specifying each coordinate value. The flatness is the maximal + * distance of a control point to the line between start and end + * point. + * + * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. In comparison to C1, + * control point C2 is father away from the gray line. Therefore, + * the result will be the square of the distance between C2 and the + * gray line, i.e. the squared length of the red line. + * + * @param x1 the <i>x</i> coordinate of the start point P1. + * @param y1 the <i>y</i> coordinate of the start point P1. + * @param cx1 the <i>x</i> coordinate of the first control point C1. + * @param cy1 the <i>y</i> coordinate of the first control point C1. + * @param cx2 the <i>x</i> coordinate of the second control point C2. + * @param cy2 the <i>y</i> coordinate of the second control point C2. + * @param x2 the <i>x</i> coordinate of the end point P2. + * @param y2 the <i>y</i> coordinate of the end point P2. + */ + public static double getFlatnessSq(double x1, double y1, double cx1, + double cy1, double cx2, double cy2, + double x2, double y2) + { + return Math.max(Line2D.ptSegDistSq(x1, y1, x2, y2, cx1, cy1), + Line2D.ptSegDistSq(x1, y1, x2, y2, cx2, cy2)); + } + + /** + * Calculates the flatness of a cubic curve, directly specifying + * each coordinate value. The flatness is the maximal distance of a + * control point to the line between start and end point. + * + * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. In comparison to C1, + * control point C2 is father away from the gray line. Therefore, + * the result will be the distance between C2 and the gray line, + * i.e. the length of the red line. + * + * @param x1 the <i>x</i> coordinate of the start point P1. + * @param y1 the <i>y</i> coordinate of the start point P1. + * @param cx1 the <i>x</i> coordinate of the first control point C1. + * @param cy1 the <i>y</i> coordinate of the first control point C1. + * @param cx2 the <i>x</i> coordinate of the second control point C2. + * @param cy2 the <i>y</i> coordinate of the second control point C2. + * @param x2 the <i>x</i> coordinate of the end point P2. + * @param y2 the <i>y</i> coordinate of the end point P2. + */ + public static double getFlatness(double x1, double y1, double cx1, + double cy1, double cx2, double cy2, + double x2, double y2) + { + return Math.sqrt(getFlatnessSq(x1, y1, cx1, cy1, cx2, cy2, x2, y2)); + } + + /** + * Calculates the squared flatness of a cubic curve, specifying the + * coordinate values in an array. The flatness is the maximal + * distance of a control point to the line between start and end + * point. + * + * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. In comparison to C1, + * control point C2 is father away from the gray line. Therefore, + * the result will be the square of the distance between C2 and the + * gray line, i.e. the squared length of the red line. + * + * @param coords an array containing the coordinate values. The + * <i>x</i> coordinate of the start point P1 is located at + * <code>coords[offset]</code>, its <i>y</i> coordinate at + * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the + * first control point C1 is located at <code>coords[offset + + * 2]</code>, its <i>y</i> coordinate at <code>coords[offset + + * 3]</code>. The <i>x</i> coordinate of the second control point C2 + * is located at <code>coords[offset + 4]</code>, its <i>y</i> + * coordinate at <code>coords[offset + 5]</code>. The <i>x</i> + * coordinate of the end point P2 is located at <code>coords[offset + * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset + + * 7]</code>. + * + * @param offset the offset of the first coordinate value in + * <code>coords</code>. + */ + public static double getFlatnessSq(double[] coords, int offset) + { + return getFlatnessSq(coords[offset++], coords[offset++], coords[offset++], + coords[offset++], coords[offset++], coords[offset++], + coords[offset++], coords[offset++]); + } + + /** + * Calculates the flatness of a cubic curve, specifying the + * coordinate values in an array. The flatness is the maximal + * distance of a control point to the line between start and end + * point. + * + * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. In comparison to C1, + * control point C2 is father away from the gray line. Therefore, + * the result will be the distance between C2 and the gray line, + * i.e. the length of the red line. + * + * @param coords an array containing the coordinate values. The + * <i>x</i> coordinate of the start point P1 is located at + * <code>coords[offset]</code>, its <i>y</i> coordinate at + * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the + * first control point C1 is located at <code>coords[offset + + * 2]</code>, its <i>y</i> coordinate at <code>coords[offset + + * 3]</code>. The <i>x</i> coordinate of the second control point C2 + * is located at <code>coords[offset + 4]</code>, its <i>y</i> + * coordinate at <code>coords[offset + 5]</code>. The <i>x</i> + * coordinate of the end point P2 is located at <code>coords[offset + * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset + + * 7]</code>. + * + * @param offset the offset of the first coordinate value in + * <code>coords</code>. + */ + public static double getFlatness(double[] coords, int offset) + { + return Math.sqrt(getFlatnessSq(coords[offset++], coords[offset++], + coords[offset++], coords[offset++], + coords[offset++], coords[offset++], + coords[offset++], coords[offset++])); + } + + /** + * Calculates the squared flatness of this curve. The flatness is + * the maximal distance of a control point to the line between start + * and end point. + * + * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. In comparison to C1, + * control point C2 is father away from the gray line. Therefore, + * the result will be the square of the distance between C2 and the + * gray line, i.e. the squared length of the red line. + */ + public double getFlatnessSq() + { + return getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(), + getCtrlX2(), getCtrlY2(), getX2(), getY2()); + } + + /** + * Calculates the flatness of this curve. The flatness is the + * maximal distance of a control point to the line between start and + * end point. + * + * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. In comparison to C1, + * control point C2 is father away from the gray line. Therefore, + * the result will be the distance between C2 and the gray line, + * i.e. the length of the red line. + */ + public double getFlatness() + { + return Math.sqrt(getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(), + getCtrlX2(), getCtrlY2(), getX2(), getY2())); + } + + /** + * Subdivides this curve into two halves. + * + * <p><img src="doc-files/CubicCurve2D-3.png" width="700" + * height="180" alt="A drawing that illustrates the effects of + * subdividing a CubicCurve2D" /> + * + * @param left a curve whose geometry will be set to the left half + * of this curve, or <code>null</code> if the caller is not + * interested in the left half. + * + * @param right a curve whose geometry will be set to the right half + * of this curve, or <code>null</code> if the caller is not + * interested in the right half. + */ + public void subdivide(CubicCurve2D left, CubicCurve2D right) + { + // Use empty slots at end to share single array. + double[] d = new double[] + { + getX1(), getY1(), getCtrlX1(), getCtrlY1(), getCtrlX2(), + getCtrlY2(), getX2(), getY2(), 0, 0, 0, 0, 0, 0 + }; + subdivide(d, 0, d, 0, d, 6); + if (left != null) + left.setCurve(d, 0); + if (right != null) + right.setCurve(d, 6); + } + + /** + * Subdivides a cubic curve into two halves. + * + * <p><img src="doc-files/CubicCurve2D-3.png" width="700" + * height="180" alt="A drawing that illustrates the effects of + * subdividing a CubicCurve2D" /> + * + * @param src the curve to be subdivided. + * + * @param left a curve whose geometry will be set to the left half + * of <code>src</code>, or <code>null</code> if the caller is not + * interested in the left half. + * + * @param right a curve whose geometry will be set to the right half + * of <code>src</code>, or <code>null</code> if the caller is not + * interested in the right half. + */ + public static void subdivide(CubicCurve2D src, CubicCurve2D left, + CubicCurve2D right) + { + src.subdivide(left, right); + } + + /** + * Subdivides a cubic curve into two halves, passing all coordinates + * in an array. + * + * <p><img src="doc-files/CubicCurve2D-3.png" width="700" + * height="180" alt="A drawing that illustrates the effects of + * subdividing a CubicCurve2D" /> + * + * <p>The left end point and the right start point will always be + * identical. Memory-concious programmers thus may want to pass the + * same array for both <code>left</code> and <code>right</code>, and + * set <code>rightOff</code> to <code>leftOff + 6</code>. + * + * @param src an array containing the coordinates of the curve to be + * subdivided. The <i>x</i> coordinate of the start point P1 is + * located at <code>src[srcOff]</code>, its <i>y</i> at + * <code>src[srcOff + 1]</code>. The <i>x</i> coordinate of the + * first control point C1 is located at <code>src[srcOff + + * 2]</code>, its <i>y</i> at <code>src[srcOff + 3]</code>. The + * <i>x</i> coordinate of the second control point C2 is located at + * <code>src[srcOff + 4]</code>, its <i>y</i> at <code>src[srcOff + + * 5]</code>. The <i>x</i> coordinate of the end point is located at + * <code>src[srcOff + 6]</code>, its <i>y</i> at <code>src[srcOff + + * 7]</code>. + * + * @param srcOff an offset into <code>src</code>, specifying + * the index of the start point’s <i>x</i> coordinate. + * + * @param left an array that will receive the coordinates of the + * left half of <code>src</code>. It is acceptable to pass + * <code>src</code>. A caller who is not interested in the left half + * can pass <code>null</code>. + * + * @param leftOff an offset into <code>left</code>, specifying the + * index where the start point’s <i>x</i> coordinate will be + * stored. + * + * @param right an array that will receive the coordinates of the + * right half of <code>src</code>. It is acceptable to pass + * <code>src</code> or <code>left</code>. A caller who is not + * interested in the right half can pass <code>null</code>. + * + * @param rightOff an offset into <code>right</code>, specifying the + * index where the start point’s <i>x</i> coordinate will be + * stored. + */ + public static void subdivide(double[] src, int srcOff, double[] left, + int leftOff, double[] right, int rightOff) + { + // To understand this code, please have a look at the image + // "CubicCurve2D-3.png" in the sub-directory "doc-files". + double src_C1_x; + double src_C1_y; + double src_C2_x; + double src_C2_y; + double left_P1_x; + double left_P1_y; + double left_C1_x; + double left_C1_y; + double left_C2_x; + double left_C2_y; + double right_C1_x; + double right_C1_y; + double right_C2_x; + double right_C2_y; + double right_P2_x; + double right_P2_y; + double Mid_x; // Mid = left.P2 = right.P1 + double Mid_y; // Mid = left.P2 = right.P1 + + left_P1_x = src[srcOff]; + left_P1_y = src[srcOff + 1]; + src_C1_x = src[srcOff + 2]; + src_C1_y = src[srcOff + 3]; + src_C2_x = src[srcOff + 4]; + src_C2_y = src[srcOff + 5]; + right_P2_x = src[srcOff + 6]; + right_P2_y = src[srcOff + 7]; + + left_C1_x = (left_P1_x + src_C1_x) / 2; + left_C1_y = (left_P1_y + src_C1_y) / 2; + right_C2_x = (right_P2_x + src_C2_x) / 2; + right_C2_y = (right_P2_y + src_C2_y) / 2; + Mid_x = (src_C1_x + src_C2_x) / 2; + Mid_y = (src_C1_y + src_C2_y) / 2; + left_C2_x = (left_C1_x + Mid_x) / 2; + left_C2_y = (left_C1_y + Mid_y) / 2; + right_C1_x = (Mid_x + right_C2_x) / 2; + right_C1_y = (Mid_y + right_C2_y) / 2; + Mid_x = (left_C2_x + right_C1_x) / 2; + Mid_y = (left_C2_y + right_C1_y) / 2; + + if (left != null) + { + left[leftOff] = left_P1_x; + left[leftOff + 1] = left_P1_y; + left[leftOff + 2] = left_C1_x; + left[leftOff + 3] = left_C1_y; + left[leftOff + 4] = left_C2_x; + left[leftOff + 5] = left_C2_y; + left[leftOff + 6] = Mid_x; + left[leftOff + 7] = Mid_y; + } + + if (right != null) + { + right[rightOff] = Mid_x; + right[rightOff + 1] = Mid_y; + right[rightOff + 2] = right_C1_x; + right[rightOff + 3] = right_C1_y; + right[rightOff + 4] = right_C2_x; + right[rightOff + 5] = right_C2_y; + right[rightOff + 6] = right_P2_x; + right[rightOff + 7] = right_P2_y; + } + } + + /** + * Finds the non-complex roots of a cubic equation, placing the + * results into the same array as the equation coefficients. The + * following equation is being solved: + * + * <blockquote><code>eqn[3]</code> · <i>x</i><sup>3</sup> + * + <code>eqn[2]</code> · <i>x</i><sup>2</sup> + * + <code>eqn[1]</code> · <i>x</i> + * + <code>eqn[0]</code> + * = 0 + * </blockquote> + * + * <p>For some background about solving cubic equations, see the + * article <a + * href="http://planetmath.org/encyclopedia/CubicFormula.html" + * >“Cubic Formula”</a> in <a + * href="http://planetmath.org/" >PlanetMath</a>. For an extensive + * library of numerical algorithms written in the C programming + * language, see the <a href= "http://www.gnu.org/software/gsl/">GNU + * Scientific Library</a>, from which this implementation was + * adapted. + * + * @param eqn an array with the coefficients of the equation. When + * this procedure has returned, <code>eqn</code> will contain the + * non-complex solutions of the equation, in no particular order. + * + * @return the number of non-complex solutions. A result of 0 + * indicates that the equation has no non-complex solutions. A + * result of -1 indicates that the equation is constant (i.e., + * always or never zero). + * + * @see #solveCubic(double[], double[]) + * @see QuadCurve2D#solveQuadratic(double[],double[]) + * + * @author Brian Gough (bjg@network-theory.com) + * (original C implementation in the <a href= + * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>) + * + * @author Sascha Brawer (brawer@dandelis.ch) + * (adaptation to Java) + */ + public static int solveCubic(double[] eqn) + { + return solveCubic(eqn, eqn); + } + + /** + * Finds the non-complex roots of a cubic equation. The following + * equation is being solved: + * + * <blockquote><code>eqn[3]</code> · <i>x</i><sup>3</sup> + * + <code>eqn[2]</code> · <i>x</i><sup>2</sup> + * + <code>eqn[1]</code> · <i>x</i> + * + <code>eqn[0]</code> + * = 0 + * </blockquote> + * + * <p>For some background about solving cubic equations, see the + * article <a + * href="http://planetmath.org/encyclopedia/CubicFormula.html" + * >“Cubic Formula”</a> in <a + * href="http://planetmath.org/" >PlanetMath</a>. For an extensive + * library of numerical algorithms written in the C programming + * language, see the <a href= "http://www.gnu.org/software/gsl/">GNU + * Scientific Library</a>, from which this implementation was + * adapted. + * + * @see QuadCurve2D#solveQuadratic(double[],double[]) + * + * @param eqn an array with the coefficients of the equation. + * + * @param res an array into which the non-complex roots will be + * stored. The results may be in an arbitrary order. It is safe to + * pass the same array object reference for both <code>eqn</code> + * and <code>res</code>. + * + * @return the number of non-complex solutions. A result of 0 + * indicates that the equation has no non-complex solutions. A + * result of -1 indicates that the equation is constant (i.e., + * always or never zero). + * + * @author Brian Gough (bjg@network-theory.com) + * (original C implementation in the <a href= + * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>) + * + * @author Sascha Brawer (brawer@dandelis.ch) + * (adaptation to Java) + */ + public static int solveCubic(double[] eqn, double[] res) + { + // Adapted from poly/solve_cubic.c in the GNU Scientific Library + // (GSL), revision 1.7 of 2003-07-26. For the original source, see + // http://www.gnu.org/software/gsl/ + // + // Brian Gough, the author of that code, has granted the + // permission to use it in GNU Classpath under the GNU Classpath + // license, and has assigned the copyright to the Free Software + // Foundation. + // + // The Java implementation is very similar to the GSL code, but + // not a strict one-to-one copy. For example, GSL would sort the + // result. + + double a; + double b; + double c; + double q; + double r; + double Q; + double R; + double c3; + double Q3; + double R2; + double CR2; + double CQ3; + + // If the cubic coefficient is zero, we have a quadratic equation. + c3 = eqn[3]; + if (c3 == 0) + return QuadCurve2D.solveQuadratic(eqn, res); + + // Divide the equation by the cubic coefficient. + c = eqn[0] / c3; + b = eqn[1] / c3; + a = eqn[2] / c3; + + // We now need to solve x^3 + ax^2 + bx + c = 0. + q = a * a - 3 * b; + r = 2 * a * a * a - 9 * a * b + 27 * c; + + Q = q / 9; + R = r / 54; + + Q3 = Q * Q * Q; + R2 = R * R; + + CR2 = 729 * r * r; + CQ3 = 2916 * q * q * q; + + if (R == 0 && Q == 0) + { + // The GNU Scientific Library would return three identical + // solutions in this case. + res[0] = -a / 3; + return 1; + } + + if (CR2 == CQ3) + { + /* this test is actually R2 == Q3, written in a form suitable + for exact computation with integers */ + /* Due to finite precision some double roots may be missed, and + considered to be a pair of complex roots z = x +/- epsilon i + close to the real axis. */ + double sqrtQ = Math.sqrt(Q); + + if (R > 0) + { + res[0] = -2 * sqrtQ - a / 3; + res[1] = sqrtQ - a / 3; + } + else + { + res[0] = -sqrtQ - a / 3; + res[1] = 2 * sqrtQ - a / 3; + } + return 2; + } + + if (CR2 < CQ3) /* equivalent to R2 < Q3 */ + { + double sqrtQ = Math.sqrt(Q); + double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ; + double theta = Math.acos(R / sqrtQ3); + double norm = -2 * sqrtQ; + res[0] = norm * Math.cos(theta / 3) - a / 3; + res[1] = norm * Math.cos((theta + 2.0 * Math.PI) / 3) - a / 3; + res[2] = norm * Math.cos((theta - 2.0 * Math.PI) / 3) - a / 3; + + // The GNU Scientific Library sorts the results. We don't. + return 3; + } + + double sgnR = (R >= 0 ? 1 : -1); + double A = -sgnR * Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0 / 3.0); + double B = Q / A; + res[0] = A + B - a / 3; + return 1; + } + + /** + * Determines whether a position lies inside the area bounded + * by the curve and the straight line connecting its end points. + * + * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" + * alt="A drawing of the area spanned by the curve" /> + * + * <p>The above drawing illustrates in which area points are + * considered “inside” a CubicCurve2D. + */ + public boolean contains(double x, double y) + { + if (! getBounds2D().contains(x, y)) + return false; + + return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0); + } + + /** + * Determines whether a point lies inside the area bounded + * by the curve and the straight line connecting its end points. + * + * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" + * alt="A drawing of the area spanned by the curve" /> + * + * <p>The above drawing illustrates in which area points are + * considered “inside” a CubicCurve2D. + */ + public boolean contains(Point2D p) + { + return contains(p.getX(), p.getY()); + } + + /** + * Determines whether any part of a rectangle is inside the area bounded + * by the curve and the straight line connecting its end points. + * + * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" + * alt="A drawing of the area spanned by the curve" /> + * + * <p>The above drawing illustrates in which area points are + * considered “inside” in a CubicCurve2D. + * @see #contains(double, double) + */ + public boolean intersects(double x, double y, double w, double h) + { + if (! getBounds2D().contains(x, y, w, h)) + return false; + + /* Does any edge intersect? */ + if (getAxisIntersections(x, y, true, w) != 0 /* top */ + || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */ + || getAxisIntersections(x + w, y, false, h) != 0 /* right */ + || getAxisIntersections(x, y, false, h) != 0) /* left */ + return true; + + /* No intersections, is any point inside? */ + if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0) + return true; + + return false; + } + + /** + * Determines whether any part of a Rectangle2D is inside the area bounded + * by the curve and the straight line connecting its end points. + * @see #intersects(double, double, double, double) + */ + public boolean intersects(Rectangle2D r) + { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Determine whether a rectangle is entirely inside the area that is bounded + * by the curve and the straight line connecting its end points. + * + * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" + * alt="A drawing of the area spanned by the curve" /> + * + * <p>The above drawing illustrates in which area points are + * considered “inside” a CubicCurve2D. + * @see #contains(double, double) + */ + public boolean contains(double x, double y, double w, double h) + { + if (! getBounds2D().intersects(x, y, w, h)) + return false; + + /* Does any edge intersect? */ + if (getAxisIntersections(x, y, true, w) != 0 /* top */ + || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */ + || getAxisIntersections(x + w, y, false, h) != 0 /* right */ + || getAxisIntersections(x, y, false, h) != 0) /* left */ + return false; + + /* No intersections, is any point inside? */ + if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0) + return true; + + return false; + } + + /** + * Determine whether a Rectangle2D is entirely inside the area that is + * bounded by the curve and the straight line connecting its end points. + * + * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" + * alt="A drawing of the area spanned by the curve" /> + * + * <p>The above drawing illustrates in which area points are + * considered “inside” a CubicCurve2D. + * @see #contains(double, double) + */ + public boolean contains(Rectangle2D r) + { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Determines the smallest rectangle that encloses the + * curve’s start, end and control points. + */ + public Rectangle getBounds() + { + return getBounds2D().getBounds(); + } + + public PathIterator getPathIterator(final AffineTransform at) + { + return new PathIterator() + { + /** Current coordinate. */ + private int current = 0; + + public int getWindingRule() + { + return WIND_NON_ZERO; + } + + public boolean isDone() + { + return current >= 2; + } + + public void next() + { + current++; + } + + public int currentSegment(float[] coords) + { + int result; + switch (current) + { + case 0: + coords[0] = (float) getX1(); + coords[1] = (float) getY1(); + result = SEG_MOVETO; + break; + case 1: + coords[0] = (float) getCtrlX1(); + coords[1] = (float) getCtrlY1(); + coords[2] = (float) getCtrlX2(); + coords[3] = (float) getCtrlY2(); + coords[4] = (float) getX2(); + coords[5] = (float) getY2(); + result = SEG_CUBICTO; + break; + default: + throw new NoSuchElementException("cubic iterator out of bounds"); + } + if (at != null) + at.transform(coords, 0, coords, 0, 3); + return result; + } + + public int currentSegment(double[] coords) + { + int result; + switch (current) + { + case 0: + coords[0] = getX1(); + coords[1] = getY1(); + result = SEG_MOVETO; + break; + case 1: + coords[0] = getCtrlX1(); + coords[1] = getCtrlY1(); + coords[2] = getCtrlX2(); + coords[3] = getCtrlY2(); + coords[4] = getX2(); + coords[5] = getY2(); + result = SEG_CUBICTO; + break; + default: + throw new NoSuchElementException("cubic iterator out of bounds"); + } + if (at != null) + at.transform(coords, 0, coords, 0, 3); + return result; + } + }; + } + + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return new FlatteningPathIterator(getPathIterator(at), flatness); + } + + /** + * Create a new curve with the same contents as this one. + * + * @return the clone. + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // Impossible + } + } + + /** + * Helper method used by contains() and intersects() methods, that + * returns the number of curve/line intersections on a given axis + * extending from a certain point. + * + * @param x x coordinate of the origin point + * @param y y coordinate of the origin point + * @param useYaxis axis used, if true the positive Y axis is used, + * false uses the positive X axis. + * + * This is an implementation of the line-crossings algorithm, + * Detailed in an article on Eric Haines' page: + * http://www.acm.org/tog/editors/erich/ptinpoly/ + * + * A special-case not adressed in this code is self-intersections + * of the curve, e.g. if the axis intersects the self-itersection, + * the degenerate roots of the polynomial will erroneously count as + * a single intersection of the curve, and not two. + */ + private int getAxisIntersections(double x, double y, boolean useYaxis, + double distance) + { + int nCrossings = 0; + double a0; + double a1; + double a2; + double a3; + double b0; + double b1; + double b2; + double b3; + double[] r = new double[4]; + int nRoots; + + a0 = a3 = 0.0; + + if (useYaxis) + { + a0 = getY1() - y; + a1 = getCtrlY1() - y; + a2 = getCtrlY2() - y; + a3 = getY2() - y; + b0 = getX1() - x; + b1 = getCtrlX1() - x; + b2 = getCtrlX2() - x; + b3 = getX2() - x; + } + else + { + a0 = getX1() - x; + a1 = getCtrlX1() - x; + a2 = getCtrlX2() - x; + a3 = getX2() - x; + b0 = getY1() - y; + b1 = getCtrlY1() - y; + b2 = getCtrlY2() - y; + b3 = getY2() - y; + } + + /* If the axis intersects a start/endpoint, shift it up by some small + amount to guarantee the line is 'inside' + If this is not done, bad behaviour may result for points on that axis.*/ + if (a0 == 0.0 || a3 == 0.0) + { + double small = getFlatness() * EPSILON; + if (a0 == 0.0) + a0 -= small; + if (a3 == 0.0) + a3 -= small; + } + + if (useYaxis) + { + if (Line2D.linesIntersect(b0, a0, b3, a3, EPSILON, 0.0, distance, 0.0)) + nCrossings++; + } + else + { + if (Line2D.linesIntersect(a0, b0, a3, b3, 0.0, EPSILON, 0.0, distance)) + nCrossings++; + } + + r[0] = a0; + r[1] = 3 * (a1 - a0); + r[2] = 3 * (a2 + a0 - 2 * a1); + r[3] = a3 - 3 * a2 + 3 * a1 - a0; + + if ((nRoots = solveCubic(r)) != 0) + for (int i = 0; i < nRoots; i++) + { + double t = r[i]; + if (t >= 0.0 && t <= 1.0) + { + double crossing = -(t * t * t) * (b0 - 3 * b1 + 3 * b2 - b3) + + 3 * t * t * (b0 - 2 * b1 + b2) + + 3 * t * (b1 - b0) + b0; + if (crossing > 0.0 && crossing <= distance) + nCrossings++; + } + } + + return (nCrossings); + } + + /** + * A two-dimensional curve that is parameterized with a cubic + * function and stores coordinate values in double-precision + * floating-point format. + * + * @see CubicCurve2D.Float + * + * @author Eric Blake (ebb9@email.byu.edu) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class Double extends CubicCurve2D + { + /** + * The <i>x</i> coordinate of the curve’s start point. + */ + public double x1; + + /** + * The <i>y</i> coordinate of the curve’s start point. + */ + public double y1; + + /** + * The <i>x</i> coordinate of the curve’s first control point. + */ + public double ctrlx1; + + /** + * The <i>y</i> coordinate of the curve’s first control point. + */ + public double ctrly1; + + /** + * The <i>x</i> coordinate of the curve’s second control point. + */ + public double ctrlx2; + + /** + * The <i>y</i> coordinate of the curve’s second control point. + */ + public double ctrly2; + + /** + * The <i>x</i> coordinate of the curve’s end point. + */ + public double x2; + + /** + * The <i>y</i> coordinate of the curve’s end point. + */ + public double y2; + + /** + * Constructs a new CubicCurve2D that stores its coordinate values + * in double-precision floating-point format. All points are + * initially at position (0, 0). + */ + public Double() + { + } + + /** + * Constructs a new CubicCurve2D that stores its coordinate values + * in double-precision floating-point format, specifying the + * initial position of each point. + * + * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" + * alt="A drawing of a CubicCurve2D" /> + * + * @param x1 the <i>x</i> coordinate of the curve’s start + * point. + * + * @param y1 the <i>y</i> coordinate of the curve’s start + * point. + * + * @param cx1 the <i>x</i> coordinate of the curve’s first + * control point. + * + * @param cy1 the <i>y</i> coordinate of the curve’s first + * control point. + * + * @param cx2 the <i>x</i> coordinate of the curve’s second + * control point. + * + * @param cy2 the <i>y</i> coordinate of the curve’s second + * control point. + * + * @param x2 the <i>x</i> coordinate of the curve’s end + * point. + * + * @param y2 the <i>y</i> coordinate of the curve’s end + * point. + */ + public Double(double x1, double y1, double cx1, double cy1, double cx2, + double cy2, double x2, double y2) + { + this.x1 = x1; + this.y1 = y1; + ctrlx1 = cx1; + ctrly1 = cy1; + ctrlx2 = cx2; + ctrly2 = cy2; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Returns the <i>x</i> coordinate of the curve’s start + * point. + */ + public double getX1() + { + return x1; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s start + * point. + */ + public double getY1() + { + return y1; + } + + /** + * Returns the curve’s start point. + */ + public Point2D getP1() + { + return new Point2D.Double(x1, y1); + } + + /** + * Returns the <i>x</i> coordinate of the curve’s first + * control point. + */ + public double getCtrlX1() + { + return ctrlx1; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s first + * control point. + */ + public double getCtrlY1() + { + return ctrly1; + } + + /** + * Returns the curve’s first control point. + */ + public Point2D getCtrlP1() + { + return new Point2D.Double(ctrlx1, ctrly1); + } + + /** + * Returns the <i>x</i> coordinate of the curve’s second + * control point. + */ + public double getCtrlX2() + { + return ctrlx2; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s second + * control point. + */ + public double getCtrlY2() + { + return ctrly2; + } + + /** + * Returns the curve’s second control point. + */ + public Point2D getCtrlP2() + { + return new Point2D.Double(ctrlx2, ctrly2); + } + + /** + * Returns the <i>x</i> coordinate of the curve’s end + * point. + */ + public double getX2() + { + return x2; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s end + * point. + */ + public double getY2() + { + return y2; + } + + /** + * Returns the curve’s end point. + */ + public Point2D getP2() + { + return new Point2D.Double(x2, y2); + } + + /** + * Changes the curve geometry, separately specifying each coordinate + * value. + * + * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" + * alt="A drawing of a CubicCurve2D" /> + * + * @param x1 the <i>x</i> coordinate of the curve’s new start + * point. + * + * @param y1 the <i>y</i> coordinate of the curve’s new start + * point. + * + * @param cx1 the <i>x</i> coordinate of the curve’s new + * first control point. + * + * @param cy1 the <i>y</i> coordinate of the curve’s new + * first control point. + * + * @param cx2 the <i>x</i> coordinate of the curve’s new + * second control point. + * + * @param cy2 the <i>y</i> coordinate of the curve’s new + * second control point. + * + * @param x2 the <i>x</i> coordinate of the curve’s new end + * point. + * + * @param y2 the <i>y</i> coordinate of the curve’s new end + * point. + */ + public void setCurve(double x1, double y1, double cx1, double cy1, + double cx2, double cy2, double x2, double y2) + { + this.x1 = x1; + this.y1 = y1; + ctrlx1 = cx1; + ctrly1 = cy1; + ctrlx2 = cx2; + ctrly2 = cy2; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Determines the smallest rectangle that encloses the + * curve’s start, end and control points. As the + * illustration below shows, the invisible control points may cause + * the bounds to be much larger than the area that is actually + * covered by the curve. + * + * <p><img src="doc-files/CubicCurve2D-2.png" width="350" height="180" + * alt="An illustration of the bounds of a CubicCurve2D" /> + */ + public Rectangle2D getBounds2D() + { + double nx1 = Math.min(Math.min(x1, ctrlx1), Math.min(ctrlx2, x2)); + double ny1 = Math.min(Math.min(y1, ctrly1), Math.min(ctrly2, y2)); + double nx2 = Math.max(Math.max(x1, ctrlx1), Math.max(ctrlx2, x2)); + double ny2 = Math.max(Math.max(y1, ctrly1), Math.max(ctrly2, y2)); + return new Rectangle2D.Double(nx1, ny1, nx2 - nx1, ny2 - ny1); + } + } + + /** + * A two-dimensional curve that is parameterized with a cubic + * function and stores coordinate values in single-precision + * floating-point format. + * + * @see CubicCurve2D.Float + * + * @author Eric Blake (ebb9@email.byu.edu) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class Float extends CubicCurve2D + { + /** + * The <i>x</i> coordinate of the curve’s start point. + */ + public float x1; + + /** + * The <i>y</i> coordinate of the curve’s start point. + */ + public float y1; + + /** + * The <i>x</i> coordinate of the curve’s first control point. + */ + public float ctrlx1; + + /** + * The <i>y</i> coordinate of the curve’s first control point. + */ + public float ctrly1; + + /** + * The <i>x</i> coordinate of the curve’s second control point. + */ + public float ctrlx2; + + /** + * The <i>y</i> coordinate of the curve’s second control point. + */ + public float ctrly2; + + /** + * The <i>x</i> coordinate of the curve’s end point. + */ + public float x2; + + /** + * The <i>y</i> coordinate of the curve’s end point. + */ + public float y2; + + /** + * Constructs a new CubicCurve2D that stores its coordinate values + * in single-precision floating-point format. All points are + * initially at position (0, 0). + */ + public Float() + { + } + + /** + * Constructs a new CubicCurve2D that stores its coordinate values + * in single-precision floating-point format, specifying the + * initial position of each point. + * + * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" + * alt="A drawing of a CubicCurve2D" /> + * + * @param x1 the <i>x</i> coordinate of the curve’s start + * point. + * + * @param y1 the <i>y</i> coordinate of the curve’s start + * point. + * + * @param cx1 the <i>x</i> coordinate of the curve’s first + * control point. + * + * @param cy1 the <i>y</i> coordinate of the curve’s first + * control point. + * + * @param cx2 the <i>x</i> coordinate of the curve’s second + * control point. + * + * @param cy2 the <i>y</i> coordinate of the curve’s second + * control point. + * + * @param x2 the <i>x</i> coordinate of the curve’s end + * point. + * + * @param y2 the <i>y</i> coordinate of the curve’s end + * point. + */ + public Float(float x1, float y1, float cx1, float cy1, float cx2, + float cy2, float x2, float y2) + { + this.x1 = x1; + this.y1 = y1; + ctrlx1 = cx1; + ctrly1 = cy1; + ctrlx2 = cx2; + ctrly2 = cy2; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Returns the <i>x</i> coordinate of the curve’s start + * point. + */ + public double getX1() + { + return x1; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s start + * point. + */ + public double getY1() + { + return y1; + } + + /** + * Returns the curve’s start point. + */ + public Point2D getP1() + { + return new Point2D.Float(x1, y1); + } + + /** + * Returns the <i>x</i> coordinate of the curve’s first + * control point. + */ + public double getCtrlX1() + { + return ctrlx1; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s first + * control point. + */ + public double getCtrlY1() + { + return ctrly1; + } + + /** + * Returns the curve’s first control point. + */ + public Point2D getCtrlP1() + { + return new Point2D.Float(ctrlx1, ctrly1); + } + + /** + * Returns the <i>s</i> coordinate of the curve’s second + * control point. + */ + public double getCtrlX2() + { + return ctrlx2; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s second + * control point. + */ + public double getCtrlY2() + { + return ctrly2; + } + + /** + * Returns the curve’s second control point. + */ + public Point2D getCtrlP2() + { + return new Point2D.Float(ctrlx2, ctrly2); + } + + /** + * Returns the <i>x</i> coordinate of the curve’s end + * point. + */ + public double getX2() + { + return x2; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s end + * point. + */ + public double getY2() + { + return y2; + } + + /** + * Returns the curve’s end point. + */ + public Point2D getP2() + { + return new Point2D.Float(x2, y2); + } + + /** + * Changes the curve geometry, separately specifying each coordinate + * value as a double-precision floating-point number. + * + * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" + * alt="A drawing of a CubicCurve2D" /> + * + * @param x1 the <i>x</i> coordinate of the curve’s new start + * point. + * + * @param y1 the <i>y</i> coordinate of the curve’s new start + * point. + * + * @param cx1 the <i>x</i> coordinate of the curve’s new + * first control point. + * + * @param cy1 the <i>y</i> coordinate of the curve’s new + * first control point. + * + * @param cx2 the <i>x</i> coordinate of the curve’s new + * second control point. + * + * @param cy2 the <i>y</i> coordinate of the curve’s new + * second control point. + * + * @param x2 the <i>x</i> coordinate of the curve’s new end + * point. + * + * @param y2 the <i>y</i> coordinate of the curve’s new end + * point. + */ + public void setCurve(double x1, double y1, double cx1, double cy1, + double cx2, double cy2, double x2, double y2) + { + this.x1 = (float) x1; + this.y1 = (float) y1; + ctrlx1 = (float) cx1; + ctrly1 = (float) cy1; + ctrlx2 = (float) cx2; + ctrly2 = (float) cy2; + this.x2 = (float) x2; + this.y2 = (float) y2; + } + + /** + * Changes the curve geometry, separately specifying each coordinate + * value as a single-precision floating-point number. + * + * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" + * alt="A drawing of a CubicCurve2D" /> + * + * @param x1 the <i>x</i> coordinate of the curve’s new start + * point. + * + * @param y1 the <i>y</i> coordinate of the curve’s new start + * point. + * + * @param cx1 the <i>x</i> coordinate of the curve’s new + * first control point. + * + * @param cy1 the <i>y</i> coordinate of the curve’s new + * first control point. + * + * @param cx2 the <i>x</i> coordinate of the curve’s new + * second control point. + * + * @param cy2 the <i>y</i> coordinate of the curve’s new + * second control point. + * + * @param x2 the <i>x</i> coordinate of the curve’s new end + * point. + * + * @param y2 the <i>y</i> coordinate of the curve’s new end + * point. + */ + public void setCurve(float x1, float y1, float cx1, float cy1, float cx2, + float cy2, float x2, float y2) + { + this.x1 = x1; + this.y1 = y1; + ctrlx1 = cx1; + ctrly1 = cy1; + ctrlx2 = cx2; + ctrly2 = cy2; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Determines the smallest rectangle that encloses the + * curve’s start, end and control points. As the + * illustration below shows, the invisible control points may cause + * the bounds to be much larger than the area that is actually + * covered by the curve. + * + * <p><img src="doc-files/CubicCurve2D-2.png" width="350" height="180" + * alt="An illustration of the bounds of a CubicCurve2D" /> + */ + public Rectangle2D getBounds2D() + { + float nx1 = (float) Math.min(Math.min(x1, ctrlx1), Math.min(ctrlx2, x2)); + float ny1 = (float) Math.min(Math.min(y1, ctrly1), Math.min(ctrly2, y2)); + float nx2 = (float) Math.max(Math.max(x1, ctrlx1), Math.max(ctrlx2, x2)); + float ny2 = (float) Math.max(Math.max(y1, ctrly1), Math.max(ctrly2, y2)); + return new Rectangle2D.Float(nx1, ny1, nx2 - nx1, ny2 - ny1); + } + } +} diff --git a/libjava/classpath/java/awt/geom/Dimension2D.java b/libjava/classpath/java/awt/geom/Dimension2D.java new file mode 100644 index 0000000..6b5ce88 --- /dev/null +++ b/libjava/classpath/java/awt/geom/Dimension2D.java @@ -0,0 +1,118 @@ +/* Dimension2D.java -- abstraction of a dimension + Copyright (C) 1999, 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.geom; + +/** + * This stores a dimension in 2-dimensional space - a width (along the x-axis) + * and height (along the y-axis). The storage is left to subclasses. + * + * @author Per Bothner (bothner@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ +public abstract class Dimension2D implements Cloneable +{ + /** + * The default constructor. + */ + protected Dimension2D() + { + } + + /** + * Get the width of this dimension. A negative result, while legal, is + * undefined in meaning. + * + * @return the width + */ + public abstract double getWidth(); + + /** + * Get the height of this dimension. A negative result, while legal, is + * undefined in meaning. + * + * @return the height + */ + public abstract double getHeight(); + + /** + * Set the size of this dimension to the requested values. Loss of precision + * may occur. + * + * @param w the new width + * @param h the new height + */ + public abstract void setSize(double w, double h); + + /** + * Set the size of this dimension to the requested value. Loss of precision + * may occur. + * + * @param d the dimension containing the new values + * + * @throws NullPointerException if d is null + */ + public void setSize(Dimension2D d) + { + setSize(d.getWidth(), d.getHeight()); + } + + /** + * Create a new dimension of the same run-time type with the same contents + * as this one. + * + * @return the clone + * + * @exception OutOfMemoryError If there is not enough memory available. + * + * @since 1.2 + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // Impossible + } + } +} // class Dimension2D diff --git a/libjava/classpath/java/awt/geom/Ellipse2D.java b/libjava/classpath/java/awt/geom/Ellipse2D.java new file mode 100644 index 0000000..e883077 --- /dev/null +++ b/libjava/classpath/java/awt/geom/Ellipse2D.java @@ -0,0 +1,413 @@ +/* Ellipse2D.java -- represents an ellipse in 2-D space + Copyright (C) 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.geom; + + +/** + * Ellipse2D is the shape of an ellipse. + * <BR> + * <img src="doc-files/Ellipse-1.png" width="347" height="221" + * alt="A drawing of an ellipse" /><BR> + * The ellipse is defined by it's bounding box (shown in red), + * and is defined by the implicit curve:<BR> + * <blockquote>(<i>x</i>/<i>a</i>)<sup>2</sup> + + * (<i>y</i>/<i>b</i>)<sup>2</sup> = 1<BR><BR></blockquote> + * + * @author Tom Tromey (tromey@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * + * @since 1.2 + */ +public abstract class Ellipse2D extends RectangularShape +{ + /** + * Ellipse2D is defined as abstract. + * Implementing classes are Ellipse2D.Float and Ellipse2D.Double. + */ + protected Ellipse2D() + { + } + + /** + * Determines if a point is contained within the ellipse. <P> + * @param x - x coordinate of the point. + * @param y - y coordinate of the point. + * @return true if the point is within the ellipse, false otherwise. + */ + public boolean contains(double x, double y) + { + double rx = getWidth() / 2; + double ry = getHeight() / 2; + double tx = (x - (getX() + rx)) / rx; + double ty = (y - (getY() + ry)) / ry; + return tx * tx + ty * ty < 1.0; + } + + /** + * Determines if a rectangle is completely contained within the + * ellipse. <P> + * @param x - x coordinate of the upper-left corner of the rectangle + * @param y - y coordinate of the upper-left corner of the rectangle + * @param w - width of the rectangle + * @param h - height of the rectangle + * @return true if the rectangle is completely contained, false otherwise. + */ + public boolean contains(double x, double y, double w, double h) + { + double x2 = x + w; + double y2 = y + h; + return (contains(x, y) && contains(x, y2) && contains(x2, y) + && contains(x2, y2)); + } + + /** + * Returns a PathIterator object corresponding to the ellipse.<P> + * + * Note: An ellipse cannot be represented exactly in PathIterator + * segments, the outline is thefore approximated with cubic + * Bezier segments. + * + * @param at an optional transform. + * @return A path iterator. + */ + public PathIterator getPathIterator(AffineTransform at) + { + // An ellipse is just a complete arc. + return new Arc2D.ArcIterator(this, at); + } + + /** + * Determines if a rectangle intersects any part of the ellipse.<P> + * @param x - x coordinate of the upper-left corner of the rectangle + * @param y - y coordinate of the upper-left corner of the rectangle + * @param w - width of the rectangle + * @param h - height of the rectangle + * @return true if the rectangle intersects the ellipse, false otherwise. + */ + public boolean intersects(double x, double y, double w, double h) + { + Rectangle2D r = new Rectangle2D.Double(x, y, w, h); + if (! r.intersects(getX(), getY(), getWidth(), getHeight())) + return false; + + if (contains(x, y) || contains(x, y + h) || contains(x + w, y) + || contains(x + w, y + h)) + return true; + + Line2D l1 = new Line2D.Double(getX(), getY() + (getHeight() / 2), + getX() + getWidth(), + getY() + (getHeight() / 2)); + Line2D l2 = new Line2D.Double(getX() + (getWidth() / 2), getY(), + getX() + (getWidth() / 2), + getY() + getHeight()); + + if (l1.intersects(r) || l2.intersects(r)) + return true; + + return false; + } + + /** + * An {@link Ellipse2D} that stores its coordinates using <code>double</code> + * primitives. + */ + public static class Double extends Ellipse2D + { + /** + * The height of the ellipse. + */ + public double height; + + /** + * The width of the ellipse. + */ + public double width; + + /** + * The upper-left x coordinate of the bounding-box + */ + public double x; + + /** + * The upper-left y coordinate of the bounding-box + */ + public double y; + + /** + * Creates a new Ellipse2D with an upper-left coordinate of (0,0) + * and a zero size. + */ + public Double() + { + } + + /** + * Creates a new Ellipse2D within a given rectangle + * using double-precision coordinates.<P> + * @param x - x coordinate of the upper-left of the bounding rectangle + * @param y - y coordinate of the upper-left of the bounding rectangle + * @param w - width of the ellipse + * @param h - height of the ellipse + */ + public Double(double x, double y, double w, double h) + { + this.x = x; + this.y = y; + height = h; + width = w; + } + + /** + * Returns the bounding-box of the ellipse. + * @return The bounding box. + */ + public Rectangle2D getBounds2D() + { + return new Rectangle2D.Double(x, y, width, height); + } + + /** + * Returns the height of the ellipse. + * @return The height of the ellipse. + */ + public double getHeight() + { + return height; + } + + /** + * Returns the width of the ellipse. + * @return The width of the ellipse. + */ + public double getWidth() + { + return width; + } + + /** + * Returns x coordinate of the upper-left corner of + * the ellipse's bounding-box. + * @return The x coordinate. + */ + public double getX() + { + return x; + } + + /** + * Returns y coordinate of the upper-left corner of + * the ellipse's bounding-box. + * @return The y coordinate. + */ + public double getY() + { + return y; + } + + /** + * Returns <code>true</code> if the ellipse encloses no area, and + * <code>false</code> otherwise. + * + * @return A boolean. + */ + public boolean isEmpty() + { + return height <= 0 || width <= 0; + } + + /** + * Sets the geometry of the ellipse's bounding box.<P> + * + * @param x - x coordinate of the upper-left of the bounding rectangle + * @param y - y coordinate of the upper-left of the bounding rectangle + * @param w - width of the ellipse + * @param h - height of the ellipse + */ + public void setFrame(double x, double y, double w, double h) + { + this.x = x; + this.y = y; + height = h; + width = w; + } + } // class Double + + /** + * An {@link Ellipse2D} that stores its coordinates using <code>float</code> + * primitives. + */ + public static class Float extends Ellipse2D + { + /** + * The height of the ellipse. + */ + public float height; + + /** + * The width of the ellipse. + */ + public float width; + + /** + * The upper-left x coordinate of the bounding-box + */ + public float x; + + /** + * The upper-left y coordinate of the bounding-box + */ + public float y; + + /** + * Creates a new Ellipse2D with an upper-left coordinate of (0,0) + * and a zero size. + */ + public Float() + { + } + + /** + * Creates a new Ellipse2D within a given rectangle + * using floating-point precision.<P> + * @param x - x coordinate of the upper-left of the bounding rectangle + * @param y - y coordinate of the upper-left of the bounding rectangle + * @param w - width of the ellipse + * @param h - height of the ellipse + * + */ + public Float(float x, float y, float w, float h) + { + this.x = x; + this.y = y; + this.height = h; + this.width = w; + } + + /** + * Returns the bounding-box of the ellipse. + * @return The bounding box. + */ + public Rectangle2D getBounds2D() + { + return new Rectangle2D.Float(x, y, width, height); + } + + /** + * Returns the height of the ellipse. + * @return The height of the ellipse. + */ + public double getHeight() + { + return height; + } + + /** + * Returns the width of the ellipse. + * @return The width of the ellipse. + */ + public double getWidth() + { + return width; + } + + /** + * Returns x coordinate of the upper-left corner of + * the ellipse's bounding-box. + * @return The x coordinate. + */ + public double getX() + { + return x; + } + + /** + * Returns y coordinate of the upper-left corner of + * the ellipse's bounding-box. + * @return The y coordinate. + */ + public double getY() + { + return y; + } + + /** + * Returns <code>true</code> if the ellipse encloses no area, and + * <code>false</code> otherwise. + * + * @return A boolean. + */ + public boolean isEmpty() + { + return height <= 0 || width <= 0; + } + + /** + * Sets the geometry of the ellipse's bounding box.<P> + * + * @param x - x coordinate of the upper-left of the bounding rectangle + * @param y - y coordinate of the upper-left of the bounding rectangle + * @param w - width of the ellipse + * @param h - height of the ellipse + */ + public void setFrame(float x, float y, float w, float h) + { + this.x = x; + this.y = y; + height = h; + width = w; + } + + /** + * Sets the geometry of the ellipse's bounding box. + * + * Note: This leads to a loss of precision.<P> + * + * @param x - x coordinate of the upper-left of the bounding rectangle + * @param y - y coordinate of the upper-left of the bounding rectangle + * @param w - width of the ellipse + * @param h - height of the ellipse + */ + public void setFrame(double x, double y, double w, double h) + { + this.x = (float) x; + this.y = (float) y; + height = (float) h; + width = (float) w; + } + } // class Float +} // class Ellipse2D diff --git a/libjava/classpath/java/awt/geom/FlatteningPathIterator.java b/libjava/classpath/java/awt/geom/FlatteningPathIterator.java new file mode 100644 index 0000000..b06e6cc --- /dev/null +++ b/libjava/classpath/java/awt/geom/FlatteningPathIterator.java @@ -0,0 +1,579 @@ +/* FlatteningPathIterator.java -- Approximates curves by straight lines + Copyright (C) 2003 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.geom; + +import java.util.NoSuchElementException; + + +/** + * A PathIterator for approximating curved path segments by sequences + * of straight lines. Instances of this class will only return + * segments of type {@link PathIterator#SEG_MOVETO}, {@link + * PathIterator#SEG_LINETO}, and {@link PathIterator#SEG_CLOSE}. + * + * <p>The accuracy of the approximation is determined by two + * parameters: + * + * <ul><li>The <i>flatness</i> is a threshold value for deciding when + * a curved segment is consided flat enough for being approximated by + * a single straight line. Flatness is defined as the maximal distance + * of a curve control point to the straight line that connects the + * curve start and end. A lower flatness threshold means a closer + * approximation. See {@link QuadCurve2D#getFlatness()} and {@link + * CubicCurve2D#getFlatness()} for drawings which illustrate the + * meaning of flatness.</li> + * + * <li>The <i>recursion limit</i> imposes an upper bound for how often + * a curved segment gets subdivided. A limit of <i>n</i> means that + * for each individual quadratic and cubic Bézier spline + * segment, at most 2<sup><small><i>n</i></small></sup> {@link + * PathIterator#SEG_LINETO} segments will be created.</li></ul> + * + * <p><b>Memory Efficiency:</b> The memory consumption grows linearly + * with the recursion limit. Neither the <i>flatness</i> parameter nor + * the number of segments in the flattened path will affect the memory + * consumption. + * + * <p><b>Thread Safety:</b> Multiple threads can safely work on + * separate instances of this class. However, multiple threads should + * not concurrently access the same instance, as no synchronization is + * performed. + * + * @see <a href="doc-files/FlatteningPathIterator-1.html" + * >Implementation Note</a> + * + * @author Sascha Brawer (brawer@dandelis.ch) + * + * @since 1.2 + */ +public class FlatteningPathIterator + implements PathIterator +{ + /** + * The PathIterator whose curved segments are being approximated. + */ + private final PathIterator srcIter; + + + /** + * The square of the flatness threshold value, which determines when + * a curve segment is considered flat enough that no further + * subdivision is needed. + * + * <p>Calculating flatness actually produces the squared flatness + * value. To avoid the relatively expensive calculation of a square + * root for each curve segment, we perform all flatness comparisons + * on squared values. + * + * @see QuadCurve2D#getFlatnessSq() + * @see CubicCurve2D#getFlatnessSq() + */ + private final double flatnessSq; + + + /** + * The maximal number of subdivions that are performed to + * approximate a quadratic or cubic curve segment. + */ + private final int recursionLimit; + + + /** + * A stack for holding the coordinates of subdivided segments. + * + * @see <a href="doc-files/FlatteningPathIterator-1.html" + * >Implementation Note</a> + */ + private double[] stack; + + + /** + * The current stack size. + * + * @see <a href="doc-files/FlatteningPathIterator-1.html" + * >Implementation Note</a> + */ + private int stackSize; + + + /** + * The number of recursions that were performed to arrive at + * a segment on the stack. + * + * @see <a href="doc-files/FlatteningPathIterator-1.html" + * >Implementation Note</a> + */ + private int[] recLevel; + + + + private final double[] scratch = new double[6]; + + + /** + * The segment type of the last segment that was returned by + * the source iterator. + */ + private int srcSegType; + + + /** + * The current <i>x</i> position of the source iterator. + */ + private double srcPosX; + + + /** + * The current <i>y</i> position of the source iterator. + */ + private double srcPosY; + + + /** + * A flag that indicates when this path iterator has finished its + * iteration over path segments. + */ + private boolean done; + + + /** + * Constructs a new PathIterator for approximating an input + * PathIterator with straight lines. The approximation works by + * recursive subdivisons, until the specified flatness threshold is + * not exceeded. + * + * <p>There will not be more than 10 nested recursion steps, which + * means that a single <code>SEG_QUADTO</code> or + * <code>SEG_CUBICTO</code> segment is approximated by at most + * 2<sup><small>10</small></sup> = 1024 straight lines. + */ + public FlatteningPathIterator(PathIterator src, double flatness) + { + this(src, flatness, 10); + } + + + /** + * Constructs a new PathIterator for approximating an input + * PathIterator with straight lines. The approximation works by + * recursive subdivisons, until the specified flatness threshold is + * not exceeded. Additionally, the number of recursions is also + * bound by the specified recursion limit. + */ + public FlatteningPathIterator(PathIterator src, double flatness, + int limit) + { + if (flatness < 0 || limit < 0) + throw new IllegalArgumentException(); + + srcIter = src; + flatnessSq = flatness * flatness; + recursionLimit = limit; + fetchSegment(); + } + + + /** + * Returns the maximally acceptable flatness. + * + * @see QuadCurve2D#getFlatness() + * @see CubicCurve2D#getFlatness() + */ + public double getFlatness() + { + return Math.sqrt(flatnessSq); + } + + + /** + * Returns the maximum number of recursive curve subdivisions. + */ + public int getRecursionLimit() + { + return recursionLimit; + } + + + // Documentation will be copied from PathIterator. + public int getWindingRule() + { + return srcIter.getWindingRule(); + } + + + // Documentation will be copied from PathIterator. + public boolean isDone() + { + return done; + } + + + // Documentation will be copied from PathIterator. + public void next() + { + if (stackSize > 0) + { + --stackSize; + if (stackSize > 0) + { + switch (srcSegType) + { + case PathIterator.SEG_QUADTO: + subdivideQuadratic(); + return; + + case PathIterator.SEG_CUBICTO: + subdivideCubic(); + return; + + default: + throw new IllegalStateException(); + } + } + } + + srcIter.next(); + fetchSegment(); + } + + + // Documentation will be copied from PathIterator. + public int currentSegment(double[] coords) + { + if (done) + throw new NoSuchElementException(); + + switch (srcSegType) + { + case PathIterator.SEG_CLOSE: + return srcSegType; + + case PathIterator.SEG_MOVETO: + case PathIterator.SEG_LINETO: + coords[0] = srcPosX; + coords[1] = srcPosY; + return srcSegType; + + case PathIterator.SEG_QUADTO: + if (stackSize == 0) + { + coords[0] = srcPosX; + coords[1] = srcPosY; + } + else + { + int sp = stack.length - 4 * stackSize; + coords[0] = stack[sp + 2]; + coords[1] = stack[sp + 3]; + } + return PathIterator.SEG_LINETO; + + case PathIterator.SEG_CUBICTO: + if (stackSize == 0) + { + coords[0] = srcPosX; + coords[1] = srcPosY; + } + else + { + int sp = stack.length - 6 * stackSize; + coords[0] = stack[sp + 4]; + coords[1] = stack[sp + 5]; + } + return PathIterator.SEG_LINETO; + } + + throw new IllegalStateException(); + } + + + // Documentation will be copied from PathIterator. + public int currentSegment(float[] coords) + { + if (done) + throw new NoSuchElementException(); + + switch (srcSegType) + { + case PathIterator.SEG_CLOSE: + return srcSegType; + + case PathIterator.SEG_MOVETO: + case PathIterator.SEG_LINETO: + coords[0] = (float) srcPosX; + coords[1] = (float) srcPosY; + return srcSegType; + + case PathIterator.SEG_QUADTO: + if (stackSize == 0) + { + coords[0] = (float) srcPosX; + coords[1] = (float) srcPosY; + } + else + { + int sp = stack.length - 4 * stackSize; + coords[0] = (float) stack[sp + 2]; + coords[1] = (float) stack[sp + 3]; + } + return PathIterator.SEG_LINETO; + + case PathIterator.SEG_CUBICTO: + if (stackSize == 0) + { + coords[0] = (float) srcPosX; + coords[1] = (float) srcPosY; + } + else + { + int sp = stack.length - 6 * stackSize; + coords[0] = (float) stack[sp + 4]; + coords[1] = (float) stack[sp + 5]; + } + return PathIterator.SEG_LINETO; + } + + throw new IllegalStateException(); + } + + + /** + * Fetches the next segment from the source iterator. + */ + private void fetchSegment() + { + int sp; + + if (srcIter.isDone()) + { + done = true; + return; + } + + srcSegType = srcIter.currentSegment(scratch); + + switch (srcSegType) + { + case PathIterator.SEG_CLOSE: + return; + + case PathIterator.SEG_MOVETO: + case PathIterator.SEG_LINETO: + srcPosX = scratch[0]; + srcPosY = scratch[1]; + return; + + case PathIterator.SEG_QUADTO: + if (recursionLimit == 0) + { + srcPosX = scratch[2]; + srcPosY = scratch[3]; + stackSize = 0; + return; + } + sp = 4 * recursionLimit; + stackSize = 1; + if (stack == null) + { + stack = new double[sp + /* 4 + 2 */ 6]; + recLevel = new int[recursionLimit + 1]; + } + recLevel[0] = 0; + stack[sp] = srcPosX; // P1.x + stack[sp + 1] = srcPosY; // P1.y + stack[sp + 2] = scratch[0]; // C.x + stack[sp + 3] = scratch[1]; // C.y + srcPosX = stack[sp + 4] = scratch[2]; // P2.x + srcPosY = stack[sp + 5] = scratch[3]; // P2.y + subdivideQuadratic(); + break; + + case PathIterator.SEG_CUBICTO: + if (recursionLimit == 0) + { + srcPosX = scratch[4]; + srcPosY = scratch[5]; + stackSize = 0; + return; + } + sp = 6 * recursionLimit; + stackSize = 1; + if ((stack == null) || (stack.length < sp + 8)) + { + stack = new double[sp + /* 6 + 2 */ 8]; + recLevel = new int[recursionLimit + 1]; + } + recLevel[0] = 0; + stack[sp] = srcPosX; // P1.x + stack[sp + 1] = srcPosY; // P1.y + stack[sp + 2] = scratch[0]; // C1.x + stack[sp + 3] = scratch[1]; // C1.y + stack[sp + 4] = scratch[2]; // C2.x + stack[sp + 5] = scratch[3]; // C2.y + srcPosX = stack[sp + 6] = scratch[4]; // P2.x + srcPosY = stack[sp + 7] = scratch[5]; // P2.y + subdivideCubic(); + return; + } + } + + + /** + * Repeatedly subdivides the quadratic curve segment that is on top + * of the stack. The iteration terminates when the recursion limit + * has been reached, or when the resulting segment is flat enough. + */ + private void subdivideQuadratic() + { + int sp; + int level; + + sp = stack.length - 4 * stackSize - 2; + level = recLevel[stackSize - 1]; + while ((level < recursionLimit) + && (QuadCurve2D.getFlatnessSq(stack, sp) >= flatnessSq)) + { + recLevel[stackSize] = recLevel[stackSize - 1] = ++level; + QuadCurve2D.subdivide(stack, sp, stack, sp - 4, stack, sp); + ++stackSize; + sp -= 4; + } + } + + + /** + * Repeatedly subdivides the cubic curve segment that is on top + * of the stack. The iteration terminates when the recursion limit + * has been reached, or when the resulting segment is flat enough. + */ + private void subdivideCubic() + { + int sp; + int level; + + sp = stack.length - 6 * stackSize - 2; + level = recLevel[stackSize - 1]; + while ((level < recursionLimit) + && (CubicCurve2D.getFlatnessSq(stack, sp) >= flatnessSq)) + { + recLevel[stackSize] = recLevel[stackSize - 1] = ++level; + + CubicCurve2D.subdivide(stack, sp, stack, sp - 6, stack, sp); + ++stackSize; + sp -= 6; + } + } + + + /* These routines were useful for debugging. Since they would + * just bloat the implementation, they are commented out. + * + * + + private static String segToString(int segType, double[] d, int offset) + { + String s; + + switch (segType) + { + case PathIterator.SEG_CLOSE: + return "SEG_CLOSE"; + + case PathIterator.SEG_MOVETO: + return "SEG_MOVETO (" + d[offset] + ", " + d[offset + 1] + ")"; + + case PathIterator.SEG_LINETO: + return "SEG_LINETO (" + d[offset] + ", " + d[offset + 1] + ")"; + + case PathIterator.SEG_QUADTO: + return "SEG_QUADTO (" + d[offset] + ", " + d[offset + 1] + + ") (" + d[offset + 2] + ", " + d[offset + 3] + ")"; + + case PathIterator.SEG_CUBICTO: + return "SEG_CUBICTO (" + d[offset] + ", " + d[offset + 1] + + ") (" + d[offset + 2] + ", " + d[offset + 3] + + ") (" + d[offset + 4] + ", " + d[offset + 5] + ")"; + } + + throw new IllegalStateException(); + } + + + private void dumpQuadraticStack(String msg) + { + int sp = stack.length - 4 * stackSize - 2; + int i = 0; + System.err.print(" " + msg + ":"); + while (sp < stack.length) + { + System.err.print(" (" + stack[sp] + ", " + stack[sp+1] + ")"); + if (i < recLevel.length) + System.out.print("/" + recLevel[i++]); + if (sp + 3 < stack.length) + System.err.print(" [" + stack[sp+2] + ", " + stack[sp+3] + "]"); + sp += 4; + } + System.err.println(); + } + + + private void dumpCubicStack(String msg) + { + int sp = stack.length - 6 * stackSize - 2; + int i = 0; + System.err.print(" " + msg + ":"); + while (sp < stack.length) + { + System.err.print(" (" + stack[sp] + ", " + stack[sp+1] + ")"); + if (i < recLevel.length) + System.out.print("/" + recLevel[i++]); + if (sp + 3 < stack.length) + { + System.err.print(" [" + stack[sp+2] + ", " + stack[sp+3] + "]"); + System.err.print(" [" + stack[sp+4] + ", " + stack[sp+5] + "]"); + } + sp += 6; + } + System.err.println(); + } + + * + * + */ +} diff --git a/libjava/classpath/java/awt/geom/GeneralPath.java b/libjava/classpath/java/awt/geom/GeneralPath.java new file mode 100644 index 0000000..f5485587 --- /dev/null +++ b/libjava/classpath/java/awt/geom/GeneralPath.java @@ -0,0 +1,958 @@ +/* GeneralPath.java -- represents a shape built from subpaths + Copyright (C) 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.geom; + +import java.awt.Rectangle; +import java.awt.Shape; + + +/** + * A general geometric path, consisting of any number of subpaths + * constructed out of straight lines and cubic or quadratic Bezier + * curves. + * + * <p>The inside of the curve is defined for drawing purposes by a winding + * rule. Either the WIND_EVEN_ODD or WIND_NON_ZERO winding rule can be chosen. + * + * <p><img src="doc-files/GeneralPath-1.png" width="300" height="210" + * alt="A drawing of a GeneralPath" /> + * <p>The EVEN_ODD winding rule defines a point as inside a path if: + * A ray from the point towards infinity in an arbitrary direction + * intersects the path an odd number of times. Points <b>A</b> and + * <b>C</b> in the image are considered to be outside the path. + * (both intersect twice) + * Point <b>B</b> intersects once, and is inside. + * + * <p>The NON_ZERO winding rule defines a point as inside a path if: + * The path intersects the ray in an equal number of opposite directions. + * Point <b>A</b> in the image is outside (one intersection in the + * ’up’ + * direction, one in the ’down’ direction) Point <b>B</b> in + * the image is inside (one intersection ’down’) + * Point <b>C</b> in the image is outside (two intersections + * ’down’) + * + * @see Line2D + * @see CubicCurve2D + * @see QuadCurve2D + * + * @author Sascha Brawer (brawer@dandelis.ch) + * @author Sven de Marothy (sven@physto.se) + * + * @since 1.2 + */ +public final class GeneralPath implements Shape, Cloneable +{ + public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD; + public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO; + + /** Initial size if not specified. */ + private static final int INIT_SIZE = 10; + + /** A big number, but not so big it can't survive a few float operations */ + private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0; + + /** The winding rule. + * This is package-private to avoid an accessor method. + */ + int rule; + + /** + * The path type in points. Note that xpoints[index] and ypoints[index] maps + * to types[index]; the control points of quad and cubic paths map as + * well but are ignored. + * This is package-private to avoid an accessor method. + */ + byte[] types; + + /** + * The list of all points seen. Since you can only append floats, it makes + * sense for these to be float[]. I have no idea why Sun didn't choose to + * allow a general path of double precision points. + * Note: Storing x and y coords seperately makes for a slower transforms, + * But it speeds up and simplifies box-intersection checking a lot. + * These are package-private to avoid accessor methods. + */ + float[] xpoints; + float[] ypoints; + + /** The index of the most recent moveto point, or null. */ + private int subpath = -1; + + /** The next available index into points. + * This is package-private to avoid an accessor method. + */ + int index; + + /** + * Constructs a GeneralPath with the default (NON_ZERO) + * winding rule and initial capacity (20). + */ + public GeneralPath() + { + this(WIND_NON_ZERO, INIT_SIZE); + } + + /** + * Constructs a GeneralPath with a specific winding rule + * and the default initial capacity (20). + * @param rule the winding rule (WIND_NON_ZERO or WIND_EVEN_ODD) + */ + public GeneralPath(int rule) + { + this(rule, INIT_SIZE); + } + + /** + * Constructs a GeneralPath with a specific winding rule + * and the initial capacity. The initial capacity should be + * the approximate number of path segments to be used. + * @param rule the winding rule (WIND_NON_ZERO or WIND_EVEN_ODD) + * @param capacity the inital capacity, in path segments + */ + public GeneralPath(int rule, int capacity) + { + if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) + throw new IllegalArgumentException(); + this.rule = rule; + if (capacity < INIT_SIZE) + capacity = INIT_SIZE; + types = new byte[capacity]; + xpoints = new float[capacity]; + ypoints = new float[capacity]; + } + + /** + * Constructs a GeneralPath from an arbitrary shape object. + * The Shapes PathIterator path and winding rule will be used. + * @param s the shape + */ + public GeneralPath(Shape s) + { + types = new byte[INIT_SIZE]; + xpoints = new float[INIT_SIZE]; + ypoints = new float[INIT_SIZE]; + PathIterator pi = s.getPathIterator(null); + setWindingRule(pi.getWindingRule()); + append(pi, false); + } + + /** + * Adds a new point to a path. + */ + public void moveTo(float x, float y) + { + subpath = index; + ensureSize(index + 1); + types[index] = PathIterator.SEG_MOVETO; + xpoints[index] = x; + ypoints[index++] = y; + } + + /** + * Appends a straight line to the current path. + * @param x x coordinate of the line endpoint. + * @param y y coordinate of the line endpoint. + */ + public void lineTo(float x, float y) + { + ensureSize(index + 1); + types[index] = PathIterator.SEG_LINETO; + xpoints[index] = x; + ypoints[index++] = y; + } + + /** + * Appends a quadratic Bezier curve to the current path. + * @param x1 x coordinate of the control point + * @param y1 y coordinate of the control point + * @param x2 x coordinate of the curve endpoint. + * @param y2 y coordinate of the curve endpoint. + */ + public void quadTo(float x1, float y1, float x2, float y2) + { + ensureSize(index + 2); + types[index] = PathIterator.SEG_QUADTO; + xpoints[index] = x1; + ypoints[index++] = y1; + xpoints[index] = x2; + ypoints[index++] = y2; + } + + /** + * Appends a cubic Bezier curve to the current path. + * @param x1 x coordinate of the first control point + * @param y1 y coordinate of the first control point + * @param x2 x coordinate of the second control point + * @param y2 y coordinate of the second control point + * @param x3 x coordinate of the curve endpoint. + * @param y3 y coordinate of the curve endpoint. + */ + public void curveTo(float x1, float y1, float x2, float y2, float x3, + float y3) + { + ensureSize(index + 3); + types[index] = PathIterator.SEG_CUBICTO; + xpoints[index] = x1; + ypoints[index++] = y1; + xpoints[index] = x2; + ypoints[index++] = y2; + xpoints[index] = x3; + ypoints[index++] = y3; + } + + /** + * Closes the current subpath by drawing a line + * back to the point of the last moveTo. + */ + public void closePath() + { + ensureSize(index + 1); + types[index] = PathIterator.SEG_CLOSE; + xpoints[index] = xpoints[subpath]; + ypoints[index++] = ypoints[subpath]; + } + + /** + * Appends the segments of a Shape to the path. If <code>connect</code> is + * true, the new path segments are connected to the existing one with a line. + * The winding rule of the Shape is ignored. + */ + public void append(Shape s, boolean connect) + { + append(s.getPathIterator(null), connect); + } + + /** + * Appends the segments of a PathIterator to this GeneralPath. + * Optionally, the initial {@link PathIterator#SEG_MOVETO} segment + * of the appended path is changed into a {@link + * PathIterator#SEG_LINETO} segment. + * + * @param iter the PathIterator specifying which segments shall be + * appended. + * + * @param connect <code>true</code> for substituting the initial + * {@link PathIterator#SEG_MOVETO} segment by a {@link + * PathIterator#SEG_LINETO}, or <code>false</code> for not + * performing any substitution. If this GeneralPath is currently + * empty, <code>connect</code> is assumed to be <code>false</code>, + * thus leaving the initial {@link PathIterator#SEG_MOVETO} + * unchanged. + */ + public void append(PathIterator iter, boolean connect) + { + // A bad implementation of this method had caused Classpath bug #6076. + float[] f = new float[6]; + while (! iter.isDone()) + { + switch (iter.currentSegment(f)) + { + case PathIterator.SEG_MOVETO: + if (! connect || (index == 0)) + { + moveTo(f[0], f[1]); + break; + } + if ((index >= 1) && (types[index - 1] == PathIterator.SEG_CLOSE) + && (f[0] == xpoints[index - 1]) + && (f[1] == ypoints[index - 1])) + break; + + // Fall through. + case PathIterator.SEG_LINETO: + lineTo(f[0], f[1]); + break; + case PathIterator.SEG_QUADTO: + quadTo(f[0], f[1], f[2], f[3]); + break; + case PathIterator.SEG_CUBICTO: + curveTo(f[0], f[1], f[2], f[3], f[4], f[5]); + break; + case PathIterator.SEG_CLOSE: + closePath(); + break; + } + + connect = false; + iter.next(); + } + } + + /** + * Returns the path’s current winding rule. + */ + public int getWindingRule() + { + return rule; + } + + /** + * Sets the path’s winding rule, which controls which areas are + * considered ’inside’ or ’outside’ the path + * on drawing. Valid rules are WIND_EVEN_ODD for an even-odd winding rule, + * or WIND_NON_ZERO for a non-zero winding rule. + */ + public void setWindingRule(int rule) + { + if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) + throw new IllegalArgumentException(); + this.rule = rule; + } + + /** + * Returns the current appending point of the path. + */ + public Point2D getCurrentPoint() + { + if (subpath < 0) + return null; + return new Point2D.Float(xpoints[index - 1], ypoints[index - 1]); + } + + /** + * Resets the path. All points and segments are destroyed. + */ + public void reset() + { + subpath = -1; + index = 0; + } + + /** + * Applies a transform to the path. + */ + public void transform(AffineTransform xform) + { + double nx; + double ny; + double[] m = new double[6]; + xform.getMatrix(m); + for (int i = 0; i < index; i++) + { + nx = m[0] * xpoints[i] + m[2] * ypoints[i] + m[4]; + ny = m[1] * xpoints[i] + m[3] * ypoints[i] + m[5]; + xpoints[i] = (float) nx; + ypoints[i] = (float) ny; + } + } + + /** + * Creates a transformed version of the path. + * @param xform the transform to apply + * @return a new transformed GeneralPath + */ + public Shape createTransformedShape(AffineTransform xform) + { + GeneralPath p = new GeneralPath(this); + p.transform(xform); + return p; + } + + /** + * Returns the path’s bounding box. + */ + public Rectangle getBounds() + { + return getBounds2D().getBounds(); + } + + /** + * Returns the path’s bounding box, in <code>float</code> precision + */ + public Rectangle2D getBounds2D() + { + float x1; + float y1; + float x2; + float y2; + + if (index > 0) + { + x1 = x2 = xpoints[0]; + y1 = y2 = ypoints[0]; + } + else + x1 = x2 = y1 = y2 = 0.0f; + + for (int i = 0; i < index; i++) + { + x1 = Math.min(xpoints[i], x1); + y1 = Math.min(ypoints[i], y1); + x2 = Math.max(xpoints[i], x2); + y2 = Math.max(ypoints[i], y2); + } + return (new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1)); + } + + /** + * Evaluates if a point is within the GeneralPath, + * The NON_ZERO winding rule is used, regardless of the + * set winding rule. + * @param x x coordinate of the point to evaluate + * @param y y coordinate of the point to evaluate + * @return true if the point is within the path, false otherwise + */ + public boolean contains(double x, double y) + { + return (getWindingNumber(x, y) != 0); + } + + /** + * Evaluates if a Point2D is within the GeneralPath, + * The NON_ZERO winding rule is used, regardless of the + * set winding rule. + * @param p The Point2D to evaluate + * @return true if the point is within the path, false otherwise + */ + public boolean contains(Point2D p) + { + return contains(p.getX(), p.getY()); + } + + /** + * Evaluates if a rectangle is completely contained within the path. + * This method will return false in the cases when the box + * intersects an inner segment of the path. + * (i.e.: The method is accurate for the EVEN_ODD winding rule) + */ + public boolean contains(double x, double y, double w, double h) + { + if (! getBounds2D().intersects(x, y, w, h)) + return false; + + /* Does any edge intersect? */ + if (getAxisIntersections(x, y, false, w) != 0 /* top */ + || getAxisIntersections(x, y + h, false, w) != 0 /* bottom */ + || getAxisIntersections(x + w, y, true, h) != 0 /* right */ + || getAxisIntersections(x, y, true, h) != 0) /* left */ + return false; + + /* No intersections, is any point inside? */ + if (getWindingNumber(x, y) != 0) + return true; + + return false; + } + + /** + * Evaluates if a rectangle is completely contained within the path. + * This method will return false in the cases when the box + * intersects an inner segment of the path. + * (i.e.: The method is accurate for the EVEN_ODD winding rule) + * @param r the rectangle + * @return <code>true</code> if the rectangle is completely contained + * within the path, <code>false</code> otherwise + */ + public boolean contains(Rectangle2D r) + { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Evaluates if a rectangle intersects the path. + * @param x x coordinate of the rectangle + * @param y y coordinate of the rectangle + * @param w width of the rectangle + * @param h height of the rectangle + * @return <code>true</code> if the rectangle intersects the path, + * <code>false</code> otherwise + */ + public boolean intersects(double x, double y, double w, double h) + { + /* Does any edge intersect? */ + if (getAxisIntersections(x, y, false, w) != 0 /* top */ + || getAxisIntersections(x, y + h, false, w) != 0 /* bottom */ + || getAxisIntersections(x + w, y, true, h) != 0 /* right */ + || getAxisIntersections(x, y, true, h) != 0) /* left */ + return true; + + /* No intersections, is any point inside? */ + if (getWindingNumber(x, y) != 0) + return true; + + return false; + } + + /** + * Evaluates if a Rectangle2D intersects the path. + * @param r The rectangle + * @return <code>true</code> if the rectangle intersects the path, + * <code>false</code> otherwise + */ + public boolean intersects(Rectangle2D r) + { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * A PathIterator that iterates over the segments of a GeneralPath. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + private static class GeneralPathIterator implements PathIterator + { + /** + * The number of coordinate values for each segment type. + */ + private static final int[] NUM_COORDS = { + /* 0: SEG_MOVETO */ 1, + /* 1: SEG_LINETO */ 1, + /* 2: SEG_QUADTO */ 2, + /* 3: SEG_CUBICTO */ 3, + /* 4: SEG_CLOSE */ 0}; + + /** + * The GeneralPath whose segments are being iterated. + * This is package-private to avoid an accessor method. + */ + final GeneralPath path; + + /** + * The affine transformation used to transform coordinates. + */ + private final AffineTransform transform; + + /** + * The current position of the iterator. + */ + private int pos; + + /** + * Constructs a new iterator for enumerating the segments of a + * GeneralPath. + * + * @param at an affine transformation for projecting the returned + * points, or <code>null</code> to return the original points + * without any mapping. + */ + GeneralPathIterator(GeneralPath path, AffineTransform transform) + { + this.path = path; + this.transform = transform; + } + + /** + * Returns the current winding rule of the GeneralPath. + */ + public int getWindingRule() + { + return path.rule; + } + + /** + * Determines whether the iterator has reached the last segment in + * the path. + */ + public boolean isDone() + { + return pos >= path.index; + } + + /** + * Advances the iterator position by one segment. + */ + public void next() + { + int seg; + + /* + * Increment pos by the number of coordinate pairs. + */ + seg = path.types[pos]; + if (seg == SEG_CLOSE) + pos++; + else + pos += NUM_COORDS[seg]; + } + + /** + * Returns the current segment in float coordinates. + */ + public int currentSegment(float[] coords) + { + int seg; + int numCoords; + + seg = path.types[pos]; + numCoords = NUM_COORDS[seg]; + if (numCoords > 0) + { + for (int i = 0; i < numCoords; i++) + { + coords[i << 1] = path.xpoints[pos + i]; + coords[(i << 1) + 1] = path.ypoints[pos + i]; + } + + if (transform != null) + transform.transform( /* src */ + coords, /* srcOffset */ + 0, /* dest */ coords, /* destOffset */ + 0, /* numPoints */ numCoords); + } + return seg; + } + + /** + * Returns the current segment in double coordinates. + */ + public int currentSegment(double[] coords) + { + int seg; + int numCoords; + + seg = path.types[pos]; + numCoords = NUM_COORDS[seg]; + if (numCoords > 0) + { + for (int i = 0; i < numCoords; i++) + { + coords[i << 1] = (double) path.xpoints[pos + i]; + coords[(i << 1) + 1] = (double) path.ypoints[pos + i]; + } + if (transform != null) + transform.transform( /* src */ + coords, /* srcOffset */ + 0, /* dest */ coords, /* destOffset */ + 0, /* numPoints */ numCoords); + } + return seg; + } + } + + /** + * Creates a PathIterator for iterating along the segments of the path. + * + * @param at an affine transformation for projecting the returned + * points, or <code>null</code> to let the created iterator return + * the original points without any mapping. + */ + public PathIterator getPathIterator(AffineTransform at) + { + return new GeneralPathIterator(this, at); + } + + /** + * Creates a new FlatteningPathIterator for the path + */ + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return new FlatteningPathIterator(getPathIterator(at), flatness); + } + + /** + * Creates a new shape of the same run-time type with the same contents + * as this one. + * + * @return the clone + * + * @exception OutOfMemoryError If there is not enough memory available. + * + * @since 1.2 + */ + public Object clone() + { + // This class is final; no need to use super.clone(). + return new GeneralPath(this); + } + + /** + * Helper method - ensure the size of the data arrays, + * otherwise, reallocate new ones twice the size + */ + private void ensureSize(int size) + { + if (subpath < 0) + throw new IllegalPathStateException("need initial moveto"); + if (size <= xpoints.length) + return; + byte[] b = new byte[types.length << 1]; + System.arraycopy(types, 0, b, 0, index); + types = b; + float[] f = new float[xpoints.length << 1]; + System.arraycopy(xpoints, 0, f, 0, index); + xpoints = f; + f = new float[ypoints.length << 1]; + System.arraycopy(ypoints, 0, f, 0, index); + ypoints = f; + } + + /** + * Helper method - Get the total number of intersections from (x,y) along + * a given axis, within a given distance. + */ + private int getAxisIntersections(double x, double y, boolean useYaxis, + double distance) + { + return (evaluateCrossings(x, y, false, useYaxis, distance)); + } + + /** + * Helper method - returns the winding number of a point. + */ + private int getWindingNumber(double x, double y) + { + /* Evaluate the crossings from x,y to infinity on the y axis (arbitrary + choice). Note that we don't actually use Double.INFINITY, since that's + slower, and may cause problems. */ + return (evaluateCrossings(x, y, true, true, BIG_VALUE)); + } + + /** + * Helper method - evaluates the number of intersections on an axis from + * the point (x,y) to the point (x,y+distance) or (x+distance,y). + * @param x x coordinate. + * @param y y coordinate. + * @param neg True if opposite-directed intersections should cancel, + * false to sum all intersections. + * @param useYaxis Use the Y axis, false uses the X axis. + * @param distance Interval from (x,y) on the selected axis to find + * intersections. + */ + private int evaluateCrossings(double x, double y, boolean neg, + boolean useYaxis, double distance) + { + float cx = 0.0f; + float cy = 0.0f; + float firstx = 0.0f; + float firsty = 0.0f; + + int negative = (neg) ? -1 : 1; + double x0; + double x1; + double x2; + double x3; + double y0; + double y1; + double y2; + double y3; + double[] r = new double[4]; + int nRoots; + double epsilon = 0.0; + int pos = 0; + int windingNumber = 0; + boolean pathStarted = false; + + if (index == 0) + return (0); + if (useYaxis) + { + float[] swap1; + swap1 = ypoints; + ypoints = xpoints; + xpoints = swap1; + double swap2; + swap2 = y; + y = x; + x = swap2; + } + + /* Get a value which is hopefully small but not insignificant relative + the path. */ + epsilon = ypoints[0] * 1E-7; + + if(epsilon == 0) + epsilon = 1E-7; + + pos = 0; + while (pos < index) + { + switch (types[pos]) + { + case PathIterator.SEG_MOVETO: + if (pathStarted) // close old path + { + x0 = cx; + y0 = cy; + x1 = firstx; + y1 = firsty; + + if (y0 == 0.0) + y0 -= epsilon; + if (y1 == 0.0) + y1 -= epsilon; + if (Line2D.linesIntersect(x0, y0, x1, y1, + epsilon, 0.0, distance, 0.0)) + windingNumber += (y1 < y0) ? 1 : negative; + + cx = firstx; + cy = firsty; + } + cx = firstx = xpoints[pos] - (float) x; + cy = firsty = ypoints[pos++] - (float) y; + pathStarted = true; + break; + case PathIterator.SEG_CLOSE: + x0 = cx; + y0 = cy; + x1 = firstx; + y1 = firsty; + + if (y0 == 0.0) + y0 -= epsilon; + if (y1 == 0.0) + y1 -= epsilon; + if (Line2D.linesIntersect(x0, y0, x1, y1, + epsilon, 0.0, distance, 0.0)) + windingNumber += (y1 < y0) ? 1 : negative; + + cx = firstx; + cy = firsty; + pos++; + pathStarted = false; + break; + case PathIterator.SEG_LINETO: + x0 = cx; + y0 = cy; + x1 = xpoints[pos] - (float) x; + y1 = ypoints[pos++] - (float) y; + + if (y0 == 0.0) + y0 -= epsilon; + if (y1 == 0.0) + y1 -= epsilon; + if (Line2D.linesIntersect(x0, y0, x1, y1, + epsilon, 0.0, distance, 0.0)) + windingNumber += (y1 < y0) ? 1 : negative; + + cx = xpoints[pos - 1] - (float) x; + cy = ypoints[pos - 1] - (float) y; + break; + case PathIterator.SEG_QUADTO: + x0 = cx; + y0 = cy; + x1 = xpoints[pos] - x; + y1 = ypoints[pos++] - y; + x2 = xpoints[pos] - x; + y2 = ypoints[pos++] - y; + + /* check if curve may intersect X+ axis. */ + if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0) + && (y0 * y1 <= 0 || y1 * y2 <= 0)) + { + if (y0 == 0.0) + y0 -= epsilon; + if (y2 == 0.0) + y2 -= epsilon; + + r[0] = y0; + r[1] = 2 * (y1 - y0); + r[2] = (y2 - 2 * y1 + y0); + + /* degenerate roots (=tangent points) do not + contribute to the winding number. */ + if ((nRoots = QuadCurve2D.solveQuadratic(r)) == 2) + for (int i = 0; i < nRoots; i++) + { + float t = (float) r[i]; + if (t > 0.0f && t < 1.0f) + { + double crossing = t * t * (x2 - 2 * x1 + x0) + + 2 * t * (x1 - x0) + x0; + if (crossing >= 0.0 && crossing <= distance) + windingNumber += (2 * t * (y2 - 2 * y1 + y0) + + 2 * (y1 - y0) < 0) ? 1 : negative; + } + } + } + + cx = xpoints[pos - 1] - (float) x; + cy = ypoints[pos - 1] - (float) y; + break; + case PathIterator.SEG_CUBICTO: + x0 = cx; + y0 = cy; + x1 = xpoints[pos] - x; + y1 = ypoints[pos++] - y; + x2 = xpoints[pos] - x; + y2 = ypoints[pos++] - y; + x3 = xpoints[pos] - x; + y3 = ypoints[pos++] - y; + + /* check if curve may intersect X+ axis. */ + if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0 || x3 > 0.0) + && (y0 * y1 <= 0 || y1 * y2 <= 0 || y2 * y3 <= 0)) + { + if (y0 == 0.0) + y0 -= epsilon; + if (y3 == 0.0) + y3 -= epsilon; + + r[0] = y0; + r[1] = 3 * (y1 - y0); + r[2] = 3 * (y2 + y0 - 2 * y1); + r[3] = y3 - 3 * y2 + 3 * y1 - y0; + + if ((nRoots = CubicCurve2D.solveCubic(r)) != 0) + for (int i = 0; i < nRoots; i++) + { + float t = (float) r[i]; + if (t > 0.0 && t < 1.0) + { + double crossing = -(t * t * t) * (x0 - 3 * x1 + + 3 * x2 - x3) + + 3 * t * t * (x0 - 2 * x1 + x2) + + 3 * t * (x1 - x0) + x0; + if (crossing >= 0 && crossing <= distance) + windingNumber += (3 * t * t * (y3 + 3 * y1 + - 3 * y2 - y0) + + 6 * t * (y0 - 2 * y1 + y2) + + 3 * (y1 - y0) < 0) ? 1 : negative; + } + } + } + + cx = xpoints[pos - 1] - (float) x; + cy = ypoints[pos - 1] - (float) y; + break; + } + } + + // swap coordinates back + if (useYaxis) + { + float[] swap; + swap = ypoints; + ypoints = xpoints; + xpoints = swap; + } + return (windingNumber); + } +} // class GeneralPath + diff --git a/libjava/classpath/java/awt/geom/IllegalPathStateException.java b/libjava/classpath/java/awt/geom/IllegalPathStateException.java new file mode 100644 index 0000000..4d190c7 --- /dev/null +++ b/libjava/classpath/java/awt/geom/IllegalPathStateException.java @@ -0,0 +1,71 @@ +/* IllegalPathStateException.java -- an operation was in an illegal path state + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.geom; + +/** + * Thrown when an operation on a path is in an illegal state, such as appending + * a segment to a <code>GeneralPath</code> without an initial moveto. + * + * @author Tom Tromey (tromey@cygnus.com) + * @see GeneralPath + * @status updated to 1.4 + */ +public class IllegalPathStateException extends RuntimeException +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = -5158084205220481094L; + + /** + * Create an exception with no message. + */ + public IllegalPathStateException() + { + } + + /** + * Create an exception with a message. + * + * @param msg the message + */ + public IllegalPathStateException(String msg) + { + super(msg); + } +} diff --git a/libjava/classpath/java/awt/geom/Line2D.java b/libjava/classpath/java/awt/geom/Line2D.java new file mode 100644 index 0000000..e15e7cf --- /dev/null +++ b/libjava/classpath/java/awt/geom/Line2D.java @@ -0,0 +1,1182 @@ +/* Line2D.java -- represents a line in 2-D space, plus operations on a line + Copyright (C) 2000, 2001, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.geom; + +import java.awt.Rectangle; +import java.awt.Shape; +import java.util.NoSuchElementException; + +/** + * Represents a directed line bewteen two points in (x,y) Cartesian space. + * Remember, on-screen graphics have increasing x from left-to-right, and + * increasing y from top-to-bottom. The storage is left to subclasses. + * + * @author Tom Tromey (tromey@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @author David Gilbert + * @since 1.2 + * @status updated to 1.4 + */ +public abstract class Line2D implements Shape, Cloneable +{ + /** + * The default constructor. + */ + protected Line2D() + { + } + + /** + * Return the x coordinate of the first point. + * + * @return the starting x coordinate + */ + public abstract double getX1(); + + /** + * Return the y coordinate of the first point. + * + * @return the starting y coordinate + */ + public abstract double getY1(); + + /** + * Return the first point. + * + * @return the starting point + */ + public abstract Point2D getP1(); + + /** + * Return the x coordinate of the second point. + * + * @return the ending x coordinate + */ + public abstract double getX2(); + + /** + * Return the y coordinate of the second point. + * + * @return the ending y coordinate + */ + public abstract double getY2(); + + /** + * Return the second point. + * + * @return the ending point + */ + public abstract Point2D getP2(); + + /** + * Set the coordinates of the line to the given coordinates. Loss of + * precision may occur due to rounding issues. + * + * @param x1 the first x coordinate + * @param y1 the first y coordinate + * @param x2 the second x coordinate + * @param y2 the second y coordinate + */ + public abstract void setLine(double x1, double y1, double x2, double y2); + + /** + * Set the coordinates to the given points. + * + * @param p1 the first point + * @param p2 the second point + * @throws NullPointerException if either point is null + */ + public void setLine(Point2D p1, Point2D p2) + { + setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY()); + } + + /** + * Set the coordinates to those of the given line. + * + * @param l the line to copy + * @throws NullPointerException if l is null + */ + public void setLine(Line2D l) + { + setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2()); + } + + /** + * Computes the relative rotation direction needed to pivot the line about + * the first point in order to have the second point colinear with point p. + * Because of floating point rounding, don't expect this to be a perfect + * measure of colinearity. The answer is 1 if the line has a shorter rotation + * in the direction of the positive X axis to the negative Y axis + * (counter-clockwise in the default Java coordinate system), or -1 if the + * shortest rotation is in the opposite direction (clockwise). If p + * is already colinear, the return value is -1 if it lies beyond the first + * point, 0 if it lies in the segment, or 1 if it lies beyond the second + * point. If the first and second point are coincident, this returns 0. + * + * @param x1 the first x coordinate + * @param y1 the first y coordinate + * @param x2 the second x coordinate + * @param y2 the second y coordinate + * @param px the reference x coordinate + * @param py the reference y coordinate + * @return the relative rotation direction + */ + public static int relativeCCW(double x1, double y1, double x2, double y2, + double px, double py) + { + if ((x1 == x2 && y1 == y2) + || (x1 == px && y1 == py)) + return 0; // Coincident points. + // Translate to the origin. + x2 -= x1; + y2 -= y1; + px -= x1; + py -= y1; + double slope2 = y2 / x2; + double slopep = py / px; + if (slope2 == slopep || (x2 == 0 && px == 0)) + return y2 > 0 // Colinear. + ? (py < 0 ? -1 : py > y2 ? 1 : 0) + : (py > 0 ? -1 : py < y2 ? 1 : 0); + if (x2 >= 0 && slope2 >= 0) + return px >= 0 // Quadrant 1. + ? (slope2 > slopep ? 1 : -1) + : (slope2 < slopep ? 1 : -1); + if (y2 > 0) + return px < 0 // Quadrant 2. + ? (slope2 > slopep ? 1 : -1) + : (slope2 < slopep ? 1 : -1); + if (slope2 >= 0.0) + return px >= 0 // Quadrant 3. + ? (slope2 < slopep ? 1 : -1) + : (slope2 > slopep ? 1 : -1); + return px < 0 // Quadrant 4. + ? (slope2 < slopep ? 1 : -1) + : (slope2 > slopep ? 1 : -1); + } + + /** + * Computes the relative rotation direction needed to pivot this line about + * the first point in order to have the second point colinear with point p. + * Because of floating point rounding, don't expect this to be a perfect + * measure of colinearity. The answer is 1 if the line has a shorter rotation + * in the direction of the positive X axis to the negative Y axis + * (counter-clockwise in the default Java coordinate system), or -1 if the + * shortest rotation is in the opposite direction (clockwise). If p + * is already colinear, the return value is -1 if it lies beyond the first + * point, 0 if it lies in the segment, or 1 if it lies beyond the second + * point. If the first and second point are coincident, this returns 0. + * + * @param px the reference x coordinate + * @param py the reference y coordinate + * @return the relative rotation direction + * @see #relativeCCW(double, double, double, double, double, double) + */ + public int relativeCCW(double px, double py) + { + return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py); + } + + /** + * Computes the relative rotation direction needed to pivot this line about + * the first point in order to have the second point colinear with point p. + * Because of floating point rounding, don't expect this to be a perfect + * measure of colinearity. The answer is 1 if the line has a shorter rotation + * in the direction of the positive X axis to the negative Y axis + * (counter-clockwise in the default Java coordinate system), or -1 if the + * shortest rotation is in the opposite direction (clockwise). If p + * is already colinear, the return value is -1 if it lies beyond the first + * point, 0 if it lies in the segment, or 1 if it lies beyond the second + * point. If the first and second point are coincident, this returns 0. + * + * @param p the reference point + * @return the relative rotation direction + * @throws NullPointerException if p is null + * @see #relativeCCW(double, double, double, double, double, double) + */ + public int relativeCCW(Point2D p) + { + return relativeCCW(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY()); + } + + /** + * Computes twice the (signed) area of the triangle defined by the three + * points. This method is used for intersection testing. + * + * @param x1 the x-coordinate of the first point. + * @param y1 the y-coordinate of the first point. + * @param x2 the x-coordinate of the second point. + * @param y2 the y-coordinate of the second point. + * @param x3 the x-coordinate of the third point. + * @param y3 the y-coordinate of the third point. + * + * @return Twice the area. + */ + private static double area2(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + return (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); + } + + /** + * Returns <code>true</code> if (x3, y3) lies between (x1, y1) and (x2, y2), + * and false otherwise, This test assumes that the three points are + * collinear, and is used for intersection testing. + * + * @param x1 the x-coordinate of the first point. + * @param y1 the y-coordinate of the first point. + * @param x2 the x-coordinate of the second point. + * @param y2 the y-coordinate of the second point. + * @param x3 the x-coordinate of the third point. + * @param y3 the y-coordinate of the third point. + * + * @return A boolean. + */ + private static boolean between(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + if (x1 != x2) { + return (x1 <= x3 && x3 <= x2) || (x1 >= x3 && x3 >= x2); + } + else { + return (y1 <= y3 && y3 <= y2) || (y1 >= y3 && y3 >= y2); + } + } + + /** + * Test if the line segment (x1,y1)->(x2,y2) intersects the line segment + * (x3,y3)->(x4,y4). + * + * @param x1 the first x coordinate of the first segment + * @param y1 the first y coordinate of the first segment + * @param x2 the second x coordinate of the first segment + * @param y2 the second y coordinate of the first segment + * @param x3 the first x coordinate of the second segment + * @param y3 the first y coordinate of the second segment + * @param x4 the second x coordinate of the second segment + * @param y4 the second y coordinate of the second segment + * @return true if the segments intersect + */ + public static boolean linesIntersect(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + double a1, a2, a3, a4; + + // deal with special cases + if ((a1 = area2(x1, y1, x2, y2, x3, y3)) == 0.0) + { + // check if p3 is between p1 and p2 OR + // p4 is collinear also AND either between p1 and p2 OR at opposite ends + if (between(x1, y1, x2, y2, x3, y3)) + { + return true; + } + else + { + if (area2(x1, y1, x2, y2, x4, y4) == 0.0) + { + return between(x3, y3, x4, y4, x1, y1) + || between (x3, y3, x4, y4, x2, y2); + } + else { + return false; + } + } + } + else if ((a2 = area2(x1, y1, x2, y2, x4, y4)) == 0.0) + { + // check if p4 is between p1 and p2 (we already know p3 is not + // collinear) + return between(x1, y1, x2, y2, x4, y4); + } + + if ((a3 = area2(x3, y3, x4, y4, x1, y1)) == 0.0) { + // check if p1 is between p3 and p4 OR + // p2 is collinear also AND either between p1 and p2 OR at opposite ends + if (between(x3, y3, x4, y4, x1, y1)) { + return true; + } + else { + if (area2(x3, y3, x4, y4, x2, y2) == 0.0) { + return between(x1, y1, x2, y2, x3, y3) + || between (x1, y1, x2, y2, x4, y4); + } + else { + return false; + } + } + } + else if ((a4 = area2(x3, y3, x4, y4, x2, y2)) == 0.0) { + // check if p2 is between p3 and p4 (we already know p1 is not + // collinear) + return between(x3, y3, x4, y4, x2, y2); + } + else { // test for regular intersection + return ((a1 > 0.0) ^ (a2 > 0.0)) && ((a3 > 0.0) ^ (a4 > 0.0)); + } + } + + /** + * Test if this line intersects the line given by (x1,y1)->(x2,y2). + * + * @param x1 the first x coordinate of the other segment + * @param y1 the first y coordinate of the other segment + * @param x2 the second x coordinate of the other segment + * @param y2 the second y coordinate of the other segment + * @return true if the segments intersect + * @see #linesIntersect(double, double, double, double, + * double, double, double, double) + */ + public boolean intersectsLine(double x1, double y1, double x2, double y2) + { + return linesIntersect(getX1(), getY1(), getX2(), getY2(), + x1, y1, x2, y2); + } + + /** + * Test if this line intersects the given line. + * + * @param l the other segment + * @return true if the segments intersect + * @throws NullPointerException if l is null + * @see #linesIntersect(double, double, double, double, + * double, double, double, double) + */ + public boolean intersectsLine(Line2D l) + { + return linesIntersect(getX1(), getY1(), getX2(), getY2(), + l.getX1(), l.getY1(), l.getX2(), l.getY2()); + } + + /** + * Measures the square of the shortest distance from the reference point + * to a point on the line segment. If the point is on the segment, the + * result will be 0. + * + * @param x1 the first x coordinate of the segment + * @param y1 the first y coordinate of the segment + * @param x2 the second x coordinate of the segment + * @param y2 the second y coordinate of the segment + * @param px the x coordinate of the point + * @param py the y coordinate of the point + * @return the square of the distance from the point to the segment + * @see #ptSegDist(double, double, double, double, double, double) + * @see #ptLineDistSq(double, double, double, double, double, double) + */ + public static double ptSegDistSq(double x1, double y1, double x2, double y2, + double px, double py) + { + double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); + + double x, y; + if (pd2 == 0) + { + // Points are coincident. + x = x1; + y = y2; + } + else + { + double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2; + + if (u < 0) + { + // "Off the end" + x = x1; + y = y1; + } + else if (u > 1.0) + { + x = x2; + y = y2; + } + else + { + x = x1 + u * (x2 - x1); + y = y1 + u * (y2 - y1); + } + } + + return (x - px) * (x - px) + (y - py) * (y - py); + } + + /** + * Measures the shortest distance from the reference point to a point on + * the line segment. If the point is on the segment, the result will be 0. + * + * @param x1 the first x coordinate of the segment + * @param y1 the first y coordinate of the segment + * @param x2 the second x coordinate of the segment + * @param y2 the second y coordinate of the segment + * @param px the x coordinate of the point + * @param py the y coordinate of the point + * @return the distance from the point to the segment + * @see #ptSegDistSq(double, double, double, double, double, double) + * @see #ptLineDist(double, double, double, double, double, double) + */ + public static double ptSegDist(double x1, double y1, double x2, double y2, + double px, double py) + { + return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py)); + } + + /** + * Measures the square of the shortest distance from the reference point + * to a point on this line segment. If the point is on the segment, the + * result will be 0. + * + * @param px the x coordinate of the point + * @param py the y coordinate of the point + * @return the square of the distance from the point to the segment + * @see #ptSegDistSq(double, double, double, double, double, double) + */ + public double ptSegDistSq(double px, double py) + { + return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py); + } + + /** + * Measures the square of the shortest distance from the reference point + * to a point on this line segment. If the point is on the segment, the + * result will be 0. + * + * @param p the point + * @return the square of the distance from the point to the segment + * @throws NullPointerException if p is null + * @see #ptSegDistSq(double, double, double, double, double, double) + */ + public double ptSegDistSq(Point2D p) + { + return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY()); + } + + /** + * Measures the shortest distance from the reference point to a point on + * this line segment. If the point is on the segment, the result will be 0. + * + * @param px the x coordinate of the point + * @param py the y coordinate of the point + * @return the distance from the point to the segment + * @see #ptSegDist(double, double, double, double, double, double) + */ + public double ptSegDist(double px, double py) + { + return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py); + } + + /** + * Measures the shortest distance from the reference point to a point on + * this line segment. If the point is on the segment, the result will be 0. + * + * @param p the point + * @return the distance from the point to the segment + * @throws NullPointerException if p is null + * @see #ptSegDist(double, double, double, double, double, double) + */ + public double ptSegDist(Point2D p) + { + return ptSegDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY()); + } + + /** + * Measures the square of the shortest distance from the reference point + * to a point on the infinite line extended from the segment. If the point + * is on the segment, the result will be 0. If the segment is length 0, + * the distance is to the common endpoint. + * + * @param x1 the first x coordinate of the segment + * @param y1 the first y coordinate of the segment + * @param x2 the second x coordinate of the segment + * @param y2 the second y coordinate of the segment + * @param px the x coordinate of the point + * @param py the y coordinate of the point + * @return the square of the distance from the point to the extended line + * @see #ptLineDist(double, double, double, double, double, double) + * @see #ptSegDistSq(double, double, double, double, double, double) + */ + public static double ptLineDistSq(double x1, double y1, double x2, double y2, + double px, double py) + { + double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); + + double x, y; + if (pd2 == 0) + { + // Points are coincident. + x = x1; + y = y2; + } + else + { + double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2; + x = x1 + u * (x2 - x1); + y = y1 + u * (y2 - y1); + } + + return (x - px) * (x - px) + (y - py) * (y - py); + } + + /** + * Measures the shortest distance from the reference point to a point on + * the infinite line extended from the segment. If the point is on the + * segment, the result will be 0. If the segment is length 0, the distance + * is to the common endpoint. + * + * @param x1 the first x coordinate of the segment + * @param y1 the first y coordinate of the segment + * @param x2 the second x coordinate of the segment + * @param y2 the second y coordinate of the segment + * @param px the x coordinate of the point + * @param py the y coordinate of the point + * @return the distance from the point to the extended line + * @see #ptLineDistSq(double, double, double, double, double, double) + * @see #ptSegDist(double, double, double, double, double, double) + */ + public static double ptLineDist(double x1, double y1, + double x2, double y2, + double px, double py) + { + return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py)); + } + + /** + * Measures the square of the shortest distance from the reference point + * to a point on the infinite line extended from this segment. If the point + * is on the segment, the result will be 0. If the segment is length 0, + * the distance is to the common endpoint. + * + * @param px the x coordinate of the point + * @param py the y coordinate of the point + * @return the square of the distance from the point to the extended line + * @see #ptLineDistSq(double, double, double, double, double, double) + */ + public double ptLineDistSq(double px, double py) + { + return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py); + } + + /** + * Measures the square of the shortest distance from the reference point + * to a point on the infinite line extended from this segment. If the point + * is on the segment, the result will be 0. If the segment is length 0, + * the distance is to the common endpoint. + * + * @param p the point + * @return the square of the distance from the point to the extended line + * @throws NullPointerException if p is null + * @see #ptLineDistSq(double, double, double, double, double, double) + */ + public double ptLineDistSq(Point2D p) + { + return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), + p.getX(), p.getY()); + } + + /** + * Measures the shortest distance from the reference point to a point on + * the infinite line extended from this segment. If the point is on the + * segment, the result will be 0. If the segment is length 0, the distance + * is to the common endpoint. + * + * @param px the x coordinate of the point + * @param py the y coordinate of the point + * @return the distance from the point to the extended line + * @see #ptLineDist(double, double, double, double, double, double) + */ + public double ptLineDist(double px, double py) + { + return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py); + } + + /** + * Measures the shortest distance from the reference point to a point on + * the infinite line extended from this segment. If the point is on the + * segment, the result will be 0. If the segment is length 0, the distance + * is to the common endpoint. + * + * @param p the point + * @return the distance from the point to the extended line + * @throws NullPointerException if p is null + * @see #ptLineDist(double, double, double, double, double, double) + */ + public double ptLineDist(Point2D p) + { + return ptLineDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY()); + } + + /** + * Test if a point is contained inside the line. Since a line has no area, + * this returns false. + * + * @param x the x coordinate + * @param y the y coordinate + * @return false; the line does not contain points + */ + public boolean contains(double x, double y) + { + return false; + } + + /** + * Test if a point is contained inside the line. Since a line has no area, + * this returns false. + * + * @param p the point + * @return false; the line does not contain points + */ + public boolean contains(Point2D p) + { + return false; + } + + /** + * Tests if this line intersects the interior of the specified rectangle. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @return true if the line intersects the rectangle + */ + public boolean intersects(double x, double y, double w, double h) + { + if (w <= 0 || h <= 0) + return false; + double x1 = getX1(); + double y1 = getY1(); + double x2 = getX2(); + double y2 = getY2(); + + if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h) + return true; + if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h) + return true; + + double x3 = x + w; + double y3 = y + h; + + return (linesIntersect(x1, y1, x2, y2, x, y, x, y3) + || linesIntersect(x1, y1, x2, y2, x, y3, x3, y3) + || linesIntersect(x1, y1, x2, y2, x3, y3, x3, y) + || linesIntersect(x1, y1, x2, y2, x3, y, x, y)); + } + + /** + * Tests if this line intersects the interior of the specified rectangle. + * + * @param r the rectangle + * @return true if the line intersects the rectangle + * @throws NullPointerException if r is null + */ + public boolean intersects(Rectangle2D r) + { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Tests if the line contains a rectangle. Since lines have no area, this + * always returns false. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @return false; the line does not contain points + */ + public boolean contains(double x, double y, double w, double h) + { + return false; + } + + /** + * Tests if the line contains a rectangle. Since lines have no area, this + * always returns false. + * + * @param r the rectangle + * @return false; the line does not contain points + */ + public boolean contains(Rectangle2D r) + { + return false; + } + + /** + * Gets a bounding box (not necessarily minimal) for this line. + * + * @return the integer bounding box + * @see #getBounds2D() + */ + public Rectangle getBounds() + { + return getBounds2D().getBounds(); + } + + /** + * Return a path iterator, possibly applying a transform on the result. This + * iterator is not threadsafe. + * + * @param at the transform, or null + * @return a new path iterator + */ + public PathIterator getPathIterator(final AffineTransform at) + { + return new PathIterator() + { + /** Current coordinate. */ + private int current = 0; + + public int getWindingRule() + { + return WIND_NON_ZERO; + } + + public boolean isDone() + { + return current >= 2; + } + + public void next() + { + current++; + } + + public int currentSegment(float[] coords) + { + int result; + switch (current) + { + case 0: + coords[0] = (float) getX1(); + coords[1] = (float) getY1(); + result = SEG_MOVETO; + break; + case 1: + coords[0] = (float) getX2(); + coords[1] = (float) getY2(); + result = SEG_LINETO; + break; + default: + throw new NoSuchElementException("line iterator out of bounds"); + } + if (at != null) + at.transform(coords, 0, coords, 0, 1); + return result; + } + + public int currentSegment(double[] coords) + { + int result; + switch (current) + { + case 0: + coords[0] = getX1(); + coords[1] = getY1(); + result = SEG_MOVETO; + break; + case 1: + coords[0] = getX2(); + coords[1] = getY2(); + result = SEG_LINETO; + break; + default: + throw new NoSuchElementException("line iterator out of bounds"); + } + if (at != null) + at.transform(coords, 0, coords, 0, 1); + return result; + } + }; + } + + /** + * Return a flat path iterator, possibly applying a transform on the result. + * This iterator is not threadsafe. + * + * @param at the transform, or null + * @param flatness ignored, since lines are already flat + * @return a new path iterator + * @see #getPathIterator(AffineTransform) + */ + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return getPathIterator(at); + } + + /** + * Create a new line of the same run-time type with the same contents as + * this one. + * + * @return the clone + * + * @exception OutOfMemoryError If there is not enough memory available. + * + * @since 1.2 + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // Impossible + } + } + + /** + * This class defines a point in <code>double</code> precision. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ + public static class Double extends Line2D + { + /** The x coordinate of the first point. */ + public double x1; + + /** The y coordinate of the first point. */ + public double y1; + + /** The x coordinate of the second point. */ + public double x2; + + /** The y coordinate of the second point. */ + public double y2; + + /** + * Construct the line segment (0,0)->(0,0). + */ + public Double() + { + } + + /** + * Construct the line segment with the specified points. + * + * @param x1 the x coordinate of the first point + * @param y1 the y coordinate of the first point + * @param x2 the x coordinate of the second point + * @param y2 the y coordinate of the second point + */ + public Double(double x1, double y1, double x2, double y2) + { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Construct the line segment with the specified points. + * + * @param p1 the first point + * @param p2 the second point + * @throws NullPointerException if either point is null + */ + public Double(Point2D p1, Point2D p2) + { + x1 = p1.getX(); + y1 = p1.getY(); + x2 = p2.getX(); + y2 = p2.getY(); + } + + /** + * Return the x coordinate of the first point. + * + * @return the value of x1 + */ + public double getX1() + { + return x1; + } + + /** + * Return the y coordinate of the first point. + * + * @return the value of y1 + */ + public double getY1() + { + return y1; + } + + /** + * Return the first point. + * + * @return the point (x1,y1) + */ + public Point2D getP1() + { + return new Point2D.Double(x1, y1); + } + + /** + * Return the x coordinate of the second point. + * + * @return the value of x2 + */ + public double getX2() + { + return x2; + } + + /** + * Return the y coordinate of the second point. + * + * @return the value of y2 + */ + public double getY2() + { + return y2; + } + + /** + * Return the second point. + * + * @return the point (x2,y2) + */ + public Point2D getP2() + { + return new Point2D.Double(x2, y2); + } + + /** + * Set this line to the given points. + * + * @param x1 the new x coordinate of the first point + * @param y1 the new y coordinate of the first point + * @param x2 the new x coordinate of the second point + * @param y2 the new y coordinate of the second point + */ + public void setLine(double x1, double y1, double x2, double y2) + { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Return the exact bounds of this line segment. + * + * @return the bounding box + */ + public Rectangle2D getBounds2D() + { + double x = Math.min(x1, x2); + double y = Math.min(y1, y2); + double w = Math.abs(x1 - x2); + double h = Math.abs(y1 - y2); + return new Rectangle2D.Double(x, y, w, h); + } + } // class Double + + /** + * This class defines a point in <code>float</code> precision. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ + public static class Float extends Line2D + { + /** The x coordinate of the first point. */ + public float x1; + + /** The y coordinate of the first point. */ + public float y1; + + /** The x coordinate of the second point. */ + public float x2; + + /** The y coordinate of the second point. */ + public float y2; + + /** + * Construct the line segment (0,0)->(0,0). + */ + public Float() + { + } + + /** + * Construct the line segment with the specified points. + * + * @param x1 the x coordinate of the first point + * @param y1 the y coordinate of the first point + * @param x2 the x coordinate of the second point + * @param y2 the y coordinate of the second point + */ + public Float(float x1, float y1, float x2, float y2) + { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Construct the line segment with the specified points. + * + * @param p1 the first point + * @param p2 the second point + * @throws NullPointerException if either point is null + */ + public Float(Point2D p1, Point2D p2) + { + x1 = (float) p1.getX(); + y1 = (float) p1.getY(); + x2 = (float) p2.getX(); + y2 = (float) p2.getY(); + } + + /** + * Return the x coordinate of the first point. + * + * @return the value of x1 + */ + public double getX1() + { + return x1; + } + + /** + * Return the y coordinate of the first point. + * + * @return the value of y1 + */ + public double getY1() + { + return y1; + } + + /** + * Return the first point. + * + * @return the point (x1,y1) + */ + public Point2D getP1() + { + return new Point2D.Float(x1, y1); + } + + /** + * Return the x coordinate of the second point. + * + * @return the value of x2 + */ + public double getX2() + { + return x2; + } + + /** + * Return the y coordinate of the second point. + * + * @return the value of y2 + */ + public double getY2() + { + return y2; + } + + /** + * Return the second point. + * + * @return the point (x2,y2) + */ + public Point2D getP2() + { + return new Point2D.Float(x2, y2); + } + + /** + * Set this line to the given points. + * + * @param x1 the new x coordinate of the first point + * @param y1 the new y coordinate of the first point + * @param x2 the new x coordinate of the second point + * @param y2 the new y coordinate of the second point + */ + public void setLine(double x1, double y1, double x2, double y2) + { + this.x1 = (float) x1; + this.y1 = (float) y1; + this.x2 = (float) x2; + this.y2 = (float) y2; + } + + /** + * Set this line to the given points. + * + * @param x1 the new x coordinate of the first point + * @param y1 the new y coordinate of the first point + * @param x2 the new x coordinate of the second point + * @param y2 the new y coordinate of the second point + */ + public void setLine(float x1, float y1, float x2, float y2) + { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Return the exact bounds of this line segment. + * + * @return the bounding box + */ + public Rectangle2D getBounds2D() + { + float x = Math.min(x1, x2); + float y = Math.min(y1, y2); + float w = Math.abs(x1 - x2); + float h = Math.abs(y1 - y2); + return new Rectangle2D.Float(x, y, w, h); + } + } // class Float +} // class Line2D diff --git a/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java b/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java new file mode 100644 index 0000000..7995a52 --- /dev/null +++ b/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java @@ -0,0 +1,65 @@ +/* NoninvertibleTransformException.java -- a transform can't be inverted + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.geom; + +/** + * Thrown if an operation requires an inverse of an + * <code>AffineTransform</code>, but the transform is in a non-invertible + * state. + * + * @author Tom Tromey (tromey@cygnus.com) + * @see AffineTransform + * @status updated to 1.4 + */ +public class NoninvertibleTransformException extends Exception +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 6137225240503990466L; + + /** + * Create an exception with a message. + * + * @param s the message + */ + public NoninvertibleTransformException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/awt/geom/PathIterator.java b/libjava/classpath/java/awt/geom/PathIterator.java new file mode 100644 index 0000000..2cd08b9 --- /dev/null +++ b/libjava/classpath/java/awt/geom/PathIterator.java @@ -0,0 +1,189 @@ +/* PathIterator.java -- describes a shape by iterating over its vertices + Copyright (C) 2000, 2002, 2003 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.geom; + +/** + * This interface provides a directed path over the boundary of a shape. The + * path can contain 1st through 3rd order Bezier curves (lines, and quadratic + * and cubic splines). A shape can have multiple disjoint paths via the + * MOVETO directive, and can close a circular path back to the previos + * MOVETO via the CLOSE directive. + * + * @author Tom Tromey (tromey@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @see java.awt.Shape + * @see java.awt.Stroke + * @see FlatteningPathIterator + * @since 1.2 + * @status updated to 1.4 + */ +public interface PathIterator +{ + /** + * The even-odd winding mode: a point is internal to the shape if a ray + * from the point to infinity (in any direction) crosses an odd number of + * segments. + */ + int WIND_EVEN_ODD = 0; + + /** + * The non-zero winding mode: a point is internal to the shape if a ray + * from the point to infinity (in any direction) crosses a different number + * of segments headed clockwise than those headed counterclockwise. + */ + int WIND_NON_ZERO = 1; + + /** + * Starts a new subpath. There is no segment from the previous vertex. + */ + int SEG_MOVETO = 0; + + /** + * The current segment is a line. + */ + int SEG_LINETO = 1; + + /** + * The current segment is a quadratic parametric curve. It is interpolated + * as t varies from 0 to 1 over the current point (CP), first control point + * (P1), and final interpolated control point (P2): + * <pre> + * P(t) = B(2,0)*CP + B(2,1)*P1 + B(2,2)*P2 + * 0 <= t <= 1 + * B(n,m) = mth coefficient of nth degree Bernstein polynomial + * = C(n,m) * t^(m) * (1 - t)^(n-m) + * C(n,m) = Combinations of n things, taken m at a time + * = n! / (m! * (n-m)!) + * </pre> + */ + int SEG_QUADTO = 2; + + /** + * The current segment is a cubic parametric curve (more commonly known as + * a Bezier curve). It is interpolated as t varies from 0 to 1 over the + * current point (CP), first control point (P1), the second control point + * (P2), and final interpolated control point (P3): + * <pre> + * P(t) = B(3,0)*CP + B(3,1)*P1 + B(3,2)*P2 + B(3,3)*P3 + * 0 <= t <= 1 + * B(n,m) = mth coefficient of nth degree Bernstein polynomial + * = C(n,m) * t^(m) * (1 - t)^(n-m) + * C(n,m) = Combinations of n things, taken m at a time + * = n! / (m! * (n-m)!) + * </pre> + */ + int SEG_CUBICTO = 3; + + /** + * The current segment closes a loop by an implicit line to the previous + * SEG_MOVETO coordinate. + */ + int SEG_CLOSE = 4; + + /** + * Returns the winding rule to determine which points are inside this path. + * + * @return the winding rule + * @see #WIND_EVEN_ODD + * @see #WIND_NON_ZERO + */ + int getWindingRule(); + + /** + * Tests if the iterator is exhausted. If this returns true, currentSegment + * and next may throw a NoSuchElementException (although this is not + * required). + * + * @return true if the iteration is complete + */ + boolean isDone(); + + /** + * Advance to the next segment in the iteration. It is not specified what + * this does if called when isDone() returns true. + * + * @throws java.util.NoSuchElementException optional when isDone() is true + */ + void next(); + + /** + * Returns the coordinates of the next point(s), as well as the type of + * line segment. The input array must be at least a float[6], to accomodate + * up to three (x,y) point pairs (although if you know the iterator is + * flat, you can probably get by with a float[2]). If the returned type is + * SEG_MOVETO or SEG_LINETO, the first point in the array is modified; if + * the returned type is SEG_QUADTO, the first two points are modified; if + * the returned type is SEG_CUBICTO, all three points are modified; and if + * the returned type is SEG_CLOSE, the array is untouched. + * + * @param coords the array to place the point coordinates in + * @return the segment type + * @throws NullPointerException if coords is null + * @throws ArrayIndexOutOfBoundsException if coords is too small + * @throws java.util.NoSuchElementException optional when isDone() is true + * @see #SEG_MOVETO + * @see #SEG_LINETO + * @see #SEG_QUADTO + * @see #SEG_CUBICTO + * @see #SEG_CLOSE + */ + int currentSegment(float[] coords); + + /** + * Returns the coordinates of the next point(s), as well as the type of + * line segment. The input array must be at least a double[6], to accomodate + * up to three (x,y) point pairs (although if you know the iterator is + * flat, you can probably get by with a double[2]). If the returned type is + * SEG_MOVETO or SEG_LINETO, the first point in the array is modified; if + * the returned type is SEG_QUADTO, the first two points are modified; if + * the returned type is SEG_CUBICTO, all three points are modified; and if + * the returned type is SEG_CLOSE, the array is untouched. + * + * @param coords the array to place the point coordinates in + * @return the segment type + * @throws NullPointerException if coords is null + * @throws ArrayIndexOutOfBoundsException if coords is too small + * @throws java.util.NoSuchElementException optional when isDone() is true + * @see #SEG_MOVETO + * @see #SEG_LINETO + * @see #SEG_QUADTO + * @see #SEG_CUBICTO + * @see #SEG_CLOSE + */ + int currentSegment(double[] coords); +} // interface PathIterator diff --git a/libjava/classpath/java/awt/geom/Point2D.java b/libjava/classpath/java/awt/geom/Point2D.java new file mode 100644 index 0000000..9f22a5a --- /dev/null +++ b/libjava/classpath/java/awt/geom/Point2D.java @@ -0,0 +1,396 @@ +/* Point2D.java -- generic point in 2-D space + Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.geom; + +/** + * This class implements a generic point in 2D Cartesian space. The storage + * representation is left up to the subclass. Point includes two useful + * nested classes, for float and double storage respectively. + * + * @author Per Bothner (bothner@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ +public abstract class Point2D implements Cloneable +{ + /** + * The default constructor. + * + * @see java.awt.Point + * @see Point2D.Float + * @see Point2D.Double + */ + protected Point2D() + { + } + + /** + * Get the X coordinate, in double precision. + * + * @return the x coordinate + */ + public abstract double getX(); + + /** + * Get the Y coordinate, in double precision. + * + * @return the y coordinate + */ + public abstract double getY(); + + /** + * Set the location of this point to the new coordinates. There may be a + * loss of precision. + * + * @param x the new x coordinate + * @param y the new y coordinate + */ + public abstract void setLocation(double x, double y); + + /** + * Set the location of this point to the new coordinates. There may be a + * loss of precision. + * + * @param p the point to copy + * @throws NullPointerException if p is null + */ + public void setLocation(Point2D p) + { + setLocation(p.getX(), p.getY()); + } + + /** + * Return the square of the distance between two points. + * + * @param x1 the x coordinate of point 1 + * @param y1 the y coordinate of point 1 + * @param x2 the x coordinate of point 2 + * @param y2 the y coordinate of point 2 + * @return (x2 - x1)^2 + (y2 - y1)^2 + */ + public static double distanceSq(double x1, double y1, double x2, double y2) + { + x2 -= x1; + y2 -= y1; + return x2 * x2 + y2 * y2; + } + + /** + * Return the distance between two points. + * + * @param x1 the x coordinate of point 1 + * @param y1 the y coordinate of point 1 + * @param x2 the x coordinate of point 2 + * @param y2 the y coordinate of point 2 + * @return the distance from (x1,y1) to (x2,y2) + */ + public static double distance(double x1, double y1, double x2, double y2) + { + return Math.sqrt(distanceSq(x1, y1, x2, y2)); + } + + /** + * Return the square of the distance from this point to the given one. + * + * @param x the x coordinate of the other point + * @param y the y coordinate of the other point + * @return the square of the distance + */ + public double distanceSq(double x, double y) + { + return distanceSq(getX(), x, getY(), y); + } + + /** + * Return the square of the distance from this point to the given one. + * + * @param p the other point + * @return the square of the distance + * @throws NullPointerException if p is null + */ + public double distanceSq(Point2D p) + { + return distanceSq(getX(), p.getX(), getY(), p.getY()); + } + + /** + * Return the distance from this point to the given one. + * + * @param x the x coordinate of the other point + * @param y the y coordinate of the other point + * @return the distance + */ + public double distance(double x, double y) + { + return distance(getX(), x, getY(), y); + } + + /** + * Return the distance from this point to the given one. + * + * @param p the other point + * @return the distance + * @throws NullPointerException if p is null + */ + public double distance(Point2D p) + { + return distance(getX(), p.getX(), getY(), p.getY()); + } + + /** + * Create a new point of the same run-time type with the same contents as + * this one. + * + * @return the clone + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // Impossible + } + } + + /** + * Return the hashcode for this point. The formula is not documented, but + * appears to be the same as: + * <pre> + * long l = Double.doubleToLongBits(getY()); + * l = l * 31 ^ Double.doubleToLongBits(getX()); + * return (int) ((l >> 32) ^ l); + * </pre> + * + * @return the hashcode + */ + public int hashCode() + { + // Talk about a fun time reverse engineering this one! + long l = java.lang.Double.doubleToLongBits(getY()); + l = l * 31 ^ java.lang.Double.doubleToLongBits(getX()); + return (int) ((l >> 32) ^ l); + } + + /** + * Compares two points for equality. This returns true if they have the + * same coordinates. + * + * @param o the point to compare + * @return true if it is equal + */ + public boolean equals(Object o) + { + if (! (o instanceof Point2D)) + return false; + Point2D p = (Point2D) o; + return getX() == p.getX() && getY() == p.getY(); + } + + /** + * This class defines a point in <code>double</code> precision. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ + public static class Double extends Point2D + { + /** The X coordinate. */ + public double x; + + /** The Y coordinate. */ + public double y; + + /** + * Create a new point at (0,0). + */ + public Double() + { + } + + /** + * Create a new point at (x,y). + * + * @param x the x coordinate + * @param y the y coordinate + */ + public Double(double x, double y) + { + this.x = x; + this.y = y; + } + + /** + * Return the x coordinate. + * + * @return the x coordinate + */ + public double getX() + { + return x; + } + + /** + * Return the y coordinate. + * + * @return the y coordinate + */ + public double getY() + { + return y; + } + + /** + * Sets the location of this point. + * + * @param x the new x coordinate + * @param y the new y coordinate + */ + public void setLocation(double x, double y) + { + this.x = x; + this.y = y; + } + + /** + * Returns a string representation of this object. The format is: + * <code>"Point2D.Double[" + x + ", " + y + ']'</code>. + * + * @return a string representation of this object + */ + public String toString() + { + return "Point2D.Double[" + x + ", " + y + ']'; + } + } // class Double + + /** + * This class defines a point in <code>float</code> precision. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ + public static class Float extends Point2D + { + /** The X coordinate. */ + public float x; + + /** The Y coordinate. */ + public float y; + + /** + * Create a new point at (0,0). + */ + public Float() + { + } + + /** + * Create a new point at (x,y). + * + * @param x the x coordinate + * @param y the y coordinate + */ + public Float(float x, float y) + { + this.x = x; + this.y = y; + } + + /** + * Return the x coordinate. + * + * @return the x coordinate + */ + public double getX() + { + return x; + } + + /** + * Return the y coordinate. + * + * @return the y coordinate + */ + public double getY() + { + return y; + } + + /** + * Sets the location of this point. + * + * @param x the new x coordinate + * @param y the new y coordinate + */ + public void setLocation(double x, double y) + { + this.x = (float) x; + this.y = (float) y; + } + + /** + * Sets the location of this point. + * + * @param x the new x coordinate + * @param y the new y coordinate + */ + public void setLocation(float x, float y) + { + this.x = x; + this.y = y; + } + + /** + * Returns a string representation of this object. The format is: + * <code>"Point2D.Float[" + x + ", " + y + ']'</code>. + * + * @return a string representation of this object + */ + public String toString() + { + return "Point2D.Float[" + x + ", " + y + ']'; + } + } // class Float +} // class Point2D diff --git a/libjava/classpath/java/awt/geom/QuadCurve2D.java b/libjava/classpath/java/awt/geom/QuadCurve2D.java new file mode 100644 index 0000000..41021db --- /dev/null +++ b/libjava/classpath/java/awt/geom/QuadCurve2D.java @@ -0,0 +1,1467 @@ +/* QuadCurve2D.java -- represents a parameterized quadratic curve in 2-D space + Copyright (C) 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.geom; + +import java.awt.Rectangle; +import java.awt.Shape; +import java.util.NoSuchElementException; + +/** + * A two-dimensional curve that is parameterized with a quadratic + * function. + * + * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180" + * alt="A drawing of a QuadCurve2D" /> + * + * @author Eric Blake (ebb9@email.byu.edu) + * @author Graydon Hoare (graydon@redhat.com) + * @author Sascha Brawer (brawer@dandelis.ch) + * @author Sven de Marothy (sven@physto.se) + * + * @since 1.2 + */ +public abstract class QuadCurve2D implements Shape, Cloneable +{ + private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0; + private static final double EPSILON = 1E-10; + + /** + * Constructs a new QuadCurve2D. Typical users will want to + * construct instances of a subclass, such as {@link + * QuadCurve2D.Float} or {@link QuadCurve2D.Double}. + */ + protected QuadCurve2D() + { + } + + /** + * Returns the <i>x</i> coordinate of the curve’s start + * point. + */ + public abstract double getX1(); + + /** + * Returns the <i>y</i> coordinate of the curve’s start + * point. + */ + public abstract double getY1(); + + /** + * Returns the curve’s start point. + */ + public abstract Point2D getP1(); + + /** + * Returns the <i>x</i> coordinate of the curve’s control + * point. + */ + public abstract double getCtrlX(); + + /** + * Returns the <i>y</i> coordinate of the curve’s control + * point. + */ + public abstract double getCtrlY(); + + /** + * Returns the curve’s control point. + */ + public abstract Point2D getCtrlPt(); + + /** + * Returns the <i>x</i> coordinate of the curve’s end + * point. + */ + public abstract double getX2(); + + /** + * Returns the <i>y</i> coordinate of the curve’s end + * point. + */ + public abstract double getY2(); + + /** + * Returns the curve’s end point. + */ + public abstract Point2D getP2(); + + /** + * Changes the curve geometry, separately specifying each coordinate + * value. + * + * @param x1 the <i>x</i> coordinate of the curve’s new start + * point. + * + * @param y1 the <i>y</i> coordinate of the curve’s new start + * point. + * + * @param cx the <i>x</i> coordinate of the curve’s new + * control point. + * + * @param cy the <i>y</i> coordinate of the curve’s new + * control point. + * + * @param x2 the <i>x</i> coordinate of the curve’s new end + * point. + * + * @param y2 the <i>y</i> coordinate of the curve’s new end + * point. + */ + public abstract void setCurve(double x1, double y1, double cx, double cy, + double x2, double y2); + + /** + * Changes the curve geometry, passing coordinate values in an + * array. + * + * @param coords an array containing the new coordinate values. The + * <i>x</i> coordinate of the new start point is located at + * <code>coords[offset]</code>, its <i>y</i> coordinate at + * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the + * new control point is located at <code>coords[offset + 2]</code>, + * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The + * <i>x</i> coordinate of the new end point is located at + * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at + * <code>coords[offset + 5]</code>. + * + * @param offset the offset of the first coordinate value in + * <code>coords</code>. + */ + public void setCurve(double[] coords, int offset) + { + setCurve(coords[offset++], coords[offset++], coords[offset++], + coords[offset++], coords[offset++], coords[offset++]); + } + + /** + * Changes the curve geometry, specifying coordinate values in + * separate Point objects. + * + * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180" + * alt="A drawing of a QuadCurve2D" /> + * + * <p>The curve does not keep any reference to the passed point + * objects. Therefore, a later change to <code>p1</code>, + * <code>c</code> <code>p2</code> will not affect the curve + * geometry. + * + * @param p1 the new start point. + * @param c the new control point. + * @param p2 the new end point. + */ + public void setCurve(Point2D p1, Point2D c, Point2D p2) + { + setCurve(p1.getX(), p1.getY(), c.getX(), c.getY(), p2.getX(), p2.getY()); + } + + /** + * Changes the curve geometry, specifying coordinate values in an + * array of Point objects. + * + * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180" + * alt="A drawing of a QuadCurve2D" /> + * + * <p>The curve does not keep references to the passed point + * objects. Therefore, a later change to the <code>pts</code> array + * or any of its elements will not affect the curve geometry. + * + * @param pts an array containing the points. The new start point + * is located at <code>pts[offset]</code>, the new control + * point at <code>pts[offset + 1]</code>, and the new end point + * at <code>pts[offset + 2]</code>. + * + * @param offset the offset of the start point in <code>pts</code>. + */ + public void setCurve(Point2D[] pts, int offset) + { + setCurve(pts[offset].getX(), pts[offset].getY(), pts[offset + 1].getX(), + pts[offset + 1].getY(), pts[offset + 2].getX(), + pts[offset + 2].getY()); + } + + /** + * Changes the geometry of the curve to that of another curve. + * + * @param c the curve whose coordinates will be copied. + */ + public void setCurve(QuadCurve2D c) + { + setCurve(c.getX1(), c.getY1(), c.getCtrlX(), c.getCtrlY(), c.getX2(), + c.getY2()); + } + + /** + * Calculates the squared flatness of a quadratic curve, directly + * specifying each coordinate value. The flatness is the distance of + * the control point to the line between start and end point. + * + * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. The result will be the + * the square of the distance between C and the gray line, i.e. + * the squared length of the red line. + * + * @param x1 the <i>x</i> coordinate of the start point P1. + * @param y1 the <i>y</i> coordinate of the start point P1. + * @param cx the <i>x</i> coordinate of the control point C. + * @param cy the <i>y</i> coordinate of the control point C. + * @param x2 the <i>x</i> coordinate of the end point P2. + * @param y2 the <i>y</i> coordinate of the end point P2. + */ + public static double getFlatnessSq(double x1, double y1, double cx, + double cy, double x2, double y2) + { + return Line2D.ptSegDistSq(x1, y1, x2, y2, cx, cy); + } + + /** + * Calculates the flatness of a quadratic curve, directly specifying + * each coordinate value. The flatness is the distance of the + * control point to the line between start and end point. + * + * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. The result will be the + * the distance between C and the gray line, i.e. the length of + * the red line. + * + * @param x1 the <i>x</i> coordinate of the start point P1. + * @param y1 the <i>y</i> coordinate of the start point P1. + * @param cx the <i>x</i> coordinate of the control point C. + * @param cy the <i>y</i> coordinate of the control point C. + * @param x2 the <i>x</i> coordinate of the end point P2. + * @param y2 the <i>y</i> coordinate of the end point P2. + */ + public static double getFlatness(double x1, double y1, double cx, double cy, + double x2, double y2) + { + return Line2D.ptSegDist(x1, y1, x2, y2, cx, cy); + } + + /** + * Calculates the squared flatness of a quadratic curve, specifying + * the coordinate values in an array. The flatness is the distance + * of the control point to the line between start and end point. + * + * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. The result will be the + * the square of the distance between C and the gray line, i.e. + * the squared length of the red line. + * + * @param coords an array containing the coordinate values. The + * <i>x</i> coordinate of the start point P1 is located at + * <code>coords[offset]</code>, its <i>y</i> coordinate at + * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the + * control point C is located at <code>coords[offset + 2]</code>, + * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The + * <i>x</i> coordinate of the end point P2 is located at + * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at + * <code>coords[offset + 5]</code>. + * + * @param offset the offset of the first coordinate value in + * <code>coords</code>. + */ + public static double getFlatnessSq(double[] coords, int offset) + { + return Line2D.ptSegDistSq(coords[offset], coords[offset + 1], + coords[offset + 4], coords[offset + 5], + coords[offset + 2], coords[offset + 3]); + } + + /** + * Calculates the flatness of a quadratic curve, specifying the + * coordinate values in an array. The flatness is the distance of + * the control point to the line between start and end point. + * + * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. The result will be the + * the the distance between C and the gray line, i.e. the length of + * the red line. + * + * @param coords an array containing the coordinate values. The + * <i>x</i> coordinate of the start point P1 is located at + * <code>coords[offset]</code>, its <i>y</i> coordinate at + * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the + * control point C is located at <code>coords[offset + 2]</code>, + * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The + * <i>x</i> coordinate of the end point P2 is located at + * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at + * <code>coords[offset + 5]</code>. + * + * @param offset the offset of the first coordinate value in + * <code>coords</code>. + */ + public static double getFlatness(double[] coords, int offset) + { + return Line2D.ptSegDist(coords[offset], coords[offset + 1], + coords[offset + 4], coords[offset + 5], + coords[offset + 2], coords[offset + 3]); + } + + /** + * Calculates the squared flatness of this curve. The flatness is + * the distance of the control point to the line between start and + * end point. + * + * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. The result will be the + * the square of the distance between C and the gray line, i.e. the + * squared length of the red line. + */ + public double getFlatnessSq() + { + return Line2D.ptSegDistSq(getX1(), getY1(), getX2(), getY2(), getCtrlX(), + getCtrlY()); + } + + /** + * Calculates the flatness of this curve. The flatness is the + * distance of the control point to the line between start and end + * point. + * + * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" + * alt="A drawing that illustrates the flatness" /> + * + * <p>In the above drawing, the straight line connecting start point + * P1 and end point P2 is depicted in gray. The result will be the + * the distance between C and the gray line, i.e. the length of the + * red line. + */ + public double getFlatness() + { + return Line2D.ptSegDist(getX1(), getY1(), getX2(), getY2(), getCtrlX(), + getCtrlY()); + } + + /** + * Subdivides this curve into two halves. + * + * <p><img src="doc-files/QuadCurve2D-3.png" width="700" + * height="180" alt="A drawing that illustrates the effects of + * subdividing a QuadCurve2D" /> + * + * @param left a curve whose geometry will be set to the left half + * of this curve, or <code>null</code> if the caller is not + * interested in the left half. + * + * @param right a curve whose geometry will be set to the right half + * of this curve, or <code>null</code> if the caller is not + * interested in the right half. + */ + public void subdivide(QuadCurve2D left, QuadCurve2D right) + { + // Use empty slots at end to share single array. + double[] d = new double[] + { + getX1(), getY1(), getCtrlX(), getCtrlY(), getX2(), getY2(), + 0, 0, 0, 0 + }; + subdivide(d, 0, d, 0, d, 4); + if (left != null) + left.setCurve(d, 0); + if (right != null) + right.setCurve(d, 4); + } + + /** + * Subdivides a quadratic curve into two halves. + * + * <p><img src="doc-files/QuadCurve2D-3.png" width="700" + * height="180" alt="A drawing that illustrates the effects of + * subdividing a QuadCurve2D" /> + * + * @param src the curve to be subdivided. + * + * @param left a curve whose geometry will be set to the left half + * of <code>src</code>, or <code>null</code> if the caller is not + * interested in the left half. + * + * @param right a curve whose geometry will be set to the right half + * of <code>src</code>, or <code>null</code> if the caller is not + * interested in the right half. + */ + public static void subdivide(QuadCurve2D src, QuadCurve2D left, + QuadCurve2D right) + { + src.subdivide(left, right); + } + + /** + * Subdivides a quadratic curve into two halves, passing all + * coordinates in an array. + * + * <p><img src="doc-files/QuadCurve2D-3.png" width="700" + * height="180" alt="A drawing that illustrates the effects of + * subdividing a QuadCurve2D" /> + * + * <p>The left end point and the right start point will always be + * identical. Memory-concious programmers thus may want to pass the + * same array for both <code>left</code> and <code>right</code>, and + * set <code>rightOff</code> to <code>leftOff + 4</code>. + * + * @param src an array containing the coordinates of the curve to be + * subdivided. The <i>x</i> coordinate of the start point is + * located at <code>src[srcOff]</code>, its <i>y</i> at + * <code>src[srcOff + 1]</code>. The <i>x</i> coordinate of the + * control point is located at <code>src[srcOff + 2]</code>, its + * <i>y</i> at <code>src[srcOff + 3]</code>. The <i>x</i> + * coordinate of the end point is located at <code>src[srcOff + + * 4]</code>, its <i>y</i> at <code>src[srcOff + 5]</code>. + * + * @param srcOff an offset into <code>src</code>, specifying + * the index of the start point’s <i>x</i> coordinate. + * + * @param left an array that will receive the coordinates of the + * left half of <code>src</code>. It is acceptable to pass + * <code>src</code>. A caller who is not interested in the left half + * can pass <code>null</code>. + * + * @param leftOff an offset into <code>left</code>, specifying the + * index where the start point’s <i>x</i> coordinate will be + * stored. + * + * @param right an array that will receive the coordinates of the + * right half of <code>src</code>. It is acceptable to pass + * <code>src</code> or <code>left</code>. A caller who is not + * interested in the right half can pass <code>null</code>. + * + * @param rightOff an offset into <code>right</code>, specifying the + * index where the start point’s <i>x</i> coordinate will be + * stored. + */ + public static void subdivide(double[] src, int srcOff, double[] left, + int leftOff, double[] right, int rightOff) + { + double x1; + double y1; + double xc; + double yc; + double x2; + double y2; + + x1 = src[srcOff]; + y1 = src[srcOff + 1]; + xc = src[srcOff + 2]; + yc = src[srcOff + 3]; + x2 = src[srcOff + 4]; + y2 = src[srcOff + 5]; + + if (left != null) + { + left[leftOff] = x1; + left[leftOff + 1] = y1; + } + + if (right != null) + { + right[rightOff + 4] = x2; + right[rightOff + 5] = y2; + } + + x1 = (x1 + xc) / 2; + x2 = (xc + x2) / 2; + xc = (x1 + x2) / 2; + y1 = (y1 + yc) / 2; + y2 = (y2 + yc) / 2; + yc = (y1 + y2) / 2; + + if (left != null) + { + left[leftOff + 2] = x1; + left[leftOff + 3] = y1; + left[leftOff + 4] = xc; + left[leftOff + 5] = yc; + } + + if (right != null) + { + right[rightOff] = xc; + right[rightOff + 1] = yc; + right[rightOff + 2] = x2; + right[rightOff + 3] = y2; + } + } + + /** + * Finds the non-complex roots of a quadratic equation, placing the + * results into the same array as the equation coefficients. The + * following equation is being solved: + * + * <blockquote><code>eqn[2]</code> · <i>x</i><sup>2</sup> + * + <code>eqn[1]</code> · <i>x</i> + * + <code>eqn[0]</code> + * = 0 + * </blockquote> + * + * <p>For some background about solving quadratic equations, see the + * article <a href= + * "http://planetmath.org/encyclopedia/QuadraticFormula.html" + * >“Quadratic Formula”</a> in <a href= + * "http://planetmath.org/">PlanetMath</a>. For an extensive library + * of numerical algorithms written in the C programming language, + * see the <a href="http://www.gnu.org/software/gsl/">GNU Scientific + * Library</a>. + * + * @see #solveQuadratic(double[], double[]) + * @see CubicCurve2D#solveCubic(double[], double[]) + * + * @param eqn an array with the coefficients of the equation. When + * this procedure has returned, <code>eqn</code> will contain the + * non-complex solutions of the equation, in no particular order. + * + * @return the number of non-complex solutions. A result of 0 + * indicates that the equation has no non-complex solutions. A + * result of -1 indicates that the equation is constant (i.e., + * always or never zero). + * + * @author Brian Gough (bjg@network-theory.com) + * (original C implementation in the <a href= + * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>) + * + * @author Sascha Brawer (brawer@dandelis.ch) + * (adaptation to Java) + */ + public static int solveQuadratic(double[] eqn) + { + return solveQuadratic(eqn, eqn); + } + + /** + * Finds the non-complex roots of a quadratic equation. The + * following equation is being solved: + * + * <blockquote><code>eqn[2]</code> · <i>x</i><sup>2</sup> + * + <code>eqn[1]</code> · <i>x</i> + * + <code>eqn[0]</code> + * = 0 + * </blockquote> + * + * <p>For some background about solving quadratic equations, see the + * article <a href= + * "http://planetmath.org/encyclopedia/QuadraticFormula.html" + * >“Quadratic Formula”</a> in <a href= + * "http://planetmath.org/">PlanetMath</a>. For an extensive library + * of numerical algorithms written in the C programming language, + * see the <a href="http://www.gnu.org/software/gsl/">GNU Scientific + * Library</a>. + * + * @see CubicCurve2D#solveCubic(double[],double[]) + * + * @param eqn an array with the coefficients of the equation. + * + * @param res an array into which the non-complex roots will be + * stored. The results may be in an arbitrary order. It is safe to + * pass the same array object reference for both <code>eqn</code> + * and <code>res</code>. + * + * @return the number of non-complex solutions. A result of 0 + * indicates that the equation has no non-complex solutions. A + * result of -1 indicates that the equation is constant (i.e., + * always or never zero). + * + * @author Brian Gough (bjg@network-theory.com) + * (original C implementation in the <a href= + * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>) + * + * @author Sascha Brawer (brawer@dandelis.ch) + * (adaptation to Java) + */ + public static int solveQuadratic(double[] eqn, double[] res) + { + // Taken from poly/solve_quadratic.c in the GNU Scientific Library + // (GSL), cvs revision 1.7 of 2003-07-26. For the original source, + // see http://www.gnu.org/software/gsl/ + // + // Brian Gough, the author of that code, has granted the + // permission to use it in GNU Classpath under the GNU Classpath + // license, and has assigned the copyright to the Free Software + // Foundation. + // + // The Java implementation is very similar to the GSL code, but + // not a strict one-to-one copy. For example, GSL would sort the + // result. + double a; + double b; + double c; + double disc; + + c = eqn[0]; + b = eqn[1]; + a = eqn[2]; + + // Check for linear or constant functions. This is not done by the + // GNU Scientific Library. Without this special check, we + // wouldn't return -1 for constant functions, and 2 instead of 1 + // for linear functions. + if (a == 0) + { + if (b == 0) + return -1; + + res[0] = -c / b; + return 1; + } + + disc = b * b - 4 * a * c; + + if (disc < 0) + return 0; + + if (disc == 0) + { + // The GNU Scientific Library returns two identical results here. + // We just return one. + res[0] = -0.5 * b / a; + return 1; + } + + // disc > 0 + if (b == 0) + { + double r; + + r = Math.abs(0.5 * Math.sqrt(disc) / a); + res[0] = -r; + res[1] = r; + } + else + { + double sgnb; + double temp; + + sgnb = (b > 0 ? 1 : -1); + temp = -0.5 * (b + sgnb * Math.sqrt(disc)); + + // The GNU Scientific Library sorts the result here. We don't. + res[0] = temp / a; + res[1] = c / temp; + } + return 2; + } + + /** + * Determines whether a point is inside the area bounded + * by the curve and the straight line connecting its end points. + * + * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180" + * alt="A drawing of the area spanned by the curve" /> + * + * <p>The above drawing illustrates in which area points are + * considered “inside” a QuadCurve2D. + */ + public boolean contains(double x, double y) + { + if (! getBounds2D().contains(x, y)) + return false; + + return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0); + } + + /** + * Determines whether a point is inside the area bounded + * by the curve and the straight line connecting its end points. + * + * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180" + * alt="A drawing of the area spanned by the curve" /> + * + * <p>The above drawing illustrates in which area points are + * considered “inside” a QuadCurve2D. + */ + public boolean contains(Point2D p) + { + return contains(p.getX(), p.getY()); + } + + /** + * Determines whether any part of a rectangle is inside the area bounded + * by the curve and the straight line connecting its end points. + * + * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180" + * alt="A drawing of the area spanned by the curve" /> + * + * <p>The above drawing illustrates in which area points are + * considered “inside” in a CubicCurve2D. + */ + public boolean intersects(double x, double y, double w, double h) + { + if (! getBounds2D().contains(x, y, w, h)) + return false; + + /* Does any edge intersect? */ + if (getAxisIntersections(x, y, true, w) != 0 /* top */ + || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */ + || getAxisIntersections(x + w, y, false, h) != 0 /* right */ + || getAxisIntersections(x, y, false, h) != 0) /* left */ + return true; + + /* No intersections, is any point inside? */ + if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0) + return true; + + return false; + } + + /** + * Determines whether any part of a Rectangle2D is inside the area bounded + * by the curve and the straight line connecting its end points. + * @see #intersects(double, double, double, double) + */ + public boolean intersects(Rectangle2D r) + { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Determines whether a rectangle is entirely inside the area bounded + * by the curve and the straight line connecting its end points. + * + * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180" + * alt="A drawing of the area spanned by the curve" /> + * + * <p>The above drawing illustrates in which area points are + * considered “inside” a QuadCurve2D. + * @see #contains(double, double) + */ + public boolean contains(double x, double y, double w, double h) + { + if (! getBounds2D().intersects(x, y, w, h)) + return false; + + /* Does any edge intersect? */ + if (getAxisIntersections(x, y, true, w) != 0 /* top */ + || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */ + || getAxisIntersections(x + w, y, false, h) != 0 /* right */ + || getAxisIntersections(x, y, false, h) != 0) /* left */ + return false; + + /* No intersections, is any point inside? */ + if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0) + return true; + + return false; + } + + /** + * Determines whether a Rectangle2D is entirely inside the area that is + * bounded by the curve and the straight line connecting its end points. + * @see #contains(double, double, double, double) + */ + public boolean contains(Rectangle2D r) + { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Determines the smallest rectangle that encloses the + * curve’s start, end and control point. As the illustration + * below shows, the invisible control point may cause the bounds to + * be much larger than the area that is actually covered by the + * curve. + * + * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180" + * alt="An illustration of the bounds of a QuadCurve2D" /> + */ + public Rectangle getBounds() + { + return getBounds2D().getBounds(); + } + + public PathIterator getPathIterator(final AffineTransform at) + { + return new PathIterator() + { + /** Current coordinate. */ + private int current = 0; + + public int getWindingRule() + { + return WIND_NON_ZERO; + } + + public boolean isDone() + { + return current >= 2; + } + + public void next() + { + current++; + } + + public int currentSegment(float[] coords) + { + int result; + switch (current) + { + case 0: + coords[0] = (float) getX1(); + coords[1] = (float) getY1(); + result = SEG_MOVETO; + break; + case 1: + coords[0] = (float) getCtrlX(); + coords[1] = (float) getCtrlY(); + coords[2] = (float) getX2(); + coords[3] = (float) getY2(); + result = SEG_QUADTO; + break; + default: + throw new NoSuchElementException("quad iterator out of bounds"); + } + if (at != null) + at.transform(coords, 0, coords, 0, 2); + return result; + } + + public int currentSegment(double[] coords) + { + int result; + switch (current) + { + case 0: + coords[0] = getX1(); + coords[1] = getY1(); + result = SEG_MOVETO; + break; + case 1: + coords[0] = getCtrlX(); + coords[1] = getCtrlY(); + coords[2] = getX2(); + coords[3] = getY2(); + result = SEG_QUADTO; + break; + default: + throw new NoSuchElementException("quad iterator out of bounds"); + } + if (at != null) + at.transform(coords, 0, coords, 0, 2); + return result; + } + }; + } + + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return new FlatteningPathIterator(getPathIterator(at), flatness); + } + + /** + * Creates a new curve with the same contents as this one. + * + * @return the clone. + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // Impossible + } + } + + /** + * Helper method used by contains() and intersects() methods + * Return the number of curve/line intersections on a given axis + * extending from a certain point. useYaxis is true for using the Y axis, + * @param x x coordinate of the origin point + * @param y y coordinate of the origin point + * @param useYaxis axis to follow, if true the positive Y axis is used, + * false uses the positive X axis. + * + * This is an implementation of the line-crossings algorithm, + * Detailed in an article on Eric Haines' page: + * http://www.acm.org/tog/editors/erich/ptinpoly/ + */ + private int getAxisIntersections(double x, double y, boolean useYaxis, + double distance) + { + int nCrossings = 0; + double a0; + double a1; + double a2; + double b0; + double b1; + double b2; + double[] r = new double[3]; + int nRoots; + + a0 = a2 = 0.0; + + if (useYaxis) + { + a0 = getY1() - y; + a1 = getCtrlY() - y; + a2 = getY2() - y; + b0 = getX1() - x; + b1 = getCtrlX() - x; + b2 = getX2() - x; + } + else + { + a0 = getX1() - x; + a1 = getCtrlX() - x; + a2 = getX2() - x; + b0 = getY1() - y; + b1 = getCtrlY() - y; + b2 = getY2() - y; + } + + /* If the axis intersects a start/endpoint, shift it up by some small + amount to guarantee the line is 'inside' + If this is not done,bad behaviour may result for points on that axis. */ + if (a0 == 0.0 || a2 == 0.0) + { + double small = getFlatness() * EPSILON; + if (a0 == 0.0) + a0 -= small; + + if (a2 == 0.0) + a2 -= small; + } + + r[0] = a0; + r[1] = 2 * (a1 - a0); + r[2] = (a2 - 2 * a1 + a0); + + nRoots = solveQuadratic(r); + for (int i = 0; i < nRoots; i++) + { + double t = r[i]; + if (t >= 0.0 && t <= 1.0) + { + double crossing = t * t * (b2 - 2 * b1 + b0) + 2 * t * (b1 - b0) + + b0; + /* single root is always doubly degenerate in quads */ + if (crossing > 0 && crossing < distance) + nCrossings += (nRoots == 1) ? 2 : 1; + } + } + + if (useYaxis) + { + if (Line2D.linesIntersect(b0, a0, b2, a2, EPSILON, 0.0, distance, 0.0)) + nCrossings++; + } + else + { + if (Line2D.linesIntersect(a0, b0, a2, b2, 0.0, EPSILON, 0.0, distance)) + nCrossings++; + } + + return (nCrossings); + } + + /** + * A two-dimensional curve that is parameterized with a quadratic + * function and stores coordinate values in double-precision + * floating-point format. + * + * @see QuadCurve2D.Float + * + * @author Eric Blake (ebb9@email.byu.edu) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class Double extends QuadCurve2D + { + /** + * The <i>x</i> coordinate of the curve’s start point. + */ + public double x1; + + /** + * The <i>y</i> coordinate of the curve’s start point. + */ + public double y1; + + /** + * The <i>x</i> coordinate of the curve’s control point. + */ + public double ctrlx; + + /** + * The <i>y</i> coordinate of the curve’s control point. + */ + public double ctrly; + + /** + * The <i>x</i> coordinate of the curve’s end point. + */ + public double x2; + + /** + * The <i>y</i> coordinate of the curve’s end point. + */ + public double y2; + + /** + * Constructs a new QuadCurve2D that stores its coordinate values + * in double-precision floating-point format. All points are + * initially at position (0, 0). + */ + public Double() + { + } + + /** + * Constructs a new QuadCurve2D that stores its coordinate values + * in double-precision floating-point format, specifying the + * initial position of each point. + * + * @param x1 the <i>x</i> coordinate of the curve’s start + * point. + * + * @param y1 the <i>y</i> coordinate of the curve’s start + * point. + * + * @param cx the <i>x</i> coordinate of the curve’s control + * point. + * + * @param cy the <i>y</i> coordinate of the curve’s control + * point. + * + * @param x2 the <i>x</i> coordinate of the curve’s end + * point. + * + * @param y2 the <i>y</i> coordinate of the curve’s end + * point. + */ + public Double(double x1, double y1, double cx, double cy, double x2, + double y2) + { + this.x1 = x1; + this.y1 = y1; + ctrlx = cx; + ctrly = cy; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Returns the <i>x</i> coordinate of the curve’s start + * point. + */ + public double getX1() + { + return x1; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s start + * point. + */ + public double getY1() + { + return y1; + } + + /** + * Returns the curve’s start point. + */ + public Point2D getP1() + { + return new Point2D.Double(x1, y1); + } + + /** + * Returns the <i>x</i> coordinate of the curve’s control + * point. + */ + public double getCtrlX() + { + return ctrlx; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s control + * point. + */ + public double getCtrlY() + { + return ctrly; + } + + /** + * Returns the curve’s control point. + */ + public Point2D getCtrlPt() + { + return new Point2D.Double(ctrlx, ctrly); + } + + /** + * Returns the <i>x</i> coordinate of the curve’s end + * point. + */ + public double getX2() + { + return x2; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s end + * point. + */ + public double getY2() + { + return y2; + } + + /** + * Returns the curve’s end point. + */ + public Point2D getP2() + { + return new Point2D.Double(x2, y2); + } + + /** + * Changes the geometry of the curve. + * + * @param x1 the <i>x</i> coordinate of the curve’s new + * start point. + * + * @param y1 the <i>y</i> coordinate of the curve’s new + * start point. + * + * @param cx the <i>x</i> coordinate of the curve’s new + * control point. + * + * @param cy the <i>y</i> coordinate of the curve’s new + * control point. + * + * @param x2 the <i>x</i> coordinate of the curve’s new + * end point. + * + * @param y2 the <i>y</i> coordinate of the curve’s new + * end point. + */ + public void setCurve(double x1, double y1, double cx, double cy, + double x2, double y2) + { + this.x1 = x1; + this.y1 = y1; + ctrlx = cx; + ctrly = cy; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Determines the smallest rectangle that encloses the + * curve’s start, end and control point. As the + * illustration below shows, the invisible control point may cause + * the bounds to be much larger than the area that is actually + * covered by the curve. + * + * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180" + * alt="An illustration of the bounds of a QuadCurve2D" /> + */ + public Rectangle2D getBounds2D() + { + double nx1 = Math.min(Math.min(x1, ctrlx), x2); + double ny1 = Math.min(Math.min(y1, ctrly), y2); + double nx2 = Math.max(Math.max(x1, ctrlx), x2); + double ny2 = Math.max(Math.max(y1, ctrly), y2); + return new Rectangle2D.Double(nx1, ny1, nx2 - nx1, ny2 - ny1); + } + } + + /** + * A two-dimensional curve that is parameterized with a quadratic + * function and stores coordinate values in single-precision + * floating-point format. + * + * @see QuadCurve2D.Double + * + * @author Eric Blake (ebb9@email.byu.edu) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class Float extends QuadCurve2D + { + /** + * The <i>x</i> coordinate of the curve’s start point. + */ + public float x1; + + /** + * The <i>y</i> coordinate of the curve’s start point. + */ + public float y1; + + /** + * The <i>x</i> coordinate of the curve’s control point. + */ + public float ctrlx; + + /** + * The <i>y</i> coordinate of the curve’s control point. + */ + public float ctrly; + + /** + * The <i>x</i> coordinate of the curve’s end point. + */ + public float x2; + + /** + * The <i>y</i> coordinate of the curve’s end point. + */ + public float y2; + + /** + * Constructs a new QuadCurve2D that stores its coordinate values + * in single-precision floating-point format. All points are + * initially at position (0, 0). + */ + public Float() + { + } + + /** + * Constructs a new QuadCurve2D that stores its coordinate values + * in single-precision floating-point format, specifying the + * initial position of each point. + * + * @param x1 the <i>x</i> coordinate of the curve’s start + * point. + * + * @param y1 the <i>y</i> coordinate of the curve’s start + * point. + * + * @param cx the <i>x</i> coordinate of the curve’s control + * point. + * + * @param cy the <i>y</i> coordinate of the curve’s control + * point. + * + * @param x2 the <i>x</i> coordinate of the curve’s end + * point. + * + * @param y2 the <i>y</i> coordinate of the curve’s end + * point. + */ + public Float(float x1, float y1, float cx, float cy, float x2, float y2) + { + this.x1 = x1; + this.y1 = y1; + ctrlx = cx; + ctrly = cy; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Returns the <i>x</i> coordinate of the curve’s start + * point. + */ + public double getX1() + { + return x1; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s start + * point. + */ + public double getY1() + { + return y1; + } + + /** + * Returns the curve’s start point. + */ + public Point2D getP1() + { + return new Point2D.Float(x1, y1); + } + + /** + * Returns the <i>x</i> coordinate of the curve’s control + * point. + */ + public double getCtrlX() + { + return ctrlx; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s control + * point. + */ + public double getCtrlY() + { + return ctrly; + } + + /** + * Returns the curve’s control point. + */ + public Point2D getCtrlPt() + { + return new Point2D.Float(ctrlx, ctrly); + } + + /** + * Returns the <i>x</i> coordinate of the curve’s end + * point. + */ + public double getX2() + { + return x2; + } + + /** + * Returns the <i>y</i> coordinate of the curve’s end + * point. + */ + public double getY2() + { + return y2; + } + + /** + * Returns the curve’s end point. + */ + public Point2D getP2() + { + return new Point2D.Float(x2, y2); + } + + /** + * Changes the geometry of the curve, specifying coordinate values + * as double-precision floating-point numbers. + * + * @param x1 the <i>x</i> coordinate of the curve’s new + * start point. + * + * @param y1 the <i>y</i> coordinate of the curve’s new + * start point. + * + * @param cx the <i>x</i> coordinate of the curve’s new + * control point. + * + * @param cy the <i>y</i> coordinate of the curve’s new + * control point. + * + * @param x2 the <i>x</i> coordinate of the curve’s new + * end point. + * + * @param y2 the <i>y</i> coordinate of the curve’s new + * end point. + */ + public void setCurve(double x1, double y1, double cx, double cy, + double x2, double y2) + { + this.x1 = (float) x1; + this.y1 = (float) y1; + ctrlx = (float) cx; + ctrly = (float) cy; + this.x2 = (float) x2; + this.y2 = (float) y2; + } + + /** + * Changes the geometry of the curve, specifying coordinate values + * as single-precision floating-point numbers. + * + * @param x1 the <i>x</i> coordinate of the curve’s new + * start point. + * + * @param y1 the <i>y</i> coordinate of the curve’s new + * start point. + * + * @param cx the <i>x</i> coordinate of the curve’s new + * control point. + * + * @param cy the <i>y</i> coordinate of the curve’s new + * control point. + * + * @param x2 the <i>x</i> coordinate of the curve’s new + * end point. + * + * @param y2 the <i>y</i> coordinate of the curve’s new + * end point. + */ + public void setCurve(float x1, float y1, float cx, float cy, float x2, + float y2) + { + this.x1 = x1; + this.y1 = y1; + ctrlx = cx; + ctrly = cy; + this.x2 = x2; + this.y2 = y2; + } + + /** + * Determines the smallest rectangle that encloses the + * curve’s start, end and control point. As the + * illustration below shows, the invisible control point may cause + * the bounds to be much larger than the area that is actually + * covered by the curve. + * + * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180" + * alt="An illustration of the bounds of a QuadCurve2D" /> + */ + public Rectangle2D getBounds2D() + { + float nx1 = (float) Math.min(Math.min(x1, ctrlx), x2); + float ny1 = (float) Math.min(Math.min(y1, ctrly), y2); + float nx2 = (float) Math.max(Math.max(x1, ctrlx), x2); + float ny2 = (float) Math.max(Math.max(y1, ctrly), y2); + return new Rectangle2D.Float(nx1, ny1, nx2 - nx1, ny2 - ny1); + } + } +} diff --git a/libjava/classpath/java/awt/geom/Rectangle2D.java b/libjava/classpath/java/awt/geom/Rectangle2D.java new file mode 100644 index 0000000..6a255f9 --- /dev/null +++ b/libjava/classpath/java/awt/geom/Rectangle2D.java @@ -0,0 +1,992 @@ +/* Rectangle2D.java -- generic rectangles in 2-D space + Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.geom; + +import java.util.NoSuchElementException; + +/** + * This class describes a rectangle by a point (x,y) and dimension (w x h). + * The actual storage is left up to subclasses. + * + * <p>It is valid for a rectangle to have negative width or height; but it + * is considered to have no area or internal points. Therefore, the behavior + * in methods like <code>contains</code> or <code>intersects</code> is + * undefined unless the rectangle has positive width and height. + * + * @author Tom Tromey (tromey@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ +public abstract class Rectangle2D extends RectangularShape +{ + /** + * The point lies left of the rectangle (p.x < r.x). + * + * @see #outcode(double, double) + */ + public static final int OUT_LEFT = 1; + + /** + * The point lies above the rectangle (p.y < r.y). + * + * @see #outcode(double, double) + */ + public static final int OUT_TOP = 2; + + /** + * The point lies right of the rectangle (p.x > r.maxX). + * + * @see #outcode(double, double) + */ + public static final int OUT_RIGHT = 4; + + /** + * The point lies below of the rectangle (p.y > r.maxY). + * + * @see #outcode(double, double) + */ + public static final int OUT_BOTTOM = 8; + + /** + * Default constructor. + */ + protected Rectangle2D() + { + } + + /** + * Set the bounding box of this rectangle. + * + * @param x the new X coordinate + * @param y the new Y coordinate + * @param w the new width + * @param h the new height + */ + public abstract void setRect(double x, double y, double w, double h); + + /** + * Set the bounding box of this rectangle from the given one. + * + * @param r rectangle to copy + * @throws NullPointerException if r is null + */ + public void setRect(Rectangle2D r) + { + setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Tests if the specified line intersects the interior of this rectangle. + * + * @param x1 the first x coordinate of line segment + * @param y1 the first y coordinate of line segment + * @param x2 the second x coordinate of line segment + * @param y2 the second y coordinate of line segment + * @return true if the line intersects the rectangle + */ + public boolean intersectsLine(double x1, double y1, double x2, double y2) + { + double x = getX(); + double y = getY(); + double w = getWidth(); + double h = getHeight(); + if (w <= 0 || h <= 0) + return false; + + if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h) + return true; + if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h) + return true; + + double x3 = x + w; + double y3 = y + h; + + return (Line2D.linesIntersect(x1, y1, x2, y2, x, y, x, y3) + || Line2D.linesIntersect(x1, y1, x2, y2, x, y3, x3, y3) + || Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x3, y) + || Line2D.linesIntersect(x1, y1, x2, y2, x3, y, x, y)); + } + + /** + * Tests if the specified line intersects the interior of this rectangle. + * + * @param l the line segment + * @return true if the line intersects the rectangle + * @throws NullPointerException if l is null + */ + public boolean intersectsLine(Line2D l) + { + return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2()); + } + + /** + * Determine where the point lies with respect to this rectangle. The + * result will be the binary OR of the appropriate bit masks. + * + * @param x the x coordinate to check + * @param y the y coordinate to check + * @return the binary OR of the result + * @see #OUT_LEFT + * @see #OUT_TOP + * @see #OUT_RIGHT + * @see #OUT_BOTTOM + */ + public abstract int outcode(double x, double y); + + /** + * Determine where the point lies with respect to this rectangle. The + * result will be the binary OR of the appropriate bit masks. + * + * @param p the point to check + * @return the binary OR of the result + * @throws NullPointerException if p is null + * @see #OUT_LEFT + * @see #OUT_TOP + * @see #OUT_RIGHT + * @see #OUT_BOTTOM + */ + public int outcode(Point2D p) + { + return outcode(p.getX(), p.getY()); + } + + /** + * Set the bounding box of this rectangle. + * + * @param x the new X coordinate + * @param y the new Y coordinate + * @param w the new width + * @param h the new height + */ + public void setFrame(double x, double y, double w, double h) + { + setRect(x, y, w, h); + } + + /** + * Returns the bounds of this rectangle. A pretty useless method, as this + * is already a rectangle. + * + * @return a copy of this rectangle + */ + public Rectangle2D getBounds2D() + { + return (Rectangle2D) clone(); + } + + /** + * Test if the given point is contained in the rectangle. + * + * @param x the x coordinate of the point + * @param y the y coordinate of the point + * @return true if (x,y) is in the rectangle + */ + public boolean contains(double x, double y) + { + double mx = getX(); + double my = getY(); + double w = getWidth(); + double h = getHeight(); + return w > 0 && h > 0 && x >= mx && x < mx + w && y >= my && y < my + h; + } + + /** + * Tests if the given rectangle intersects this one. In other words, test if + * the two rectangles share at least one internal point. + * + * @param x the x coordinate of the other rectangle + * @param y the y coordinate of the other rectangle + * @param w the width of the other rectangle + * @param h the height of the other rectangle + * @return true if the rectangles intersect + */ + public boolean intersects(double x, double y, double w, double h) + { + double mx = getX(); + double my = getY(); + double mw = getWidth(); + double mh = getHeight(); + return w > 0 && h > 0 && mw > 0 && mh > 0 + && x < mx + mw && x + w > mx && y < my + mh && y + h > my; + } + + /** + * Tests if this rectangle contains the given one. In other words, test if + * this rectangle contains all points in the given one. + * + * @param x the x coordinate of the other rectangle + * @param y the y coordinate of the other rectangle + * @param w the width of the other rectangle + * @param h the height of the other rectangle + * @return true if this rectangle contains the other + */ + public boolean contains(double x, double y, double w, double h) + { + double mx = getX(); + double my = getY(); + double mw = getWidth(); + double mh = getHeight(); + return w > 0 && h > 0 && mw > 0 && mh > 0 + && x >= mx && x + w <= mx + mw && y >= my && y + h <= my + mh; + } + + /** + * Return a new rectangle which is the intersection of this and the given + * one. The result will be empty if there is no intersection. + * + * @param r the rectangle to be intersected + * @return the intersection + * @throws NullPointerException if r is null + */ + public abstract Rectangle2D createIntersection(Rectangle2D r); + + /** + * Intersects a pair of rectangles, and places the result in the + * destination; this can be used to avoid object creation. This method + * even works when the destination is also a source, although you stand + * to lose the original data. + * + * @param src1 the first source + * @param src2 the second source + * @param dest the destination for the intersection + * @throws NullPointerException if any rectangle is null + */ + public static void intersect(Rectangle2D src1, Rectangle2D src2, + Rectangle2D dest) + { + double x = Math.max(src1.getX(), src2.getX()); + double y = Math.max(src1.getY(), src2.getY()); + double maxx = Math.min(src1.getMaxX(), src2.getMaxX()); + double maxy = Math.min(src1.getMaxY(), src2.getMaxY()); + dest.setRect(x, y, maxx - x, maxy - y); + } + + /** + * Return a new rectangle which is the union of this and the given one. + * + * @param r the rectangle to be merged + * @return the union + * @throws NullPointerException if r is null + */ + public abstract Rectangle2D createUnion(Rectangle2D r); + + /** + * Joins a pair of rectangles, and places the result in the destination; + * this can be used to avoid object creation. This method even works when + * the destination is also a source, although you stand to lose the + * original data. + * + * @param src1 the first source + * @param src2 the second source + * @param dest the destination for the union + * @throws NullPointerException if any rectangle is null + */ + public static void union(Rectangle2D src1, Rectangle2D src2, + Rectangle2D dest) + { + double x = Math.min(src1.getX(), src2.getX()); + double y = Math.min(src1.getY(), src2.getY()); + double maxx = Math.max(src1.getMaxX(), src2.getMaxX()); + double maxy = Math.max(src1.getMaxY(), src2.getMaxY()); + dest.setRect(x, y, maxx - x, maxy - y); + } + + /** + * Modifies this rectangle so that it represents the smallest rectangle + * that contains both the existing rectangle and the specified point. + * However, if the point falls on one of the two borders which are not + * inside the rectangle, a subsequent call to <code>contains</code> may + * return false. + * + * @param newx the X coordinate of the point to add to this rectangle + * @param newy the Y coordinate of the point to add to this rectangle + */ + public void add(double newx, double newy) + { + double minx = Math.min(getX(), newx); + double maxx = Math.max(getMaxX(), newx); + double miny = Math.min(getY(), newy); + double maxy = Math.max(getMaxY(), newy); + setRect(minx, miny, maxx - minx, maxy - miny); + } + + /** + * Modifies this rectangle so that it represents the smallest rectangle + * that contains both the existing rectangle and the specified point. + * However, if the point falls on one of the two borders which are not + * inside the rectangle, a subsequent call to <code>contains</code> may + * return false. + * + * @param p the point to add to this rectangle + * @throws NullPointerException if p is null + */ + public void add(Point2D p) + { + add(p.getX(), p.getY()); + } + + /** + * Modifies this rectangle so that it represents the smallest rectangle + * that contains both the existing rectangle and the specified rectangle. + * + * @param r the rectangle to add to this rectangle + * @throws NullPointerException if r is null + * @see #union(Rectangle2D, Rectangle2D, Rectangle2D) + */ + public void add(Rectangle2D r) + { + union(this, r, this); + } + + /** + * Return an iterator along the shape boundary. If the optional transform + * is provided, the iterator is transformed accordingly. Each call returns + * a new object, independent from others in use. This iterator is thread + * safe; modifications to the rectangle do not affect the results of this + * path instance. + * + * @param at an optional transform to apply to the iterator + * @return a new iterator over the boundary + * @since 1.2 + */ + public PathIterator getPathIterator(final AffineTransform at) + { + final double minx = getX(); + final double miny = getY(); + final double maxx = minx + getWidth(); + final double maxy = miny + getHeight(); + return new PathIterator() + { + /** Current coordinate. */ + private int current = (maxx <= minx && maxy <= miny) ? 6 : 0; + + public int getWindingRule() + { + // A test program showed that Sun J2SE 1.3.1 and 1.4.1_01 + // return WIND_NON_ZERO paths. While this does not really + // make any difference for rectangles (because they are not + // self-intersecting), it seems appropriate to behave + // identically. + + return WIND_NON_ZERO; + } + + public boolean isDone() + { + return current > 5; + } + + public void next() + { + current++; + } + + public int currentSegment(float[] coords) + { + switch (current) + { + case 1: + coords[0] = (float) maxx; + coords[1] = (float) miny; + break; + case 2: + coords[0] = (float) maxx; + coords[1] = (float) maxy; + break; + case 3: + coords[0] = (float) minx; + coords[1] = (float) maxy; + break; + case 0: + case 4: + coords[0] = (float) minx; + coords[1] = (float) miny; + break; + case 5: + return SEG_CLOSE; + default: + throw new NoSuchElementException("rect iterator out of bounds"); + } + if (at != null) + at.transform(coords, 0, coords, 0, 1); + return current == 0 ? SEG_MOVETO : SEG_LINETO; + } + + public int currentSegment(double[] coords) + { + switch (current) + { + case 1: + coords[0] = maxx; + coords[1] = miny; + break; + case 2: + coords[0] = maxx; + coords[1] = maxy; + break; + case 3: + coords[0] = minx; + coords[1] = maxy; + break; + case 0: + case 4: + coords[0] = minx; + coords[1] = miny; + break; + case 5: + return SEG_CLOSE; + default: + throw new NoSuchElementException("rect iterator out of bounds"); + } + if (at != null) + at.transform(coords, 0, coords, 0, 1); + return current == 0 ? SEG_MOVETO : SEG_LINETO; + } + }; + } + + /** + * Return an iterator along the shape boundary. If the optional transform + * is provided, the iterator is transformed accordingly. Each call returns + * a new object, independent from others in use. This iterator is thread + * safe; modifications to the rectangle do not affect the results of this + * path instance. As the rectangle is already flat, the flatness parameter + * is ignored. + * + * @param at an optional transform to apply to the iterator + * @param flatness the maximum distance for deviation from the real boundary + * @return a new iterator over the boundary + * @since 1.2 + */ + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return getPathIterator(at); + } + + /** + * Return the hashcode for this rectangle. The formula is not documented, but + * appears to be the same as: + * <pre> + * long l = Double.doubleToLongBits(getX()) + * + 37 * Double.doubleToLongBits(getY()) + * + 43 * Double.doubleToLongBits(getWidth()) + * + 47 * Double.doubleToLongBits(getHeight()); + * return (int) ((l >> 32) ^ l); + * </pre> + * + * @return the hashcode + */ + public int hashCode() + { + // Talk about a fun time reverse engineering this one! + long l = java.lang.Double.doubleToLongBits(getX()) + + 37 * java.lang.Double.doubleToLongBits(getY()) + + 43 * java.lang.Double.doubleToLongBits(getWidth()) + + 47 * java.lang.Double.doubleToLongBits(getHeight()); + return (int) ((l >> 32) ^ l); + } + + /** + * Tests this rectangle for equality against the specified object. This + * will be true if an only if the specified object is an instance of + * Rectangle2D with the same coordinates and dimensions. + * + * @param obj the object to test against for equality + * @return true if the specified object is equal to this one + */ + public boolean equals(Object obj) + { + if (! (obj instanceof Rectangle2D)) + return false; + Rectangle2D r = (Rectangle2D) obj; + return r.getX() == getX() && r.getY() == getY() + && r.getWidth() == getWidth() && r.getHeight() == getHeight(); + } + + /** + * This class defines a rectangle in <code>double</code> precision. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ + public static class Double extends Rectangle2D + { + /** The x coordinate of the lower left corner. */ + public double x; + + /** The y coordinate of the lower left corner. */ + public double y; + + /** The width of the rectangle. */ + public double width; + + /** The height of the rectangle. */ + public double height; + + /** + * Create a rectangle at (0,0) with width 0 and height 0. + */ + public Double() + { + } + + /** + * Create a rectangle with the given values. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + */ + public Double(double x, double y, double w, double h) + { + this.x = x; + this.y = y; + width = w; + height = h; + } + + /** + * Return the X coordinate. + * + * @return the value of x + */ + public double getX() + { + return x; + } + + /** + * Return the Y coordinate. + * + * @return the value of y + */ + public double getY() + { + return y; + } + + /** + * Return the width. + * + * @return the value of width + */ + public double getWidth() + { + return width; + } + + /** + * Return the height. + * + * @return the value of height + */ + public double getHeight() + { + return height; + } + + /** + * Test if the rectangle is empty. + * + * @return true if width or height is not positive + */ + public boolean isEmpty() + { + return width <= 0 || height <= 0; + } + + /** + * Set the contents of this rectangle to those specified. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + */ + public void setRect(double x, double y, double w, double h) + { + this.x = x; + this.y = y; + width = w; + height = h; + } + + /** + * Set the contents of this rectangle to those specified. + * + * @param r the rectangle to copy + * @throws NullPointerException if r is null + */ + public void setRect(Rectangle2D r) + { + x = r.getX(); + y = r.getY(); + width = r.getWidth(); + height = r.getHeight(); + } + + /** + * Determine where the point lies with respect to this rectangle. The + * result will be the binary OR of the appropriate bit masks. + * + * @param x the x coordinate to check + * @param y the y coordinate to check + * @return the binary OR of the result + * @see #OUT_LEFT + * @see #OUT_TOP + * @see #OUT_RIGHT + * @see #OUT_BOTTOM + * @since 1.2 + */ + public int outcode(double x, double y) + { + int result = 0; + if (width <= 0) + result |= OUT_LEFT | OUT_RIGHT; + else if (x < this.x) + result |= OUT_LEFT; + else if (x > this.x + width) + result |= OUT_RIGHT; + if (height <= 0) + result |= OUT_BOTTOM | OUT_TOP; + else if (y < this.y) // Remember that +y heads top-to-bottom. + result |= OUT_TOP; + else if (y > this.y + height) + result |= OUT_BOTTOM; + return result; + } + + /** + * Returns the bounds of this rectangle. A pretty useless method, as this + * is already a rectangle. + * + * @return a copy of this rectangle + */ + public Rectangle2D getBounds2D() + { + return new Double(x, y, width, height); + } + + /** + * Return a new rectangle which is the intersection of this and the given + * one. The result will be empty if there is no intersection. + * + * @param r the rectangle to be intersected + * @return the intersection + * @throws NullPointerException if r is null + */ + public Rectangle2D createIntersection(Rectangle2D r) + { + Double res = new Double(); + intersect(this, r, res); + return res; + } + + /** + * Return a new rectangle which is the union of this and the given one. + * + * @param r the rectangle to be merged + * @return the union + * @throws NullPointerException if r is null + */ + public Rectangle2D createUnion(Rectangle2D r) + { + Double res = new Double(); + union(this, r, res); + return res; + } + + /** + * Returns a string representation of this rectangle. This is in the form + * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width + * + ",h=" + height + ']'</code>. + * + * @return a string representation of this rectangle + */ + public String toString() + { + return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width + + ",h=" + height + ']'; + } + } + + /** + * This class defines a rectangle in <code>float</code> precision. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ + public static class Float extends Rectangle2D + { + /** The x coordinate of the lower left corner. */ + public float x; + + /** The y coordinate of the lower left corner. */ + public float y; + + /** The width of the rectangle. */ + public float width; + + /** The height of the rectangle. */ + public float height; + + /** + * Create a rectangle at (0,0) with width 0 and height 0. + */ + public Float() + { + } + + /** + * Create a rectangle with the given values. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + */ + public Float(float x, float y, float w, float h) + { + this.x = x; + this.y = y; + width = w; + height = h; + } + + /** + * Create a rectangle with the given values. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + */ + Float(double x, double y, double w, double h) + { + this.x = (float) x; + this.y = (float) y; + width = (float) w; + height = (float) h; + } + + /** + * Return the X coordinate. + * + * @return the value of x + */ + public double getX() + { + return x; + } + + /** + * Return the Y coordinate. + * + * @return the value of y + */ + public double getY() + { + return y; + } + + /** + * Return the width. + * + * @return the value of width + */ + public double getWidth() + { + return width; + } + + /** + * Return the height. + * + * @return the value of height + */ + public double getHeight() + { + return height; + } + + /** + * Test if the rectangle is empty. + * + * @return true if width or height is not positive + */ + public boolean isEmpty() + { + return width <= 0 || height <= 0; + } + + /** + * Set the contents of this rectangle to those specified. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + */ + public void setRect(float x, float y, float w, float h) + { + this.x = x; + this.y = y; + width = w; + height = h; + } + + /** + * Set the contents of this rectangle to those specified. + * + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + */ + public void setRect(double x, double y, double w, double h) + { + this.x = (float) x; + this.y = (float) y; + width = (float) w; + height = (float) h; + } + + /** + * Set the contents of this rectangle to those specified. + * + * @param r the rectangle to copy + * @throws NullPointerException if r is null + */ + public void setRect(Rectangle2D r) + { + x = (float) r.getX(); + y = (float) r.getY(); + width = (float) r.getWidth(); + height = (float) r.getHeight(); + } + + /** + * Determine where the point lies with respect to this rectangle. The + * result will be the binary OR of the appropriate bit masks. + * + * @param x the x coordinate to check + * @param y the y coordinate to check + * @return the binary OR of the result + * @see #OUT_LEFT + * @see #OUT_TOP + * @see #OUT_RIGHT + * @see #OUT_BOTTOM + * @since 1.2 + */ + public int outcode(double x, double y) + { + int result = 0; + if (width <= 0) + result |= OUT_LEFT | OUT_RIGHT; + else if (x < this.x) + result |= OUT_LEFT; + else if (x > this.x + width) + result |= OUT_RIGHT; + if (height <= 0) + result |= OUT_BOTTOM | OUT_TOP; + else if (y < this.y) // Remember that +y heads top-to-bottom. + result |= OUT_TOP; + else if (y > this.y + height) + result |= OUT_BOTTOM; + return result; + } + + /** + * Returns the bounds of this rectangle. A pretty useless method, as this + * is already a rectangle. + * + * @return a copy of this rectangle + */ + public Rectangle2D getBounds2D() + { + return new Float(x, y, width, height); + } + + /** + * Return a new rectangle which is the intersection of this and the given + * one. The result will be empty if there is no intersection. + * + * @param r the rectangle to be intersected + * @return the intersection + * @throws NullPointerException if r is null + */ + public Rectangle2D createIntersection(Rectangle2D r) + { + Float res = new Float(); + intersect(this, r, res); + return res; + } + + /** + * Return a new rectangle which is the union of this and the given one. + * + * @param r the rectangle to be merged + * @return the union + * @throws NullPointerException if r is null + */ + public Rectangle2D createUnion(Rectangle2D r) + { + Float res = new Float(); + union(this, r, res); + return res; + } + + /** + * Returns a string representation of this rectangle. This is in the form + * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width + * + ",h=" + height + ']'</code>. + * + * @return a string representation of this rectangle + */ + public String toString() + { + return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width + + ",h=" + height + ']'; + } + } +} diff --git a/libjava/classpath/java/awt/geom/RectangularShape.java b/libjava/classpath/java/awt/geom/RectangularShape.java new file mode 100644 index 0000000..8f66dab --- /dev/null +++ b/libjava/classpath/java/awt/geom/RectangularShape.java @@ -0,0 +1,385 @@ +/* RectangularShape.java -- a rectangular frame for several generic shapes + Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.geom; + +import java.awt.Rectangle; +import java.awt.Shape; + +/** + * This class provides a generic framework, and several helper methods, for + * subclasses which represent geometric objects inside a rectangular frame. + * This does not specify any geometry except for the bounding box. + * + * @author Tom Tromey (tromey@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @see Arc2D + * @see Ellipse2D + * @see Rectangle2D + * @see RoundRectangle2D + * @status updated to 1.4 + */ +public abstract class RectangularShape implements Shape, Cloneable +{ + /** + * Default constructor. + */ + protected RectangularShape() + { + } + + /** + * Get the x coordinate of the upper-left corner of the framing rectangle. + * + * @return the x coordinate + */ + public abstract double getX(); + + /** + * Get the y coordinate of the upper-left corner of the framing rectangle. + * + * @return the y coordinate + */ + public abstract double getY(); + + /** + * Get the width of the framing rectangle. + * + * @return the width + */ + public abstract double getWidth(); + + /** + * Get the height of the framing rectangle. + * + * @return the height + */ + public abstract double getHeight(); + + /** + * Get the minimum x coordinate in the frame. This is misnamed, or else + * Sun has a bug, because the implementation returns getX() even when + * getWidth() is negative. + * + * @return the minimum x coordinate + */ + public double getMinX() + { + return getX(); + } + + /** + * Get the minimum y coordinate in the frame. This is misnamed, or else + * Sun has a bug, because the implementation returns getY() even when + * getHeight() is negative. + * + * @return the minimum y coordinate + */ + public double getMinY() + { + return getY(); + } + + /** + * Get the maximum x coordinate in the frame. This is misnamed, or else + * Sun has a bug, because the implementation returns getX()+getWidth() even + * when getWidth() is negative. + * + * @return the maximum x coordinate + */ + public double getMaxX() + { + return getX() + getWidth(); + } + + /** + * Get the maximum y coordinate in the frame. This is misnamed, or else + * Sun has a bug, because the implementation returns getY()+getHeight() even + * when getHeight() is negative. + * + * @return the maximum y coordinate + */ + public double getMaxY() + { + return getY() + getHeight(); + } + + /** + * Return the x coordinate of the center point of the framing rectangle. + * + * @return the central x coordinate + */ + public double getCenterX() + { + return getX() + getWidth() / 2; + } + + /** + * Return the y coordinate of the center point of the framing rectangle. + * + * @return the central y coordinate + */ + public double getCenterY() + { + return getY() + getHeight() / 2; + } + + /** + * Return the frame around this object. Note that this may be a looser + * bounding box than getBounds2D. + * + * @return the frame, in double precision + * @see #setFrame(double, double, double, double) + */ + public Rectangle2D getFrame() + { + return new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight()); + } + + /** + * Test if the shape is empty, meaning that no points are inside it. + * + * @return true if the shape is empty + */ + public abstract boolean isEmpty(); + + /** + * Set the framing rectangle of this shape to the given coordinate and size. + * + * @param x the new x coordinate + * @param y the new y coordinate + * @param w the new width + * @param h the new height + * @see #getFrame() + */ + public abstract void setFrame(double x, double y, double w, double h); + + /** + * Set the framing rectangle of this shape to the given coordinate and size. + * + * @param p the new point + * @param d the new dimension + * @throws NullPointerException if p or d is null + * @see #getFrame() + */ + public void setFrame(Point2D p, Dimension2D d) + { + setFrame(p.getX(), p.getY(), d.getWidth(), d.getHeight()); + } + + /** + * Set the framing rectangle of this shape to the given rectangle. + * + * @param r the new framing rectangle + * @throws NullPointerException if r is null + * @see #getFrame() + */ + public void setFrame(Rectangle2D r) + { + setFrame(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Set the framing rectangle of this shape using two points on a diagonal. + * The area will be positive. + * + * @param x1 the first x coordinate + * @param y1 the first y coordinate + * @param x2 the second x coordinate + * @param y2 the second y coordinate + */ + public void setFrameFromDiagonal(double x1, double y1, double x2, double y2) + { + if (x1 > x2) + { + double t = x2; + x2 = x1; + x1 = t; + } + if (y1 > y2) + { + double t = y2; + y2 = y1; + y1 = t; + } + setFrame(x1, y1, x2 - x1, y2 - y1); + } + + /** + * Set the framing rectangle of this shape using two points on a diagonal. + * The area will be positive. + * + * @param p1 the first point + * @param p2 the second point + * @throws NullPointerException if either point is null + */ + public void setFrameFromDiagonal(Point2D p1, Point2D p2) + { + setFrameFromDiagonal(p1.getX(), p1.getY(), p2.getX(), p2.getY()); + } + + /** + * Set the framing rectangle of this shape using the center of the frame, + * and one of the four corners. The area will be positive. + * + * @param centerX the x coordinate at the center + * @param centerY the y coordinate at the center + * @param cornerX the x coordinate at a corner + * @param cornerY the y coordinate at a corner + */ + public void setFrameFromCenter(double centerX, double centerY, + double cornerX, double cornerY) + { + double halfw = Math.abs(cornerX - centerX); + double halfh = Math.abs(cornerY - centerY); + setFrame(centerX - halfw, centerY - halfh, halfw + halfw, halfh + halfh); + } + + /** + * Set the framing rectangle of this shape using the center of the frame, + * and one of the four corners. The area will be positive. + * + * @param center the center point + * @param corner a corner point + * @throws NullPointerException if either point is null + */ + public void setFrameFromCenter(Point2D center, Point2D corner) + { + setFrameFromCenter(center.getX(), center.getY(), + corner.getX(), corner.getY()); + } + + /** + * Tests if a point is inside the boundary of the shape. + * + * @param p the point to test + * @return true if the point is inside the shape + * @throws NullPointerException if p is null + * @see #contains(double, double) + */ + public boolean contains(Point2D p) + { + return contains(p.getX(), p.getY()); + } + + /** + * Tests if a rectangle and this shape share common internal points. + * + * @param r the rectangle to test + * @return true if the rectangle intersects this shpae + * @throws NullPointerException if r is null + * @see #intersects(double, double, double, double) + */ + public boolean intersects(Rectangle2D r) + { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Tests if the shape completely contains the given rectangle. + * + * @param r the rectangle to test + * @return true if r is contained in this shape + * @throws NullPointerException if r is null + * @see #contains(double, double, double, double) + */ + public boolean contains(Rectangle2D r) + { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + /** + * Returns a bounding box for this shape, in integer format. Notice that you + * may get a tighter bound with getBounds2D. If the frame is empty, the + * box is the default empty box at the origin. + * + * @return a bounding box + */ + public Rectangle getBounds() + { + if (isEmpty()) + return new Rectangle(); + double x = getX(); + double y = getY(); + double maxx = Math.ceil(x + getWidth()); + double maxy = Math.ceil(y + getHeight()); + x = Math.floor(x); + y = Math.floor(y); + return new Rectangle((int) x, (int) y, (int) (maxx - x), (int) (maxy - y)); + } + + /** + * Return an iterator along the shape boundary. If the optional transform + * is provided, the iterator is transformed accordingly. The path is + * flattened until all segments differ from the curve by at most the value + * of the flatness parameter, within the limits of the default interpolation + * recursion limit of 1024 segments between actual points. Each call + * returns a new object, independent from others in use. The result is + * threadsafe if and only if the iterator returned by + * {@link #getPathIterator(AffineTransform)} is as well. + * + * @param at an optional transform to apply to the iterator + * @param flatness the desired flatness + * @return a new iterator over the boundary + * @throws IllegalArgumentException if flatness is invalid + * @since 1.2 + */ + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return new FlatteningPathIterator(getPathIterator(at), flatness); + } + + /** + * Create a new shape of the same run-time type with the same contents as + * this one. + * + * @return the clone + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // Impossible + } + } +} // class RectangularShape diff --git a/libjava/classpath/java/awt/geom/RoundRectangle2D.java b/libjava/classpath/java/awt/geom/RoundRectangle2D.java new file mode 100644 index 0000000..ac0e6f8 --- /dev/null +++ b/libjava/classpath/java/awt/geom/RoundRectangle2D.java @@ -0,0 +1,533 @@ +/* RoundRectangle2D.java -- represents a rectangle with rounded corners + Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.geom; + +import java.util.NoSuchElementException; + + +/** This class implements a rectangle with rounded corners. + * @author Tom Tromey (tromey@cygnus.com) + * @date December 3, 2000 + */ +public abstract class RoundRectangle2D extends RectangularShape +{ + /** Return the arc height of this round rectangle. */ + public abstract double getArcHeight(); + + /** Return the arc width of this round rectangle. */ + public abstract double getArcWidth(); + + /** Set the values of this round rectangle + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + * @param arcWidth The arc width + * @param arcHeight The arc height + */ + public abstract void setRoundRect(double x, double y, double w, double h, + double arcWidth, double arcHeight); + + /** Create a RoundRectangle2D. This is protected because this class + * is abstract and cannot be instantiated. + */ + protected RoundRectangle2D() + { + } + + /** Return true if this object contains the specified point. + * @param x The x coordinate + * @param y The y coordinate + */ + public boolean contains(double x, double y) + { + double mx = getX(); + double mw = getWidth(); + if (x < mx || x >= mx + mw) + return false; + double my = getY(); + double mh = getHeight(); + if (y < my || y >= my + mh) + return false; + + // Now check to see if the point is in range of an arc. + double dy = Math.min(Math.abs(my - y), Math.abs(my + mh - y)); + double dx = Math.min(Math.abs(mx - x), Math.abs(mx + mw - x)); + + // The arc dimensions are that of the corresponding ellipse + // thus a 90 degree segment is half of that. + double aw = getArcWidth() / 2.0; + double ah = getArcHeight() / 2.0; + if (dx > aw || dy > ah) + return true; + + // At this point DX represents the distance from the nearest edge + // of the rectangle. But we want to transform it to represent the + // scaled distance from the center of the ellipse that forms the + // arc. Hence this code: + dy = (ah - dy) / ah; + dx = (aw - dx) / aw; + + return dx * dx + dy * dy <= 1.0; + } + + /** Return true if this object contains the specified rectangle + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + */ + public boolean contains(double x, double y, double w, double h) + { + // We have to check all four points here (for ordinary rectangles + // we can just check opposing corners). + return (contains(x, y) && contains(x, y + h) && contains(x + w, y + h) + && contains(x + w, y)); + } + + /** Return a new path iterator which iterates over this rectangle. + * @param at An affine transform to apply to the object + */ + public PathIterator getPathIterator(final AffineTransform at) + { + final double minx = getX(); + final double miny = getY(); + final double maxx = minx + getWidth(); + final double maxy = miny + getHeight(); + final double arcwidth = getArcWidth(); + final double archeight = getArcHeight(); + return new PathIterator() + { + /** We iterate counterclockwise around the rectangle, starting in the + * upper right. This variable tracks our current point, which + * can be on either side of a given corner. */ + private int current = 0; + + /** Child path iterator, used for corners. */ + private PathIterator corner; + + /** This is used when rendering the corners. We re-use the arc + * for each corner. */ + private Arc2D arc = new Arc2D.Double(); + + /** Temporary array used by getPoint. */ + private double[] temp = new double[2]; + + public int getWindingRule() + { + return WIND_NON_ZERO; + } + + public boolean isDone() + { + return current > 9; + } + + private void getPoint(int val) + { + switch (val) + { + case 0: + case 8: + temp[0] = maxx; + temp[1] = miny + archeight; + break; + case 7: + temp[0] = maxx; + temp[1] = maxy - archeight; + break; + case 6: + temp[0] = maxx - arcwidth; + temp[1] = maxy; + break; + case 5: + temp[0] = minx + arcwidth; + temp[1] = maxy; + break; + case 4: + temp[0] = minx; + temp[1] = maxy - archeight; + break; + case 3: + temp[0] = minx; + temp[1] = miny + archeight; + break; + case 2: + temp[0] = minx + arcwidth; + temp[1] = miny; + break; + case 1: + temp[0] = maxx - arcwidth; + temp[1] = miny; + break; + } + } + + public void next() + { + if (current >= 8) + ++current; + else if (corner != null) + { + // We're iterating through the corner. Work on the child + // iterator; if it finishes, reset and move to the next + // point along the rectangle. + corner.next(); + if (corner.isDone()) + { + corner = null; + ++current; + } + } + else + { + // Make an arc between this point on the rectangle and + // the next one, and then iterate over this arc. + getPoint(current); + double x1 = temp[0]; + double y1 = temp[1]; + getPoint(current + 1); + Rectangle2D.Double r = new Rectangle2D.Double(Math.min(x1, + temp[0]), + Math.min(y1, + temp[1]), + Math.abs(x1 + - temp[0]), + Math.abs(y1 + - temp[1])); + arc.setArc(r, (current >> 1) * 90.0, 90.0, Arc2D.OPEN); + corner = arc.getPathIterator(at); + } + } + + public int currentSegment(float[] coords) + { + if (corner != null) + { + int r = corner.currentSegment(coords); + if (r == SEG_MOVETO) + r = SEG_LINETO; + return r; + } + + if (current < 9) + { + getPoint(current); + coords[0] = (float) temp[0]; + coords[1] = (float) temp[1]; + } + else if (current == 9) + return SEG_CLOSE; + else + throw new NoSuchElementException("rect iterator out of bounds"); + + if (at != null) + at.transform(coords, 0, coords, 0, 1); + return current == 0 ? SEG_MOVETO : SEG_LINETO; + } + + public int currentSegment(double[] coords) + { + if (corner != null) + { + int r = corner.currentSegment(coords); + if (r == SEG_MOVETO) + r = SEG_LINETO; + return r; + } + + if (current < 9) + { + getPoint(current); + coords[0] = temp[0]; + coords[1] = temp[1]; + } + else if (current == 9) + return SEG_CLOSE; + else + throw new NoSuchElementException("rect iterator out of bounds"); + + if (at != null) + at.transform(coords, 0, coords, 0, 1); + return current == 0 ? SEG_MOVETO : SEG_LINETO; + } + }; + } + + /** Return true if the given rectangle intersects this shape. + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + */ + public boolean intersects(double x, double y, double w, double h) + { + // Check if any corner is within the rectangle + return (contains(x, y) || contains(x, y + h) || contains(x + w, y + h) + || contains(x + w, y)); + } + + /** Set the boundary of this round rectangle. + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + */ + public void setFrame(double x, double y, double w, double h) + { + // This is a bit lame. + setRoundRect(x, y, w, h, getArcWidth(), getArcHeight()); + } + + /** Set the values of this round rectangle to be the same as those + * of the argument. + * @param rr The round rectangle to copy + */ + public void setRoundRect(RoundRectangle2D rr) + { + setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(), + rr.getArcWidth(), rr.getArcHeight()); + } + + /** A subclass of RoundRectangle which keeps its parameters as + * doubles. */ + public static class Double extends RoundRectangle2D + { + /** The height of the corner arc. */ + public double archeight; + + /** The width of the corner arc. */ + public double arcwidth; + + /** The x coordinate of this object. */ + public double x; + + /** The y coordinate of this object. */ + public double y; + + /** The width of this object. */ + public double width; + + /** The height of this object. */ + public double height; + + /** Construct a new instance, with all parameters set to 0. */ + public Double() + { + } + + /** Construct a new instance with the given arguments. + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + * @param arcWidth The arc width + * @param arcHeight The arc height + */ + public Double(double x, double y, double w, double h, double arcWidth, + double arcHeight) + { + this.x = x; + this.y = y; + this.width = w; + this.height = h; + this.arcwidth = arcWidth; + this.archeight = arcHeight; + } + + public double getArcHeight() + { + return archeight; + } + + public double getArcWidth() + { + return arcwidth; + } + + public Rectangle2D getBounds2D() + { + return new Rectangle2D.Double(x, y, width, height); + } + + public double getX() + { + return x; + } + + public double getY() + { + return y; + } + + public double getWidth() + { + return width; + } + + public double getHeight() + { + return height; + } + + public boolean isEmpty() + { + return width <= 0 || height <= 0; + } + + public void setRoundRect(double x, double y, double w, double h, + double arcWidth, double arcHeight) + { + this.x = x; + this.y = y; + this.width = w; + this.height = h; + this.arcwidth = arcWidth; + this.archeight = arcHeight; + } + } // class Double + + /** A subclass of RoundRectangle which keeps its parameters as + * floats. */ + public static class Float extends RoundRectangle2D + { + /** The height of the corner arc. */ + public float archeight; + + /** The width of the corner arc. */ + public float arcwidth; + + /** The x coordinate of this object. */ + public float x; + + /** The y coordinate of this object. */ + public float y; + + /** The width of this object. */ + public float width; + + /** The height of this object. */ + public float height; + + /** Construct a new instance, with all parameters set to 0. */ + public Float() + { + } + + /** Construct a new instance with the given arguments. + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + * @param arcWidth The arc width + * @param arcHeight The arc height + */ + public Float(float x, float y, float w, float h, float arcWidth, + float arcHeight) + { + this.x = x; + this.y = y; + this.width = w; + this.height = h; + this.arcwidth = arcWidth; + this.archeight = arcHeight; + } + + public double getArcHeight() + { + return archeight; + } + + public double getArcWidth() + { + return arcwidth; + } + + public Rectangle2D getBounds2D() + { + return new Rectangle2D.Float(x, y, width, height); + } + + public double getX() + { + return x; + } + + public double getY() + { + return y; + } + + public double getWidth() + { + return width; + } + + public double getHeight() + { + return height; + } + + public boolean isEmpty() + { + return width <= 0 || height <= 0; + } + + public void setRoundRect(float x, float y, float w, float h, + float arcWidth, float arcHeight) + { + this.x = x; + this.y = y; + this.width = w; + this.height = h; + this.arcwidth = arcWidth; + this.archeight = arcHeight; + } + + public void setRoundRect(double x, double y, double w, double h, + double arcWidth, double arcHeight) + { + this.x = (float) x; + this.y = (float) y; + this.width = (float) w; + this.height = (float) h; + this.arcwidth = (float) arcWidth; + this.archeight = (float) arcHeight; + } + } // class Float +} // class RoundRectangle2D diff --git a/libjava/classpath/java/awt/geom/doc-files/Area-1.png b/libjava/classpath/java/awt/geom/doc-files/Area-1.png Binary files differnew file mode 100644 index 0000000..44650f2 --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/Area-1.png diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png Binary files differnew file mode 100644 index 0000000..1784509 --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png Binary files differnew file mode 100644 index 0000000..1ddae9f --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png Binary files differnew file mode 100644 index 0000000..b200dad --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png Binary files differnew file mode 100644 index 0000000..e57ffdc --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png Binary files differnew file mode 100644 index 0000000..701ab13 --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png diff --git a/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png b/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png Binary files differnew file mode 100644 index 0000000..8317db6 --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png diff --git a/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html b/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html new file mode 100644 index 0000000..5a52d69 --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html @@ -0,0 +1,481 @@ +<?xml version="1.0" encoding="US-ASCII"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> + <title>The GNU Implementation of java.awt.geom.FlatteningPathIterator</title> + <meta name="author" content="Sascha Brawer" /> + <style type="text/css"><!-- + td { white-space: nowrap; } + li { margin: 2mm 0; } + --></style> +</head> +<body> + +<h1>The GNU Implementation of FlatteningPathIterator</h1> + +<p><i><a href="http://www.dandelis.ch/people/brawer/">Sascha +Brawer</a>, November 2003</i></p> + +<p>This document describes the GNU implementation of the class +<code>java.awt.geom.FlatteningPathIterator</code>. It does +<em>not</em> describe how a programmer should use this class; please +refer to the generated API documentation for this purpose. Instead, it +is intended for maintenance programmers who want to understand the +implementation, for example because they want to extend the class or +fix a bug.</p> + + +<h2>Data Structures</h2> + +<p>The algorithm uses a stack. Its allocation is delayed to the time +when the source path iterator actually returns the first curved +segment (either <code>SEG_QUADTO</code> or <code>SEG_CUBICTO</code>). +If the input path does not contain any curved segments, the value of +the <code>stack</code> variable stays <code>null</code>. In this quite +common case, the memory consumption is minimal.</p> + +<dl><dt><code>stack</code></dt><dd>The variable <code>stack</code> is +a <code>double</code> array that holds the start, control and end +points of individual sub-segments.</dd> + +<dt><code>recLevel</code></dt><dd>The variable <code>recLevel</code> +holds how many recursive sub-divisions were needed to calculate a +segment. The original curve has recursion level 0. For each +sub-division, the corresponding recursion level is increased by +one.</dd> + +<dt><code>stackSize</code></dt><dd>Finally, the variable +<code>stackSize</code> indicates how many sub-segments are stored on +the stack.</dd></dl> + +<h2>Algorithm</h2> + +<p>The implementation separately processes each segment that the +base iterator returns.</p> + +<p>In the case of <code>SEG_CLOSE</code>, +<code>SEG_MOVETO</code> and <code>SEG_LINETO</code> segments, the +implementation simply hands the segment to the consumer, without actually +doing anything.</p> + +<p>Any <code>SEG_QUADTO</code> and <code>SEG_CUBICTO</code> segments +need to be flattened. Flattening is performed with a fixed-sized +stack, holding the coordinates of subdivided segments. When the base +iterator returns a <code>SEG_QUADTO</code> and +<code>SEG_CUBICTO</code> segments, it is recursively flattened as +follows:</p> + +<ol><li>Intialization: Allocate memory for the stack (unless a +sufficiently large stack has been allocated previously). Push the +original quadratic or cubic curve onto the stack. Mark that segment as +having a <code>recLevel</code> of zero.</li> + +<li>If the stack is empty, flattening the segment is complete, +and the next segment is fetched from the base iterator.</li> + +<li>If the stack is not empty, pop a curve segment from the +stack. + + <ul><li>If its <code>recLevel</code> exceeds the recursion limit, + hand the current segment to the consumer.</li> + + <li>Calculate the squared flatness of the segment. If it smaller + than <code>flatnessSq</code>, hand the current segment to the + consumer.</li> + + <li>Otherwise, split the segment in two halves. Push the right + half onto the stack. Then, push the left half onto the stack. + Continue with step two.</li></ul></li> +</ol> + +<p>The implementation is slightly complicated by the fact that +consumers <em>pull</em> the flattened segments from the +<code>FlatteningPathIterator</code>. This means that we actually +cannot “hand the curent segment over to the consumer.” +But the algorithm is easier to understand if one assumes a +<em>push</em> paradigm.</p> + + +<h2>Example</h2> + +<p>The following example shows how a +<code>FlatteningPathIterator</code> processes a +<code>SEG_QUADTO</code> segment. It is (arbitrarily) assumed that the +recursion limit was set to 2.</p> + +<blockquote> +<table border="1" cellspacing="0" cellpadding="8"> + <tr align="center" valign="baseline"> + <th></th><th>A</th><th>B</th><th>C</th> + <th>D</th><th>E</th><th>F</th><th>G</th><th>H</th> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[0]</code></th> + <td>—</td> + <td>—</td> + <td><i>S<sub>ll</sub>.x</i></td> + <td>—</td> + <td>—</td> + <td>—</td> + <td>—</td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[1]</code></th> + <td>—</td> + <td>—</td> + <td><i>S<sub>ll</sub>.y</i></td> + <td>—</td> + <td>—</td> + <td>—</td> + <td>—</td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[2]</code></th> + <td>—</td> + <td>—</td> + <td><i>C<sub>ll</sub>.x</i></td> + <td>—</td> + <td>—</td> + <td>—</td> + <td>—</td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[3]</code></th> + <td>—</td> + <td>—</td> + <td><i>C<sub>ll</sub>.y</i></td> + <td>—</td> + <td>—</td> + <td>—</td> + <td>—</td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[4]</code></th> + <td>—</td> + <td><i>S<sub>l</sub>.x</i></td> + <td><i>E<sub>ll</sub>.x</i> + = <i>S<sub>lr</sub>.x</i></td> + <td><i>S<sub>lr</sub>.x</i></td> + <td>—</td> + <td><i>S<sub>rl</sub>.x</i></td> + <td>—</td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[5]</code></th> + <td>—</td> + <td><i>S<sub>l</sub>.y</i></td> + <td><i>E<sub>ll</sub>.x</i> + = <i>S<sub>lr</sub>.y</i></td> + <td><i>S<sub>lr</sub>.y</i></td> + <td>—</td> + <td><i>S<sub>rl</sub>.y</i></td> + <td>—</td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[6]</code></th> + <td>—</td> + <td><i>C<sub>l</sub>.x</i></td> + <td><i>C<sub>lr</sub>.x</i></td> + <td><i>C<sub>lr</sub>.x</i></td> + <td>—</td> + <td><i>C<sub>rl</sub>.x</i></td> + <td>—</td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[7]</code></th> + <td>—</td> + <td><i>C<sub>l</sub>.y</i></td> + <td><i>C<sub>lr</sub>.y</i></td> + <td><i>C<sub>lr</sub>.y</i></td> + <td>—</td> + <td><i>C<sub>rl</sub>.y</i></td> + <td>—</td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[8]</code></th> + <td><i>S.x</i></td> + <td><i>E<sub>l</sub>.x</i> + = <i>S<sub>r</sub>.x</i></td> + <td><i>E<sub>lr</sub>.x</i> + = <i>S<sub>r</sub>.x</i></td> + <td><i>E<sub>lr</sub>.x</i> + = <i>S<sub>r</sub>.x</i></td> + <td><i>S<sub>r</sub>.x</i></td> + <td><i>E<sub>rl</sub>.x</i> + = <i>S<sub>rr</sub>.x</i></td> + <td><i>S<sub>rr</sub>.x</i></td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[9]</code></th> + <td><i>S.y</i></td> + <td><i>E<sub>l</sub>.y</i> + = <i>S<sub>r</sub>.y</i></td> + <td><i>E<sub>lr</sub>.y</i> + = <i>S<sub>r</sub>.y</i></td> + <td><i>E<sub>lr</sub>.y</i> + = <i>S<sub>r</sub>.y</i></td> + <td><i>S<sub>r</sub>.y</i></td> + <td><i>E<sub>rl</sub>.y</i> + = <i>S<sub>rr</sub>.y</i></td> + <td><i>S<sub>rr</sub>.y</i></td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[10]</code></th> + <td><i>C.x</i></td> + <td><i>C<sub>r</sub>.x</i></td> + <td><i>C<sub>r</sub>.x</i></td> + <td><i>C<sub>r</sub>.x</i></td> + <td><i>C<sub>r</sub>.x</i></td> + <td><i>C<sub>rr</sub>.x</i></td> + <td><i>C<sub>rr</sub>.x</i></td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[11]</code></th> + <td><i>C.y</i></td> + <td><i>C<sub>r</sub>.y</i></td> + <td><i>C<sub>r</sub>.y</i></td> + <td><i>C<sub>r</sub>.y</i></td> + <td><i>C<sub>r</sub>.y</i></td> + <td><i>C<sub>rr</sub>.y</i></td> + <td><i>C<sub>rr</sub>.y</i></td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[12]</code></th> + <td><i>E.x</i></td> + <td><i>E<sub>r</sub>.x</i></td> + <td><i>E<sub>r</sub>.x</i></td> + <td><i>E<sub>r</sub>.x</i></td> + <td><i>E<sub>r</sub>.x</i></td> + <td><i>E<sub>rr</sub>.x</i></td> + <td><i>E<sub>rr</sub>.x</i></td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stack[13]</code></th> + <td><i>E.y</i></td> + <td><i>E<sub>r</sub>.y</i></td> + <td><i>E<sub>r</sub>.y</i></td> + <td><i>E<sub>r</sub>.y</i></td> + <td><i>E<sub>r</sub>.y</i></td> + <td><i>E<sub>rr</sub>.y</i></td> + <td><i>E<sub>rr</sub>.x</i></td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>stackSize</code></th> + <td>1</td> + <td>2</td> + <td>3</td> + <td>2</td> + <td>1</td> + <td>2</td> + <td>1</td> + <td>0</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>recLevel[2]</code></th> + <td>—</td> + <td>—</td> + <td>2</td> + <td>—</td> + <td>—</td> + <td>—</td> + <td>—</td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>recLevel[1]</code></th> + <td>—</td> + <td>1</td> + <td>2</td> + <td>2</td> + <td>—</td> + <td>2</td> + <td>—</td> + <td>—</td> + </tr> + <tr align="center" valign="baseline"> + <th><code>recLevel[0]</code></th> + <td>0</td> + <td>1</td> + <td>1</td> + <td>1</td> + <td>1</td> + <td>2</td> + <td>2</td> + <td>—</td> + </tr> + </table> +</blockquote> + +<ol> + +<li>The data structures are initialized as follows. + +<ul><li>The segment’s end point <i>E</i>, control point +<i>C</i>, and start point <i>S</i> are pushed onto the stack.</li> + + <li>Currently, the curve in the stack would be approximated by one + single straight line segment (<i>S</i> – <i>E</i>). + Therefore, <code>stackSize</code> is set to 1.</li> + + <li>This single straight line segment is approximating the original + curve, which can be seen as the result of zero recursive + splits. Therefore, <code>recLevel[0]</code> is set to + zero.</li></ul> + +Column A shows the state after the initialization step.</li> + +<li>The algorithm proceeds by taking the topmost curve segment +(<i>S</i> – <i>C</i> – <i>E</i>) from the stack. + + <ul><li>The recursion level of this segment (stored in + <code>recLevel[0]</code>) is zero, which is smaller than + the limit 2.</li> + + <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code> + is called to calculate the squared flatness.</li> + + <li>For the sake of argument, we assume that the squared flatness is + exceeding the threshold stored in <code>flatnessSq</code>. Thus, the + curve segment <i>S</i> – <i>C</i> – <i>E</i> gets + subdivided into a left and a right half, namely + <i>S<sub>l</sub></i> – <i>C<sub>l</sub></i> – + <i>E<sub>l</sub></i> and <i>S<sub>r</sub></i> – + <i>C<sub>r</sub></i> – <i>E<sub>r</sub></i>. Both halves are + pushed onto the stack, so the left half is now on top. + + <br /> <br />The left half starts at the same point + as the original curve, so <i>S<sub>l</sub></i> has the same + coordinates as <i>S</i>. Similarly, the end point of the right + half and of the original curve are identical + (<i>E<sub>r</sub></i> = <i>E</i>). More interestingly, the left + half ends where the right half starts. Because + <i>E<sub>l</sub></i> = <i>S<sub>r</sub></i>, their coordinates need + to be stored only once, which amounts to saving 16 bytes (two + <code>double</code> values) for each iteration.</li></ul> + +Column B shows the state after the first iteration.</li> + +<li>Again, the topmost curve segment (<i>S<sub>l</sub></i> +– <i>C<sub>l</sub></i> – <i>E<sub>l</sub></i>) is +taken from the stack. + + <ul><li>The recursion level of this segment (stored in + <code>recLevel[1]</code>) is 1, which is smaller than + the limit 2.</li> + + <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code> + is called to calculate the squared flatness.</li> + + <li>Assuming that the segment is still not considered + flat enough, it gets subdivided into a left + (<i>S<sub>ll</sub></i> – <i>C<sub>ll</sub></i> – + <i>E<sub>ll</sub></i>) and a right (<i>S<sub>lr</sub></i> + – <i>C<sub>lr</sub></i> – <i>E<sub>lr</sub></i>) + half.</li></ul> + +Column C shows the state after the second iteration.</li> + +<li>The topmost curve segment (<i>S<sub>ll</sub></i> – +<i>C<sub>ll</sub></i> – <i>E<sub>ll</sub></i>) is popped from +the stack. + + <ul><li>The recursion level of this segment (stored in + <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than + the limit 2. Therefore, a <code>SEG_LINETO</code> (from + <i>S<sub>ll</sub></i> to <i>E<sub>ll</sub></i>) is passed to the + consumer.</li></ul> + + The new state is shown in column D.</li> + + +<li>The topmost curve segment (<i>S<sub>lr</sub></i> – +<i>C<sub>lr</sub></i> – <i>E<sub>lr</sub></i>) is popped from +the stack. + + <ul><li>The recursion level of this segment (stored in + <code>recLevel[1]</code>) is 2, which is <em>not</em> smaller than + the limit 2. Therefore, a <code>SEG_LINETO</code> (from + <i>S<sub>lr</sub></i> to <i>E<sub>lr</sub></i>) is passed to the + consumer.</li></ul> + + The new state is shown in column E.</li> + +<li>The algorithm proceeds by taking the topmost curve segment +(<i>S<sub>r</sub></i> – <i>C<sub>r</sub></i> – +<i>E<sub>r</sub></i>) from the stack. + + <ul><li>The recursion level of this segment (stored in + <code>recLevel[0]</code>) is 1, which is smaller than + the limit 2.</li> + + <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code> + is called to calculate the squared flatness.</li> + + <li>For the sake of argument, we again assume that the squared + flatness is exceeding the threshold stored in + <code>flatnessSq</code>. Thus, the curve segment + (<i>S<sub>r</sub></i> – <i>C<sub>r</sub></i> – + <i>E<sub>r</sub></i>) is subdivided into a left and a right half, + namely + <i>S<sub>rl</sub></i> – <i>C<sub>rl</sub></i> – + <i>E<sub>rl</sub></i> and <i>S<sub>rr</sub></i> – + <i>C<sub>rr</sub></i> – <i>E<sub>rr</sub></i>. Both halves + are pushed onto the stack.</li></ul> + + The new state is shown in column F.</li> + +<li>The topmost curve segment (<i>S<sub>rl</sub></i> – +<i>C<sub>rl</sub></i> – <i>E<sub>rl</sub></i>) is popped from +the stack. + + <ul><li>The recursion level of this segment (stored in + <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than + the limit 2. Therefore, a <code>SEG_LINETO</code> (from + <i>S<sub>rl</sub></i> to <i>E<sub>rl</sub></i>) is passed to the + consumer.</li></ul> + + The new state is shown in column G.</li> + +<li>The topmost curve segment (<i>S<sub>rr</sub></i> – +<i>C<sub>rr</sub></i> – <i>E<sub>rr</sub></i>) is popped from +the stack. + + <ul><li>The recursion level of this segment (stored in + <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than + the limit 2. Therefore, a <code>SEG_LINETO</code> (from + <i>S<sub>rr</sub></i> to <i>E<sub>rr</sub></i>) is passed to the + consumer.</li></ul> + + The new state is shown in column H.</li> + +<li>The stack is now empty. The FlatteningPathIterator will fetch the +next segment from the base iterator, and process it.</li> + +</ol> + +<p>In order to split the most recently pushed segment, the +<code>subdivideQuadratic()</code> method passes <code>stack</code> +directly to +<code>QuadCurve2D.subdivide(double[],int,double[],int,double[],int)</code>. +Because the stack grows towards the beginning of the array, no data +needs to be copied around: <code>subdivide</code> will directly store +the result into the stack, which will have the contents shown to the +right.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png b/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png Binary files differnew file mode 100644 index 0000000..d1d75d5 --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png Binary files differnew file mode 100644 index 0000000..7c2ec0e --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png Binary files differnew file mode 100644 index 0000000..496180c --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png Binary files differnew file mode 100644 index 0000000..a7557ba --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png Binary files differnew file mode 100644 index 0000000..835c064 --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png Binary files differnew file mode 100644 index 0000000..72110cd --- /dev/null +++ b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png diff --git a/libjava/classpath/java/awt/geom/package.html b/libjava/classpath/java/awt/geom/package.html new file mode 100644 index 0000000..c8ee827 --- /dev/null +++ b/libjava/classpath/java/awt/geom/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.geom package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.geom</title></head> + +<body> +<p>Classes to represent 2D objects and different path transformations.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/im/InputContext.java b/libjava/classpath/java/awt/im/InputContext.java new file mode 100644 index 0000000..e289677 --- /dev/null +++ b/libjava/classpath/java/awt/im/InputContext.java @@ -0,0 +1,434 @@ +/* InputContext.java -- provides the context for text input + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.im; + +import gnu.java.util.EmptyEnumeration; + +import java.awt.AWTEvent; +import java.awt.AWTException; +import java.awt.Component; +import java.awt.im.spi.InputMethod; +import java.awt.im.spi.InputMethodDescriptor; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; + +/** + * Provides a context for controlling input methods and keyboard layouts. + * This class provides the communication layer between the client component, + * and the various locale-dependent text entry input methods that can be used + * for the client. By default, there is one instance per Window, shared among + * all components, but this limits text entry to one component at a time. + * Thus, text components can create their own instance to allow text entry + * in multiple components at a time. + * + * <p>By using the interfaces of {@link java.awt.im.spi}, you can install + * extensions which allow additional input methods. Some of these may use + * platform native input methods, or keyboard layouts provided by the platform. + * Input methods are unavailable if none have been installed and the platform + * has no underlying native input methods. Extensions are installed as jar + * files, usually accessed in the default extension location or specified by + * the -extdir VM flag. The jar must contain a file named + * "META_INF/services/java.awt.im.spi.InputMethodDescriptor" which lists, + * one entry per line in UTF-8 encoding, each class in the jar that implements + * java.awt.im.spi.InputMethodDescriptor. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see Component#getInputContext() + * @see Component#enableInputMethods(boolean) + * @since 1.2 + * @status updated to 1.4, but unverified + */ +public class InputContext +{ + /** + * The list of installed input method descriptors. + */ + private static final ArrayList descriptors = new ArrayList(); + static + { + Enumeration e; + try + { + e = ClassLoader.getSystemResources + ("META_INF/services/java.awt.im.spi.InputMethodDescriptor"); + } + catch (IOException ex) + { + // XXX Should we do something else? + e = EmptyEnumeration.getInstance(); + } + while (e.hasMoreElements()) + { + URL url = (URL) e.nextElement(); + BufferedReader in; + String line; + try + { + in = new BufferedReader + (new InputStreamReader(url.openConnection().getInputStream(), + "UTF-8")); + line = in.readLine().trim(); + } + catch (IOException ignored) + { + continue; + } + outer: + while (line != null) + { + try + { + if (line.charAt(0) != '#') + { + Class c = Class.forName(line); + descriptors.add((InputMethodDescriptor) c.newInstance()); + } + line = in.readLine().trim(); + } + catch (IOException ex) + { + continue outer; + } + catch (Exception ignored) + { + } + } + } + } + + /** The current input method; null if no input methods are installed. */ + private InputMethod im; + + /** Map of locales to the most recently selected input method. */ + private final HashMap recent = new HashMap(); + + /** The list of acceptable character subsets. */ + private Character.Subset[] subsets; + + /** + * Construct an InputContext. This is protected, so clients must use + * {@link #getInstance()} instead. + */ + protected InputContext() + { + } + + /** + * Returns a new InputContext. + * + * @return a new instance, initialized to the default locale if available + */ + public static InputContext getInstance() + { + InputContext ic = new InputContext(); + ic.selectInputMethod(Locale.getDefault()); + return ic; + } + + /** + * Attempts to select an input method or keyboard layout which supports the + * given locale. This returns true if a locale is available and was selected. + * The following steps are taken in choosing an input method:<ul> + * <li>If the currently selected input method or keyboard layout supports + * the requested locale, it remains selected.</li> + * <li>If there is no input method or keyboard layout available that + * supports the requested locale, the current input method or keyboard + * layout remains selected.</li> + * <li>If the user has previously selected an input method or keyboard + * layout for the requested locale from the user interface, then the most + * recently selected such input method or keyboard layout is reselected.</li> + * <li>Otherwise, an input method or keyboard layout that supports the + * requested locale is selected in an implementation dependent way. This + * implementation chooses the first input method which supports the requested + * locale based on the InputMethodDescriptors loaded from the extensions + * installed on the CLASSPATH.</li> + * </ul> + * + * <p>Before switching away from an input method, any currently uncommitted + * text is committed. Not all host operating systems provide API to + * determine the locale of the currently selected native input method or + * keyboard layout, and to select a native input method or keyboard layout + * by locale. For host operating systems that don't provide such API, + * selectInputMethod assumes that native input methods or keyboard layouts + * provided by the host operating system support only the system's default + * locale. + * + * <p>An example of where this may be called is in a multi-language document, + * when moving the insertion point between sections of different locale, so + * that the user may use the input method appropriate to that section of the + * document. + * + * @param locale the desired new locale + * @return true if the new locale is active + * @throws NullPointerException if locale is null + */ + public boolean selectInputMethod(Locale locale) + { + if (im != null && im.setLocale(locale)) + { + recent.put(locale, im); + return true; + } + InputMethod next = (InputMethod) recent.get(locale); + outer: + if (next != null) + for (int i = 0, limit = descriptors.size(); i < limit; i++) + { + InputMethodDescriptor d = (InputMethodDescriptor) descriptors.get(i); + Locale[] list; + try + { + list = d.getAvailableLocales(); + } + catch (AWTException ignored) + { + continue; + } + for (int j = list.length; --j >= 0; ) + if (locale.equals(list[j])) + { + try + { + next = d.createInputMethod(); + recent.put(locale, next); + } + catch (Exception ignored) + { + continue; + } + } + } + if (next == null) + return false; + // XXX I'm not sure if this does all the necessary steps in the switch. + if (im != null) + { + try + { + next.setCompositionEnabled(im.isCompositionEnabled()); + } + catch (UnsupportedOperationException ignored) + { + } + im.endComposition(); + im.deactivate(false); + im.hideWindows(); + } + im = next; + im.setLocale(locale); + im.setCharacterSubsets(subsets); + return true; + } + + /** + * Returns the current locale of the current input method or keyboard + * layout. Returns null if the input context does not have a current input + * method or keyboard layout or if the current input method's + * {@link InputMethod#getLocale()} method returns null. Not all host + * operating systems provide API to determine the locale of the currently + * selected native input method or keyboard layout. For host operating + * systems that don't provide such API, getLocale assumes that the current + * locale of all native input methods or keyboard layouts provided by the + * host operating system is the system's default locale. + * + * @return the locale of the current input method, or null + * @since 1.3 + */ + public Locale getLocale() + { + return im == null ? null : im.getLocale(); + } + + /** + * Sets the subsets of Unicode characters allowed to be input by the current + * input method, as well as subsequent input methods. The value of null + * implies all characters are legal. Applications should not rely on this + * behavior, since native host input methods may not allow restrictions. + * If no current input method is available, this has no immediate effect. + * + * @param subsets the set of Unicode subsets to accept, or null + */ + public void setCharacterSubsets(Character.Subset[] subsets) + { + this.subsets = subsets; + if (im != null) + im.setCharacterSubsets(subsets); + } + + /** + * Changes the enabled status of the current input method. An input method + * that is enabled for composition interprets incoming events for both + * composition and control purposes, while a disabled input method only + * interprets control commands (including commands to enable itself). + * + * @param enable whether to enable the input method + * @throws UnsupportedOperationException if there is no current input method, + * or the input method does not support enabling + * @see #isCompositionEnabled() + * @since 1.3 + */ + public void setCompositionEnabled(boolean enable) + { + if (im == null) + throw new UnsupportedOperationException(); + im.setCompositionEnabled(enable); + } + + /** + * Find out if the current input method is enabled. + * + * @return true if the current input method is enabled + * @throws UnsupportedOperationException if there is no current input method, + * or the input method does not support enabling + * @see #setCompositionEnabled(boolean) + * @since 1.3 + */ + public boolean isCompositionEnabled() + { + if (im == null) + throw new UnsupportedOperationException(); + return im.isCompositionEnabled(); + } + + /** + * Starts a reconversion operation in the current input method. The input + * method gets theh text to reconvert from the client component, using + * {@link InputMethodRequests#getSelectedText(Attribute[])}. Then the + * composed and committed text produced by the operation is sent back to + * the client using a sequence of InputMethodRequests. + * + * @throws UnsupportedOperationException if there is no current input method, + * or the input method does not support reconversion + * @since 1.3 + */ + public void reconvert() + { + if (im == null) + throw new UnsupportedOperationException(); + im.reconvert(); + } + + /** + * Dispatches an event to the current input method. This is called + * automatically by AWT. If no input method is available, then the event + * will never be consumed. + * + * @param event the event to dispatch + * @throws NullPointerException if event is null + */ + public void dispatchEvent(AWTEvent event) + { + if (im != null) + im.dispatchEvent(event); + } + + /** + * Notifies the input context that a client component has been removed from + * its containment hierarchy, or that input method support has been disabled + * for the component. This method is usually called from the client + * component's {@link Component#removeNotify()} method. Potentially pending + * input from input methods for this component is discarded. If no input + * methods are available, then this method has no effect. + * + * @param client the client component + * @throws NullPointerException if client is null + */ + public void removeNotify(Component client) + { + // XXX What to do with client information? + if (im != null) + { + im.deactivate(false); + im.removeNotify(); + } + } + + /** + * Ends any input composition that may currently be going on in this + * context. Depending on the platform and possibly user preferences, this + * may commit or delete uncommitted text. Any changes to the text are + * communicated to the active component using an input method event. If no + * input methods are available, then this method has no effect. This may + * be called for a variety of reasons, such as when the user moves the + * insertion point in the client text outside the range of the composed text, + * or when text is saved to file. + */ + public void endComposition() + { + if (im != null) + im.endComposition(); + } + + /** + * Disposes of the input context and release the resources used by it. + * Called automatically by AWT for the default input context of each + * Window. If no input methods are available, then this method has no + * effect. + */ + public void dispose() + { + if (im != null) + { + im.deactivate(false); + im.dispose(); + } + } + + /** + * Returns a control object from the current input method, or null. A + * control object provides implementation-dependent methods that control + * the behavior of the input method or obtain information from the input + * method. Clients have to compare the result against known input method + * control object types. If no input methods are available or the current + * input method does not provide an input method control object, then null + * is returned. + * + * @return the control object, or null + */ + public Object getInputMethodControlObject() + { + return im == null ? null : im.getControlObject(); + } +} // class InputContext diff --git a/libjava/classpath/java/awt/im/InputMethodHighlight.java b/libjava/classpath/java/awt/im/InputMethodHighlight.java new file mode 100644 index 0000000..0d664b1 --- /dev/null +++ b/libjava/classpath/java/awt/im/InputMethodHighlight.java @@ -0,0 +1,185 @@ +/* InputMethodHighlight.java -- highlights the current text selection + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.im; + +import java.util.Map; + +/** + * This describes the highlight attributes of text composed in an input method. + * The description includes an abstract level (whether text has been converted + * yet, and whether it is selected), and a concrete level (which style + * attributes are used in rendering). If no concrete level is defined, the + * renderer should use + * {@link Toolkit#mapInputMethodHighlight(InputMethodHighlight)}. An example + * of conversion state is kana -> kanji. + * + * <p>Instances of this class are typically used in + * AttributedCharacterIterators, and may be wrapped in Annotations to separate + * text segments. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see AttributedCharacterIterators + * @see Annotation + * @since 1.2 + * @status updated to 1.4 + */ +public class InputMethodHighlight +{ + /** Raw text state (before conversion). */ + public static final int RAW_TEXT = 0; + + /** Converted text state (after conversion). */ + public static final int CONVERTED_TEXT = 1; + + /** Default do-nothing highlighting for unselected raw text. */ + public static final InputMethodHighlight UNSELECTED_RAW_TEXT_HIGHLIGHT + = new InputMethodHighlight(false, RAW_TEXT); + + /** Default do-nothing highlighting for selected raw text. */ + public static final InputMethodHighlight SELECTED_RAW_TEXT_HIGHLIGHT + = new InputMethodHighlight(true, RAW_TEXT); + + /** Default do-nothing highlighting for unselected converted text. */ + public static final InputMethodHighlight UNSELECTED_CONVERTED_TEXT_HIGHLIGHT + = new InputMethodHighlight(false, CONVERTED_TEXT); + + /** Default do-nothing highlighting for selected converted text. */ + public static final InputMethodHighlight SELECTED_CONVERTED_TEXT_HIGHLIGHT + = new InputMethodHighlight(true, CONVERTED_TEXT); + + /** Whether the highlighting applies to selected text. */ + private final boolean selected; + + /** The state of highlighted text. */ + private final int state; + + /** Any variation on the highlighting style. */ + private final int variation; + + /** The unmodifiable map of rendering styles. */ + private final Map style; + + /** + * Create an input method highlight style, with variation 0 and null style + * mapping. + * + * @param selected whether the text range is selected + * @param state either {@link #RAW_TEXT} or {@link #CONVERTED_TEXT} + * @throws IllegalArgumentException if state is invalid + */ + public InputMethodHighlight(boolean selected, int state) + { + this(selected, state, 0, null); + } + + /** + * Create an input method highlight style, with null style mapping. + * + * @param selected whether the text range is selected + * @param state either {@link #RAW_TEXT} or {@link #CONVERTED_TEXT} + * @param variation the style variation + * @throws IllegalArgumentException if state is invalid + */ + public InputMethodHighlight(boolean selected, int state, int variation) + { + this(selected, state, variation, null); + } + + /** + * Create an input method highlight style. + * + * @param selected whether the text range is selected + * @param state either {@link #RAW_TEXT} or {@link #CONVERTED_TEXT} + * @param variation the style variation + * @param style an unmodifiable map of rendering styles, or null + * @throws IllegalArgumentException if state is invalid + * @since 1.3 + */ + public InputMethodHighlight(boolean selected, int state, int variation, + Map style) + { + if (state != RAW_TEXT && state != CONVERTED_TEXT) + throw new IllegalArgumentException(); + this.selected = selected; + this.state = state; + this.variation = variation; + this.style = style; + } + + /** + * Return whether the highlighting applies to selected text. + * + * @return the selection status + */ + public boolean isSelected() + { + return selected; + } + + /** + * Return the conversion state of the highlighted text. + * + * @return one of {@link #RAW_TEXT} or {@link #CONVERTED_TEXT} + */ + public int getState() + { + return state; + } + + /** + * Return the highlighting style variation. + * + * @return the variation + */ + public int getVariation() + { + return variation; + } + + /** + * Return the rendering style attributes map, or null if it should be the + * default mapping. + * + * @return the style map + * @since 1.3 + */ + public Map getStyle() + { + return style; + } +} // class InputMethodHighlight diff --git a/libjava/classpath/java/awt/im/InputMethodRequests.java b/libjava/classpath/java/awt/im/InputMethodRequests.java new file mode 100644 index 0000000..d50ec33 --- /dev/null +++ b/libjava/classpath/java/awt/im/InputMethodRequests.java @@ -0,0 +1,153 @@ +/* InputMethodRequests.java -- handles text insertion via input methods + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.im; + +import java.awt.Rectangle; +import java.awt.font.TextHitInfo; +import java.text.AttributedCharacterIterator; +import java.text.AttributedCharacterIterator.Attribute; + +/** + * This interface handles requests made by input methods on text editing + * components. A component must specify a handler for input methods that + * implements this interface, and which supports one of two user interfaces: + * <ul><li><em>on-the-spot</em>: composed text is shown in place</li> + * <li><em>below-the-spot</em>: composed text is in a separate window, + * usually below the main text window, until it is committed into place at + * the insertion point, overwriting any selected text</li></ul> + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see Component#getInputMethodRequests() + * @see InputMethodListener + * @since 1.2 + * @status updated to 1.4 + */ +public interface InputMethodRequests +{ + /** + * Gets the location of a given offset of the text. This can be used to + * position a composition window near the location of where the composed + * text will be inserted. + * + * <p>If the component has composed text (from the most recent + * InputMethodEvent), then offset 0 indicates the location of the first + * character of this composed text. Otherwise, the offset is ignored, and + * the location should be the beginning of the final line of selected + * text (in horizontal left-to-right text, like English, this would be the + * lower left corner of the selction; in vertical top-to-bottom text, like + * Chinese, this would be the top right corner of the selection). + * + * <p>The location returned is a 0-thickness caret (either horizontal or + * vertical, depending on text flow), mapped to absolute screen coordinates. + * + * @param offset offset within composed text, or null + * @return the screen location of the caret at the offset + */ + Rectangle getTextLocation(TextHitInfo offset); + + /** + * Get the text offset for the given screen coordinate. The offset is + * relative to the composed text, and the return is null if it is outside + * the range of composed text. For example, this can be used to find + * where a mouse click should pop up a text composition window. + * + * @param x the x screen coordinate + * @param y the y screen coordinate + * @return a text hit info describing the composed text offset + */ + TextHitInfo getLocationOffset(int x, int y); + + /** + * Gets the offset where the committed text exists in the text editing + * component. This can be used to examine the text surrounding the insert + * position. + * + * @return the offset of the insert position + */ + int getInsertPositionOffset(); + + /** + * Gets an interator which provides access to the text and its attributes, + * except for the uncommitted text. The input method may provide a list of + * attributes it is interested in; and the iterator need not provide + * information on the remaining attributes. If the attribute list is null, + * the iterator must list all attributes. + * + * @param beginIndex the index of the first character in the iteration + * @param endIndex the index of the last character in the iteration + * @param attributes a list of attributes interested in, or null + * @return an iterator over the region of text with its attributes + */ + AttributedCharacterIterator getCommittedText(int beginIndex, int endIndex, + Attribute[] attributes); + + /** + * Gets the length of committed text. + * + * @return the number of committed characters + */ + int getCommittedTextLength(); + + /** + * Gets the latest committed text, and removes it from the component's text + * body. This allows an input method to provide an "Undo" command. In + * general, this should only be supported immediately after a commit, and + * not when other actions intervene; if not supported, simply return null. + * The input method may provide a list of attributes it is interested in; + * and the iterator need not provide information on the remaining attributes. + * If the attribute list is null, the iterator must list all attributes. + * + * @param attributes a list of attributes interested in, or null + * @return the latest committed text, or null + */ + AttributedCharacterIterator cancelLatestCommittedText + (Attribute[] attributes); + + /** + * Gets the currently selected text. One use of this is to implement a + * "Reconvert" feature in an input method, which modifies the selection + * based on the text in the composition window. The input method may + * provide a list of attributes it is interested in; and the iterator need + * not provide information on the remaining attributes. If the attribute + * list is null, the iterator must list all attributes. + * + * @param attributes a list of attributes interested in, or null + * @return the current selection + */ + AttributedCharacterIterator getSelectedText(Attribute[] attributes); +} // interface InputMethodRequests diff --git a/libjava/classpath/java/awt/im/InputSubset.java b/libjava/classpath/java/awt/im/InputSubset.java new file mode 100644 index 0000000..5e7d58e --- /dev/null +++ b/libjava/classpath/java/awt/im/InputSubset.java @@ -0,0 +1,129 @@ +/* InputSubset.java -- subsets of Unicode important in text input + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.im; + +/** + * Defines additional Unicode character blocks for use by input methods. + * These constants encompass several Unicode blocks, or portions thereof, for + * simplification over {@link Character.UnicodeBlock}. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ +public final class InputSubset extends Character.Subset +{ + /** + * Constant for all Latin characters, including the characters in the + * BASIC_LATIN, LATIN_1_SUPPLEMENT, LATIN_EXTENDED_A, LATIN_EXTENDED_B + * Unicode character blocks. + */ + public static final InputSubset LATIN = new InputSubset("LATIN"); + + /** + * Constant for the digits included in the BASIC_LATIN Unicode character + * block. + */ + public static final InputSubset LATIN_DIGITS + = new InputSubset("LATIN_DIGITS"); + + /** + * Constant for all Han characters used in writing Traditional Chinese, + * including a subset of the CJK unified ideographs as well as Traditional + * Chinese Han characters that may be defined as surrogate characters. + */ + public static final InputSubset TRADITIONAL_HANZI + = new InputSubset("TRADITIONAL_HANZI"); + + /** + * Constant for all Han characters used in writing Simplified Chinese, + * including a subset of the CJK unified ideographs as well as Simplified + * Chinese Han characters that may be defined as surrogate characters. + */ + public static final InputSubset SIMPLIFIED_HANZI + = new InputSubset("SIMPLIFIED_HANZI"); + + /** + * Constant for all Han characters used in writing Japanese, including a + * subset of the CJK unified ideographs as well as Japanese Han characters + * that may be defined as surrogate characters. + */ + public static final InputSubset KANJI = new InputSubset("KANJI"); + + /** + * Constant for all Han characters used in writing Korean, including a + * subset of the CJK unified ideographs as well as Korean Han characters + * that may be defined as surrogate characters. + */ + public static final InputSubset HANJA = new InputSubset("HANJA"); + + /** + * Constant for the halfwidth katakana subset of the Unicode halfwidth and + * fullwidth forms character block. + */ + public static final InputSubset HALFWIDTH_KATAKANA + = new InputSubset("HALFWIDTH_KATAKANA"); + + /** + * Constant for the fullwidth ASCII variants subset of the Unicode + * halfwidth and fullwidth forms character block. + * + * @since 1.3 + */ + public static final InputSubset FULLWIDTH_LATIN + = new InputSubset("FULLWIDTH_LATIN"); + + /** + * Constant for the fullwidth digits included in the Unicode halfwidth and + * fullwidth forms character block. + * + * @since 1.3 + */ + public static final InputSubset FULLWIDTH_DIGITS + = new InputSubset("FULLWIDTH_DIGITS"); + + /** + * Construct a subset. + * + * @param name the subset name + */ + private InputSubset(String name) + { + super(name); + } +} // class InputSubset diff --git a/libjava/classpath/java/awt/im/package.html b/libjava/classpath/java/awt/im/package.html new file mode 100644 index 0000000..895da66 --- /dev/null +++ b/libjava/classpath/java/awt/im/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.im package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.im</title></head> + +<body> +<p>Support for text input methods.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/im/spi/InputMethod.java b/libjava/classpath/java/awt/im/spi/InputMethod.java new file mode 100644 index 0000000..840d193 --- /dev/null +++ b/libjava/classpath/java/awt/im/spi/InputMethod.java @@ -0,0 +1,240 @@ +/* InputMethod.java -- defines an interface for complex text input + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.im.spi; + +import java.awt.AWTEvent; +import java.awt.Rectangle; +import java.util.Locale; + +/** + * This interface supports complex text input, often for situations where + * the text is more complex than a keyboard will accomodate. For example, + * this can be used for Chinese, Japanese, and Korean, where multiple + * keystrokes are necessary to compose text. This could also support things + * like phonetic English, or reordering Thai. + * + * <p>These contexts can be loaded by the input method framework, using + * {@link InputContext#selectInputMethod(Locale)}. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + * @status updated to 1.4 + */ +public interface InputMethod +{ + /** + * Set the input method context, which ties the input method to a client + * component. This is called once automatically when creating the input + * method. + * + * @param context the context for this input method + * @throws NullPointerException if context is null + */ + void setInputMethodContext(InputMethodContext context); + + /** + * Sets the input locale. If the input method supports that locale, it + * changes its behavior to be consistent with the locale and returns true. + * Otherwise, it returns false. This is called by + * {@link InputContext#selectInputMethod(Locale)} when the user specifies + * a locale, or when the previously selected input method had a locale. + * + * @param locale the locale to use for input + * @return true if the change is successful + * @throws NullPointerException if locale is null + */ + boolean setLocale(Locale locale); + + /** + * Returns the current input locale, or null if none is defined. This is + * called by {@link InputContext#getLocale()}, or before switching input + * methods. + * + * @return the current input locale, or null + */ + Locale getLocale(); + + /** + * Sets the allowed Unicode subsets that this input method can use. Null + * indicates that all characters are allowed. This is called after creation, + * or when switching to this input method, by + * {@link InputContext#setCharacterSubsets(Character.Subset[])}. + * + * @param subsets the accepted subsets for this input method, or null for all + */ + void setCharacterSubsets(Character.Subset[] subsets); + + /** + * Changes the enabled status of this input method. An enabled input method + * accepts incoming events for composition and control purposes, while a + * disabled input method ignores events (except for control purposes). This + * is called by {@link InputContext#setCompositionEnabled(boolean)} or when + * switching from an input method if the previous input method returned + * without exception on {@link #isCompositionEnabled()}. + * + * @param enable whether to enable this input method + * @throws UnsupportedOperationException if enabling/disabling is unsupported + * @see #isCompositionEnabled() + */ + void setCompositionEnabled(boolean enable); + + /** + * Find out if this input method is enabled. This is called by + * {@link InputContext#isCompositionEnabled()}, or when switching input + * methods via {@link InputContext#selectInputMethod(Locale)}. + * + * @return true if this input method is enabled + * @throws UnsupportedOperationException if enabling/disabling is unsupported + * @see #setCompositionEnabled(boolean) + */ + boolean isCompositionEnabled(); + + /** + * Starts a reconversion operation. The input method gets its text from the + * client, using {@link InputMethodRequests#getSelectedText(Attribute[])}. + * Then the composed and committed text produced by the operation is sent + * back to the client using a sequence of InputMethodEvents. This is called + * by {@link InputContext#reconvert()}. + * + * @throws UnsupportedOperationException if reconversion is unsupported + */ + void reconvert(); + + /** + * Dispatch an event to the input method. If input method support is enabled, + * certain events are dispatched to the input method before the client + * component or event listeners. The input method must either consume the + * event or pass it on to the component. Instances of InputEvent, including + * KeyEvent and MouseEvent, are given to this input method. This method is + * called by {@link InputContext#dispatchEvent(AWTEvent)}. + * + * @param event the event to dispatch + * @throws NullPointerException if event is null + */ + void dispatchEvent(AWTEvent event); + + /** + * Notify this input method of changes in the client window. This is called + * when notifications are enabled (see {@link + * InputMethodContext#enableClientWindowNotification(InputMethod, boolean)}, + * if {@link #removeNotify(Component)} has not been called. The following + * situations trigger a notification:<ul> + * <li>The client window changes in location, size, visibility, + * iconification, or is closed.</li> + * <li>When enabling client notification (or on the first activation after + * enabling if no client existed at the time).</li> + * <li>When activating a new client after <code>removeNotify</code> was + * called on a previous client.</li> + * </ul> + * + * @param bounds the client window's current bounds, or null + */ + void notifyClientWindowChange(Rectangle bounds); + + /** + * Activate this input method for input processing. If the input method + * provides its own windows, it should make them open and visible at this + * time. This method is called when a client component receives a + * FOCUS_GAINED event, or when switching to this input method from another + * one. It is only called when the input method is inactive, assuming that + * new instances begin in an inactive state. + */ + void activate(); + + /** + * Deactivate this input method, either temporarily or permanently for the + * given client. If the input method provides its own windows, it should + * only close those related to the current composition (such as a lookup + * choice panel), while leaving more persistant windows (like a control + * panel) open to avoid screen flicker. Before control is given to another + * input method, {@link #hideWindows()} will be called on this instance. + * This method is called when a client component receives a + * FOCUS_LOST event, when switching to another input method, or before + * {@link #removeNotify()} when the client is removed. + * + * @param isTemporary true if the focus change is temporary + */ + void deactivate(boolean isTemporary); + + /** + * Close or hide all windows opened by this input method. This is called + * before activating a different input method, and before calling + * {@link #dispose()} on this instance. It is only called when the input + * method is inactive. + */ + void hideWindows(); + + /** + * Notify the input method that a client component has been removed from its + * hierarchy, or that input method support has been disabled. This is + * called by {@link InputContext#removeNotify()}, and only when the input + * method is inactive. + */ + void removeNotify(); + + /** + * End any input composition currently taking place. Depending on the + * platform and user preferences, this may commit or delete uncommitted text, + * using input method events. This may be called for a variety of reasons, + * such as when the user moves the insertion point in the client text outside + * the range of the composed text, or when text is saved to file. This is + * called by {@link InputContext#endComposition()}, when switching to a + * new input method, or by {@link InputContext#selectInputMethod(Locale)}. + */ + void endComposition(); + + /** + * Disposes the input method and release any resources it is using. In + * particular, the input method should dispose windows and close files. This + * is called by {@link InputContext#dispose()}, when the input method is + * inactive; and nothing will be called on this instance afterwards. + */ + void dispose(); + + /** + * Returns a control object from this input method, or null. A control object + * provides method to control the behavior of this input method, as well as + * query information about it. The object is implementation dependent, so + * clients must compare the result against known input method control + * object types. This is called by + * {@link InputContext#getInputMethodControlObject()}. + * + * @return the control object, or null + */ + Object getControlObject(); +} // interface InputMethod diff --git a/libjava/classpath/java/awt/im/spi/InputMethodContext.java b/libjava/classpath/java/awt/im/spi/InputMethodContext.java new file mode 100644 index 0000000..43bee8d --- /dev/null +++ b/libjava/classpath/java/awt/im/spi/InputMethodContext.java @@ -0,0 +1,123 @@ +/* InputMethodContext.java -- communication between an input method and client + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.im.spi; + +import java.awt.Window; +import java.awt.font.TextHitInfo; +import java.awt.im.InputMethodRequests; +import java.text.AttributedCharacterIterator; + +import javax.swing.JFrame; + +/** + * Provides methods for the communication context between an input method + * and the client component. This should be passed to + * {@link InputMethod#setInputMethodContext(InputMethodContext)}. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + * @status updated to 1.4 + */ +public interface InputMethodContext extends InputMethodRequests +{ + /** + * Create an input method event and dispatch it to the client. + * + * @param id the event type + * @param text an iterator over the text to be committed + * @param count the count of characters to be committed + * @param caret the insertion point of the commit, or null + * @param visiblePosition the best location to make visible, or null + */ + void dispatchInputMethodEvent(int id, AttributedCharacterIterator text, + int count, TextHitInfo caret, + TextHitInfo visiblePosition); + + /** + * Creates a top-level window for use by the input method. This window should + * float above all document windows and dialogs, not receive focus, and have + * lightweight decorations (such as no title, reduced drag regions). But + * this behavior may be modified to meet the platform style. The title may + * or may not be displayed, depending on the platform. + * + * <p>If attachToInputContext is true, the new window will share the input + * context of the input method, so that events in the new window are + * dispatched to the input method. Also, this supresses deactivate and + * activate calls to the input method caused by setVisible. + * + * @param title the window title, if one is displayed; null becomes "" + * @param attachToInputContext true for the window to share context with + * the input method + * @return the new window for use by the input method + * @throws HeadlessException if GraphicsEnvironment.isHeadless is true + */ + Window createInputMethodWindow(String title, boolean attachToInputContext); + + /** + * Creates a top-level Swing JFrame for use by the input method. This frame + * should float above all document windows and dialogs, not receive focus, + * and have lightweight decorations (such as no title, reduced drag + * regions). But this behavior may be modified to meet the platform style. + * The title may or may not be displayed, depending on the platform. + * + * <p>If attachToInputContext is true, the new window will share the input + * context of the input method, so that events in the new window are + * dispatched to the input method. Also, this supresses deactivate and + * activate calls to the input method caused by setVisible. + * + * @param title the window title, if one is displayed; null becomes "" + * @param attachToInputContext true for the window to share context with + * the input method + * @return the new window for use by the input method + * @throws HeadlessException if GraphicsEnvironment.isHeadless is true + * @since 1.4 + */ + JFrame createInputMethodJFrame(String title, boolean attachToInputContext); + + /** + * Sets whether notification of the client window's location and state should + * be enabled for the input method. When enabled, the input method's + * {@link #notifyClientWindowChange(Rectangle)} method is called. + * Notification is automatically disabled when the input method is disposed. + * + * @param inputMethod the method to change status of + * @param enable true to enable notification + */ + void enableClientWindowNotification(InputMethod inputMethod, boolean enable); +} // interface InputMethodContext diff --git a/libjava/classpath/java/awt/im/spi/InputMethodDescriptor.java b/libjava/classpath/java/awt/im/spi/InputMethodDescriptor.java new file mode 100644 index 0000000..093d731 --- /dev/null +++ b/libjava/classpath/java/awt/im/spi/InputMethodDescriptor.java @@ -0,0 +1,113 @@ +/* InputMethodDescriptor.java -- enables loading and use of an input method + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.im.spi; + +import java.awt.AWTException; +import java.awt.Image; +import java.util.Locale; + +/** + * This interface provides information about an InputMethod before it is + * loaded. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + * @status updated to 1.4 + */ +public interface InputMethodDescriptor +{ + /** + * Returns the locales supported by the input method this describes. This + * allows the selection of input methods by locale (by language only, or + * also by country and variant), via + * {@link InputContext#selectInputMethod(Locale)}. The returned list should + * ignore pass-through locales, so it is usually a subset of locales for + * which {@link InputMethod#setContext(Locale)} returns true. If + * {@link #hasDynamicLocaleList()} returns true, this is called each time + * information is needed, allowing dynamic addition or removal of supported + * locales. + * + * @return the list of supported locales + * @throws AWTException if the input method is not available + */ + Locale[] getAvailableLocales() throws AWTException; + + /** + * Test whether the input method this describes has a static or dynamic + * locale list. For example, this would return true if the list of supported + * locales depends on adapters currently loaded over a network. + * + * @return true if the locale list is dynamic + */ + boolean hasDynamicLocaleList(); + + /** + * Returns a user visible name of the input locale, displayed in the + * specified locale. The inputLocale parameter must be one obtained from + * the list in {@link #getAvailableLocales()}, or null for a + * locale-independent description of the input method. If a translation to + * the desired display language is not available, another language may be + * used. + * + * @param inputLocale the locale of the input method, or null + * @param displayLanguage the language of the result + * @return the name of the input method when using the given inputLocale + */ + String getInputMethodDisplayName(Locale inputLocale, + Locale displayLanguage); + + /** + * Returns a 16x16 icon for the input locale. The inputLocale parameter + * must be one obtained from the list in {@link #getAvailableLocales()}, or + * null for a locale-independent icon for the input method. + * + * @param inputLocale the locale of the input method, or null + * @return a 16x16 icon for the input method when using the given inputLocale + */ + Image getInputMethodIcon(Locale inputLocale); + + /** + * Creates a new instance of the input method. + * + * @return the newly created input method + * @throws Exception if anything goes wrong + */ + InputMethod createInputMethod() throws Exception; + +} // interface InputMethodDescriptor + diff --git a/libjava/classpath/java/awt/im/spi/package.html b/libjava/classpath/java/awt/im/spi/package.html new file mode 100644 index 0000000..c526ee1 --- /dev/null +++ b/libjava/classpath/java/awt/im/spi/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.im.spi package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.im.spi</title></head> + +<body> +<p>Interfaces for implementation of text input methods.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/image/AffineTransformOp.java b/libjava/classpath/java/awt/image/AffineTransformOp.java new file mode 100644 index 0000000..f11066e --- /dev/null +++ b/libjava/classpath/java/awt/image/AffineTransformOp.java @@ -0,0 +1,375 @@ +/* AffineTransformOp.java -- This class performs affine + transformation between two images or rasters in 2 dimensions. + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Arrays; + +/** + * This class performs affine transformation between two images or + * rasters in 2 dimensions. + * + * @author Olga Rodimina (rodimina@redhat.com) + */ +public class AffineTransformOp implements BufferedImageOp, RasterOp +{ + public static final int TYPE_NEAREST_NEIGHBOR = 1; + + public static final int TYPE_BILINEAR = 2; + + /** + * @since 1.5.0 + */ + public static final int TYPE_BICUBIC = 3; + + private AffineTransform transform; + private RenderingHints hints; + + /** + * Construct AffineTransformOp with the given xform and interpolationType. + * Interpolation type can be TYPE_BILINEAR, TYPE_BICUBIC or + * TYPE_NEAREST_NEIGHBOR. + * + * @param xform AffineTransform that will applied to the source image + * @param interpolationType type of interpolation used + */ + public AffineTransformOp (AffineTransform xform, int interpolationType) + { + this.transform = xform; + if (xform.getDeterminant() == 0) + throw new ImagingOpException(null); + + switch (interpolationType) + { + case TYPE_BILINEAR: + hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); + break; + case TYPE_BICUBIC: + hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BICUBIC); + break; + default: + hints = new RenderingHints (RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + } + } + + /** + * Construct AffineTransformOp with the given xform and rendering hints. + * + * @param xform AffineTransform that will applied to the source image + * @param hints rendering hints that will be used during transformation + */ + public AffineTransformOp (AffineTransform xform, RenderingHints hints) + { + this.transform = xform; + this.hints = hints; + if (xform.getDeterminant() == 0) + throw new ImagingOpException(null); + } + + /** + * Creates empty BufferedImage with the size equal to that of the + * transformed image and correct number of bands. The newly created + * image is created with the specified ColorModel. + * If the ColorModel is equal to null, then image is created + * with the ColorModel of the source image. + * + * @param src source image + * @param destCM color model for the destination image + * @return new compatible destination image + */ + public BufferedImage createCompatibleDestImage (BufferedImage src, + ColorModel destCM) + { + + // if destCm is not specified, use color model of the source image + + if (destCM == null) + destCM = src.getColorModel (); + + return new BufferedImage (destCM, + createCompatibleDestRaster (src.getRaster ()), + src.isAlphaPremultiplied (), + null); + + } + + /** + * Creates empty WritableRaster with the size equal to the transformed + * source raster and correct number of bands + * + * @param src source raster + * @throws RasterFormatException if resulting width or height of raster is 0 + * @return new compatible raster + */ + public WritableRaster createCompatibleDestRaster (Raster src) + { + Rectangle rect = (Rectangle) getBounds2D (src); + + // throw RasterFormatException if resulting width or height of the + // transformed raster is 0 + + if (rect.getWidth () == 0 || rect.getHeight () == 0) + throw new RasterFormatException("width or height is 0"); + + return src.createCompatibleWritableRaster ((int) rect.getWidth (), + (int) rect.getHeight ()); + } + + /** + * Transforms source image using transform specified at the constructor. + * The resulting transformed image is stored in the destination image. + * + * @param src source image + * @param dst destination image + * @return transformed source image + */ + public final BufferedImage filter (BufferedImage src, BufferedImage dst) + { + + if (dst == src) + throw new IllegalArgumentException ("src image cannot be the same as the dst image"); + + // If the destination image is null, then BufferedImage is + // created with ColorModel of the source image + + if (dst == null) + dst = createCompatibleDestImage(src, src.getColorModel ()); + + // FIXME: Must check if color models of src and dst images are the same. + // If it is not, then source image should be converted to color model + // of the destination image + + Graphics2D gr = (Graphics2D) dst.createGraphics (); + gr.setRenderingHints (hints); + gr.drawImage (src, transform, null); + return dst; + + } + + /** + * Transforms source raster using transform specified at the constructor. + * The resulting raster is stored in the destination raster. + * + * @param src source raster + * @param dst destination raster + * @return transformed raster + */ + public final WritableRaster filter (Raster src, WritableRaster dst) + { + if (dst == src) + throw new IllegalArgumentException("src image cannot be the same as" + + " the dst image"); + + if (dst == null) + dst = createCompatibleDestRaster(src); + + if (src.getNumBands() != dst.getNumBands()) + throw new IllegalArgumentException("src and dst must have same number" + + " of bands"); + + double[] dpts = new double[dst.getWidth() * 2]; + double[] pts = new double[dst.getWidth() * 2]; + for (int x = 0; x < dst.getWidth(); x++) + { + dpts[2 * x] = x + dst.getMinX(); + dpts[2 * x + 1] = x; + } + Rectangle srcbounds = src.getBounds(); + if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)) + { + for (int y = dst.getMinY(); y < dst.getMinY() + dst.getHeight(); y++) + { + try { + transform.inverseTransform(dpts, 0, pts, 0, dst.getWidth() * 2); + } catch (NoninvertibleTransformException e) { + // Can't happen since the constructor traps this + e.printStackTrace(); + } + + for (int x = 0; x < dst.getWidth(); x++) + { + if (!srcbounds.contains(pts[2 * x], pts[2 * x + 1])) + continue; + dst.setDataElements(x + dst.getMinX(), y, + src.getDataElements((int)pts[2 * x], + (int)pts[2 * x + 1], + null)); + } + } + } + else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR)) + { + double[] tmp = new double[4 * src.getNumBands()]; + for (int y = dst.getMinY(); y < dst.getMinY() + dst.getHeight(); y++) + { + try { + transform.inverseTransform(dpts, 0, pts, 0, dst.getWidth() * 2); + } catch (NoninvertibleTransformException e) { + // Can't happen since the constructor traps this + e.printStackTrace(); + } + + for (int x = 0; x < dst.getWidth(); x++) + { + if (!srcbounds.contains(pts[2 * x], pts[2 * x + 1])) + continue; + int xx = (int)pts[2 * x]; + int yy = (int)pts[2 * x + 1]; + double dx = (pts[2 * x] - xx); + double dy = (pts[2 * x + 1] - yy); + + // TODO write this more intelligently + if (xx == src.getMinX() + src.getWidth() - 1 || + yy == src.getMinY() + src.getHeight() - 1) + { + // bottom or right edge + Arrays.fill(tmp, 0); + src.getPixel(xx, yy, tmp); + } + else + { + // Normal case + src.getPixels(xx, yy, 2, 2, tmp); + for (int b = 0; b < src.getNumBands(); b++) + tmp[b] = dx * dy * tmp[b] + + (1 - dx) * dy * tmp[b + src.getNumBands()] + + dx * (1 - dy) * tmp[b + 2 * src.getNumBands()] + + (1 - dx) * (1 - dy) * tmp[b + 3 * src.getNumBands()]; + } + dst.setPixel(x, y, tmp); + } + } + } + else + { + // Bicubic + throw new UnsupportedOperationException("not implemented yet"); + } + + return dst; + } + + /** + * Transforms source image using transform specified at the constructor and + * returns bounds of the transformed image. + * + * @param src image to be transformed + * @return bounds of the transformed image. + */ + public final Rectangle2D getBounds2D (BufferedImage src) + { + return getBounds2D (src.getRaster()); + } + + /** + * Returns bounds of the transformed raster. + * + * @param src raster to be transformed + * @return bounds of the transformed raster. + */ + public final Rectangle2D getBounds2D (Raster src) + { + // determine new size for the transformed raster. + // Need to calculate transformed coordinates of the lower right + // corner of the raster. The upper left corner is always (0,0) + + double x2 = (double) src.getWidth () + src.getMinX (); + double y2 = (double) src.getHeight () + src.getMinY (); + Point2D p2 = getPoint2D (new Point2D.Double (x2,y2), null); + + Rectangle2D rect = new Rectangle (0, 0, (int) p2.getX (), (int) p2.getY ()); + return rect.getBounds (); + } + + /** + * Returns interpolation type used during transformations + * + * @return interpolation type + */ + public final int getInterpolationType () + { + if(hints.containsValue (RenderingHints.VALUE_INTERPOLATION_BILINEAR)) + return TYPE_BILINEAR; + else + return TYPE_NEAREST_NEIGHBOR; + } + + /** + * Returns location of the transformed source point. The resulting point + * is stored in the dstPt if one is specified. + * + * @param srcPt point to be transformed + * @param dstPt destination point + * @return the location of the transformed source point. + */ + public Point2D getPoint2D (Point2D srcPt, Point2D dstPt) + { + return transform.transform (srcPt, dstPt); + } + + /** + * Returns rendering hints that are used during transformation. + * + * @return rendering hints + */ + public final RenderingHints getRenderingHints () + { + return hints; + } + + /** + * Returns transform used in transformation between source and destination + * image. + * + * @return transform + */ + public final AffineTransform getTransform () + { + return transform; + } +} diff --git a/libjava/classpath/java/awt/image/AreaAveragingScaleFilter.java b/libjava/classpath/java/awt/image/AreaAveragingScaleFilter.java new file mode 100644 index 0000000..b9ca1b7 --- /dev/null +++ b/libjava/classpath/java/awt/image/AreaAveragingScaleFilter.java @@ -0,0 +1,127 @@ +/* AreaAveragingScaleFilter.java -- Java class for filtering images + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +/** + * This filter should produce images which do not have image artifacts + * like broken lines which were originally unbroken. The cost is of + * course speed. Using bi-linear interpolation here against 4 pixel + * points should give the desired results although Sun does not + * specify what the exact algorithm should be. + * <br> + * Currently this filter does nothing and needs to be implemented. + * + * @author C. Brian Jones (cbj@gnu.org) + */ +public class AreaAveragingScaleFilter extends ReplicateScaleFilter +{ + /** + * Construct an instance of <code>AreaAveragingScaleFilter</code> which + * should be used in conjunction with a <code>FilteredImageSource</code> + * object. + * + * @param width the width of the destination image + * @param height the height of the destination image + */ + public AreaAveragingScaleFilter(int width, int height) { + super(width, height); + } + + /** + * The <code>ImageProducer</code> should call this method with a + * bit mask of hints from any of <code>RANDOMPIXELORDER</code>, + * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>, + * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code> from the + * <code>ImageConsumer</code> interface. + * <br> + * FIXME - more than likely Sun's implementation desires + * <code>TOPDOWNLEFTRIGHT</code> order and this method is overloaded here + * in order to assure that mask is part of the hints added to + * the consumer. + * + * @param flags a bit mask of hints + * @see ImageConsumer + */ + public void setHints(int flags) + { + consumer.setHints(flags); + } + + /** + * This function delivers a rectangle of pixels where any + * pixel(m,n) is stored in the array as a <code>byte</code> at + * index (n * scansize + m + offset). + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param model the <code>ColorModel</code> used to translate the pixels + * @param pixels the array of pixel values + * @param offset the index of the first pixels in the <code>pixels</code> array + * @param scansize the width to use in extracting pixels from the <code>pixels</code> array + */ + public void setPixels(int x, int y, int w, int h, + ColorModel model, byte[] pixels, int offset, int scansize) + { + consumer.setPixels(x, y, w, h, model, pixels, offset, scansize); + } + + /** + * This function delivers a rectangle of pixels where any + * pixel(m,n) is stored in the array as an <code>int</code> at + * index (n * scansize + m + offset). + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param model the <code>ColorModel</code> used to translate the pixels + * @param pixels the array of pixel values + * @param offset the index of the first pixels in the <code>pixels</code> array + * @param scansize the width to use in extracting pixels from the <code>pixels</code> array + */ + public void setPixels(int x, int y, int w, int h, + ColorModel model, int[] pixels, int offset, int scansize) + { + consumer.setPixels(x, y, w, h, model, pixels, offset, scansize); + } + +} + diff --git a/libjava/classpath/java/awt/image/BandCombineOp.java b/libjava/classpath/java/awt/image/BandCombineOp.java new file mode 100644 index 0000000..79efb02 --- /dev/null +++ b/libjava/classpath/java/awt/image/BandCombineOp.java @@ -0,0 +1,168 @@ +/* Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +/** + * Filter Raster pixels by applying a matrix. + * + * BandCombineOp applies a matrix to each pixel to produce new pixel values. + * The width of the matrix must be the same or one more than the number of + * bands in the source Raster. If one more, the pixels in the source are + * assumed to contain an implicit 1.0 at the end. + * + * The rows of the matrix are multiplied by the pixel to produce the values + * for the destination. Therefore the destination Raster must contain the + * same number of bands as the number of rows in the filter matrix. + * + * @author Jerry Quinn (jlquinn@optonline.net) + */ +public class BandCombineOp implements RasterOp +{ + private RenderingHints hints; + private float[][] matrix; + + /** + * Construct a BandCombineOp. + * + * @param matrix The matrix to filter pixels with. + * @param hints Rendering hints to apply. Ignored. + */ + public BandCombineOp(float[][] matrix, RenderingHints hints) + { + this.matrix = matrix; + this.hints = hints; + } + + /** + * Filter Raster pixels through a matrix. + * + * Applies the Op matrix to source pixes to produce dest pixels. Each row + * of the matrix is multiplied by the src pixel components to produce the + * dest pixel. If matrix is one more than the number of bands in the src, + * the last element is implicitly multiplied by 1, i.e. added to the sum + * for that dest component. + * + * If dest is null, a suitable Raster is created. This implementation uses + * createCompatibleDestRaster. + * + * @param src The source Raster. + * @param dest The destination Raster, or null. + * @returns The destination Raster or an allocated Raster. + * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, + *java.awt.image.WritableRaster) + */ + public WritableRaster filter(Raster src, WritableRaster dest) { + if (dest == null) + dest = createCompatibleDestRaster(src); + + // Filter the pixels + float[] spix = new float[matrix[0].length]; + float[] dpix = new float[matrix.length]; + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + { + // In case matrix rows have implicit translation + spix[spix.length - 1] = 1.0f; + src.getPixel(x, y, spix); + for (int i = 0; i < matrix.length; i++) + { + dpix[i] = 0; + for (int j = 0; j < matrix[0].length; j++) + dpix[i] += spix[j] * matrix[i][j]; + } + dest.setPixel(x, y, dpix); + } + + return dest; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster) + */ + public Rectangle2D getBounds2D(Raster src) + { + return src.getBounds(); + } + + /** + * Creates a new WritableRaster that can be used as the destination for this + * Op. This implementation creates a Banded Raster with data type FLOAT. + * @see + *java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster) + */ + public WritableRaster createCompatibleDestRaster(Raster src) + { + return Raster.createBandedRaster(DataBuffer.TYPE_FLOAT, src.getWidth(), + src.getHeight(), matrix.length, + new Point(src.getMinX(), src.getMinY())); + } + + /** Return corresponding destination point for source point. + * + * LookupOp will return the value of src unchanged. + * @param src The source point. + * @param dst The destination point. + * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, + *java.awt.geom.Point2D) + */ + public Point2D getPoint2D(Point2D src, Point2D dst) + { + if (dst == null) return (Point2D)src.clone(); + dst.setLocation(src); + return dst; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getRenderingHints() + */ + public RenderingHints getRenderingHints() + { + return hints; + } + + /** Return the matrix for this Op. */ + public float[][] getMatrix() + { + return matrix; + } + +} diff --git a/libjava/classpath/java/awt/image/BandedSampleModel.java b/libjava/classpath/java/awt/image/BandedSampleModel.java new file mode 100644 index 0000000..24d315a --- /dev/null +++ b/libjava/classpath/java/awt/image/BandedSampleModel.java @@ -0,0 +1,548 @@ +/* Copyright (C) 2004, 2005, Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +/** + * MultiPixelPackedSampleModel provides a single band model that supports + * multiple pixels in a single unit. Pixels have 2^n bits and 2^k pixels fit + * per data element. + * + * @author Jerry Quinn (jlquinn@optonline.net) + */ +public final class BandedSampleModel extends ComponentSampleModel +{ + private int[] bitMasks; + private int[] bitOffsets; + private int[] sampleSize; + private int dataBitOffset; + private int elemBits; + private int numberOfBits; + private int numElems; + + private static int[] createBankArray(int size) + { + int[] result = new int[size]; + for (int i = 0; i < size; i++) + result[i] = i; + return result; + } + + public BandedSampleModel(int dataType, int w, int h, int numBands) + { + this(dataType, w, h, w, createBankArray(numBands), new int[numBands]); + } + + public BandedSampleModel(int dataType, int w, int h, int scanlineStride, + int[] bankIndices, int[] bandOffsets) + { + super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets); + } + + public SampleModel createCompatibleSampleModel(int w, int h) + { + // NOTE: blackdown 1.4.1 sets all offsets to 0. Sun's 1.4.2 docs + // disagree. + + // Compress offsets so minimum is 0, others w*scanlineStride + int[] newoffsets = new int[bandOffsets.length]; + int[] order = new int[bandOffsets.length]; + for (int i=0; i < bandOffsets.length; i++) + order[i] = i; + // FIXME: This is N^2, but not a big issue, unless there's a lot of + // bands... + for (int i=0; i < bandOffsets.length; i++) + for (int j=i+1; j < bandOffsets.length; i++) + if (bankIndices[order[i]] > bankIndices[order[j]] + || (bankIndices[order[i]] == bankIndices[order[j]] + && bandOffsets[order[i]] > bandOffsets[order[j]])) + { + int t = order[i]; order[i] = order[j]; order[j] = t; + } + int bank = 0; + int offset = 0; + for (int i=0; i < bandOffsets.length; i++) + { + if (bankIndices[order[i]] != bank) + { + bank = bankIndices[order[i]]; + offset = 0; + } + newoffsets[order[i]] = offset; + offset += w * scanlineStride; + } + + return new BandedSampleModel(dataType, w, h, scanlineStride, bankIndices, newoffsets); + } + + + public SampleModel createSubsetSampleModel(int[] bands) + { + if (bands.length > bankIndices.length) + throw new + RasterFormatException("BandedSampleModel createSubsetSampleModel too" + +" many bands"); + int[] newoff = new int[bands.length]; + int[] newbanks = new int[bands.length]; + for (int i=0; i < bands.length; i++) + { + int b = bands[i]; + newoff[i] = bandOffsets[b]; + newbanks[i] = bankIndices[b]; + } + + return new BandedSampleModel(dataType, width, height, scanlineStride, + newbanks, newoff); + } + + /** + * Extract all samples of one pixel and return in an array of transfer type. + * + * Extracts the pixel at x, y from data and stores samples into the array + * obj. If obj is null, a new array of getTransferType() is created. + * + * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>. + * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>. + * @param obj The primitive array to store the pixels into or null to force creation. + * @param data The DataBuffer that is the source of the pixel data. + * @return The primitive array containing the pixel data. + * @see java.awt.image.SampleModel#getDataElements(int, int, java.lang.Object, java.awt.image.DataBuffer) + */ + public Object getDataElements(int x, int y, Object obj, + DataBuffer data) + { + int pixel = getSample(x, y, 0, data); + switch (getTransferType()) + { + case DataBuffer.TYPE_BYTE: + { + byte[] b = (byte[])obj; + if (b == null) b = new byte[numBands]; + for (int i=0; i < numBands; i++) + b[i] = (byte)getSample(x, y, i, data); + return b; + } + case DataBuffer.TYPE_SHORT: + case DataBuffer.TYPE_USHORT: + { + short[] b = (short[])obj; + if (b == null) b = new short[numBands]; + for (int i=0; i < numBands; i++) + b[i] = (short)getSample(x, y, i, data); + return b; + } + case DataBuffer.TYPE_INT: + { + int[] b = (int[])obj; + if (b == null) b = new int[numBands]; + for (int i=0; i < numBands; i++) + b[i] = getSample(x, y, i, data); + return b; + } + case DataBuffer.TYPE_FLOAT: + { + float[] b = (float[])obj; + if (b == null) b = new float[numBands]; + for (int i=0; i < numBands; i++) + b[i] = getSampleFloat(x, y, i, data); + return b; + } + case DataBuffer.TYPE_DOUBLE: + { + double[] b = (double[])obj; + if (b == null) b = new double[numBands]; + for (int i=0; i < numBands; i++) + b[i] = getSample(x, y, i, data); + return b; + } + + default: + // Seems like the only sensible thing to do. + throw new ClassCastException(); + } + } + + public int[] getPixel(int x, int y, int[] iArray, DataBuffer data) + { + if (iArray == null) iArray = new int[numBands]; + for (int i=0; i < numBands; i++) + iArray[i] = getSample(x, y, i, data); + + return iArray; + } + + /** + * Copy pixels from a region into an array. + * + * Copies the samples of the pixels in the rectangle starting at x, y that + * is w pixels wide and h scanlines high. When there is more than one band, + * the samples stored in order before the next pixel. This ordering isn't + * well specified in Sun's docs as of 1.4.2. + * + * If iArray is null, a new array is allocated, filled, and returned. + * + * @param x The x-coordinate of the pixel rectangle to store in + * <code>iArray</code>. + * @param y The y-coordinate of the pixel rectangle to store in + * <code>iArray</code>. + * @param w The width in pixels of the rectangle. + * @param h The height in pixels of the rectangle. + * @param iArray The int array to store the pixels into or null to force + * creation. + * @param data The DataBuffer that is the source of the pixel data. + * @return The primitive array containing the pixel data. + */ + public int[] getPixels(int x, int y, int w, int h, int[] iArray, + DataBuffer data) + { + if (iArray == null) iArray = new int[w*h*numBands]; + int outOffset = 0; + int maxX = x + w; + int maxY = y + h; + for (int yy = x; yy < maxY; yy++) + { + for (int xx = x; xx < maxX; xx++) + { + for (int b = 0; b < numBands; b++) + { + int offset = bandOffsets[b] + yy * scanlineStride + xx; + iArray[outOffset++] = + data.getElem(bankIndices[b], offset); + } + } + } + return iArray; + } + + public int getSample(int x, int y, int b, DataBuffer data) + { + int offset = bandOffsets[b] + y * scanlineStride + x; + return data.getElem(bankIndices[b], offset); + } + + public float getSampleFloat(int x, int y, int b, DataBuffer data) + { + int offset = bandOffsets[b] + y * scanlineStride + x; + return data.getElemFloat(bankIndices[b], offset); + } + + public double getSampleDouble(int x, int y, int b, DataBuffer data) + { + int offset = bandOffsets[b] + y * scanlineStride + x; + return data.getElemDouble(bankIndices[b], offset); + } + + /** + * Copy one band's samples from a region into an array. + * + * Copies from one band the samples of the pixels in the rectangle starting + * at x, y that is w pixels wide and h scanlines high. + * + * If iArray is null, a new array is allocated, filled, and returned. + * + * @param x The x-coordinate of the pixel rectangle to store in + * <code>iArray</code>. + * @param y The y-coordinate of the pixel rectangle to store in + * <code>iArray</code>. + * @param w The width in pixels of the rectangle. + * @param h The height in pixels of the rectangle. + * @param b The band to retrieve. + * @param iArray The int array to store the pixels into or null to force + * creation. + * @param data The DataBuffer that is the source of the pixel data. + * @return The primitive array containing the pixel data. + */ + public int[] getSamples(int x, int y, int w, int h, int b, int[] iArray, + DataBuffer data) + { + if (iArray == null) iArray = new int[w*h]; + int outOffset = 0; + int maxX = x + w; + int maxY = y + h; + for (int yy = y; yy < maxY; yy++) + { + for (int xx = x; xx < maxX; xx++) + { + int offset = bandOffsets[b] + yy * scanlineStride + xx; + iArray[outOffset++] = + data.getElem(bankIndices[b], offset); + } + } + return iArray; + } + + + /** + * Set the pixel at x, y to the value in the first element of the primitive + * array obj. + * + * @param x The x-coordinate of the data elements in <code>obj</code>. + * @param y The y-coordinate of the data elements in <code>obj</code>. + * @param obj The primitive array containing the data elements to set. + * @param data The DataBuffer to store the data elements into. + * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer) + */ + public void setDataElements(int x, int y, Object obj, DataBuffer data) + { + int transferType = getTransferType(); + if (getTransferType() != data.getDataType()) + { + throw new IllegalArgumentException("transfer type ("+ + getTransferType()+"), "+ + "does not match data "+ + "buffer type (" + + data.getDataType() + + ")."); + } + + int offset = y * scanlineStride + x; + + try + { + switch (transferType) + { + case DataBuffer.TYPE_BYTE: + { + DataBufferByte out = (DataBufferByte) data; + byte[] in = (byte[]) obj; + for (int i=0; i < numBands; i++) + out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i]; + return; + } + case DataBuffer.TYPE_SHORT: + { + DataBufferShort out = (DataBufferShort) data; + short[] in = (short[]) obj; + for (int i=0; i < numBands; i++) + out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i]; + return; + } + case DataBuffer.TYPE_USHORT: + { + DataBufferUShort out = (DataBufferUShort) data; + short[] in = (short[]) obj; + for (int i=0; i < numBands; i++) + out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i]; + return; + } + case DataBuffer.TYPE_INT: + { + DataBufferInt out = (DataBufferInt) data; + int[] in = (int[]) obj; + for (int i=0; i < numBands; i++) + out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i]; + return; + } + case DataBuffer.TYPE_FLOAT: + { + DataBufferFloat out = (DataBufferFloat) data; + float[] in = (float[]) obj; + for (int i=0; i < numBands; i++) + out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i]; + return; + } + case DataBuffer.TYPE_DOUBLE: + { + DataBufferDouble out = (DataBufferDouble) data; + double[] in = (double[]) obj; + for (int i=0; i < numBands; i++) + out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i]; + return; + } + default: + throw new ClassCastException("Unsupported data type"); + } + } + catch (ArrayIndexOutOfBoundsException aioobe) + { + String msg = "While writing data elements" + + ", x="+x+", y="+y+ + ", width="+width+", height="+height+ + ", scanlineStride="+scanlineStride+ + ", offset="+offset+ + ", data.getSize()="+data.getSize()+ + ", data.getOffset()="+data.getOffset()+ + ": " + + aioobe; + throw new ArrayIndexOutOfBoundsException(msg); + } + } + + public void setPixel(int x, int y, int[] iArray, DataBuffer data) + { + for (int b=0; b < numBands; b++) + data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, + iArray[b]); + } + + public void setPixels(int x, int y, int w, int h, int[] iArray, + DataBuffer data) + { + int inOffset = 0; + for (int hh = 0; hh < h; hh++) + { + for (int ww = 0; ww < w; ww++) + { + int offset = y * scanlineStride + (x + ww); + for (int b=0; b < numBands; b++) + data.setElem(bankIndices[b], bandOffsets[b] + offset, + iArray[inOffset++]); + } + y++; + } + } + + public void setSample(int x, int y, int b, int s, DataBuffer data) + { + data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s); + } + + public void setSample(int x, int y, int b, float s, DataBuffer data) + { + data.setElemFloat(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s); + } + + public void setSample(int x, int y, int b, double s, DataBuffer data) + { + data.setElemDouble(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s); + } + + public void setSamples(int x, int y, int w, int h, int b, int[] iArray, + DataBuffer data) + { + int inOffset = 0; + + switch (getTransferType()) + { + case DataBuffer.TYPE_BYTE: + { + DataBufferByte out = (DataBufferByte) data; + byte[] bank = out.getData(bankIndices[b]); + for (int hh = 0; hh < h; hh++) + { + for (int ww = 0; ww < w; ww++) + { + int offset = bandOffsets[b] + y * scanlineStride + (x + ww); + bank[offset] = (byte)iArray[inOffset++]; + } + y++; + } + return; + } + case DataBuffer.TYPE_SHORT: + { + DataBufferShort out = (DataBufferShort) data; + short[] bank = out.getData(bankIndices[b]); + for (int hh = 0; hh < h; hh++) + { + for (int ww = 0; ww < w; ww++) + { + int offset = bandOffsets[b] + y * scanlineStride + (x + ww); + bank[offset] = (short)iArray[inOffset++]; + } + y++; + } + return; + } + case DataBuffer.TYPE_USHORT: + { + DataBufferShort out = (DataBufferShort) data; + short[] bank = out.getData(bankIndices[b]); + for (int hh = 0; hh < h; hh++) + { + for (int ww = 0; ww < w; ww++) + { + int offset = bandOffsets[b] + y * scanlineStride + (x + ww); + bank[offset] = (short)iArray[inOffset++]; + } + y++; + } + return; + } + case DataBuffer.TYPE_INT: + { + DataBufferInt out = (DataBufferInt) data; + int[] bank = out.getData(bankIndices[b]); + for (int hh = 0; hh < h; hh++) + { + for (int ww = 0; ww < w; ww++) + { + int offset = bandOffsets[b] + y * scanlineStride + (x + ww); + bank[offset] = iArray[inOffset++]; + } + y++; + } + return; + } + case DataBuffer.TYPE_FLOAT: + case DataBuffer.TYPE_DOUBLE: + break; + default: + throw new ClassCastException("Unsupported data type"); + } + + // Default implementation probably slower for float and double + for (int hh = 0; hh < h; hh++) + { + for (int ww = 0; ww < w; ww++) + { + int offset = bandOffsets[b] + y * scanlineStride + (x + ww); + data.setElem(bankIndices[b], offset, iArray[inOffset++]); + } + y++; + } + } + + /** + * Creates a String with some information about this SampleModel. + * @return A String describing this SampleModel. + * @see java.lang.Object#toString() + */ + public String toString() + { + StringBuffer result = new StringBuffer(); + result.append(getClass().getName()); + result.append("["); + result.append("scanlineStride=").append(scanlineStride); + for(int i=0; i < bitMasks.length; i+=1) + { + result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i])); + } + + result.append("]"); + return result.toString(); + } +} diff --git a/libjava/classpath/java/awt/image/BufferStrategy.java b/libjava/classpath/java/awt/image/BufferStrategy.java new file mode 100644 index 0000000..e86aad6 --- /dev/null +++ b/libjava/classpath/java/awt/image/BufferStrategy.java @@ -0,0 +1,124 @@ +/* BufferStrategy.java -- describes image buffering resources + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.BufferCapabilities; +import java.awt.Graphics; + +/** + * This class describes a strategy for managing image buffering + * resources on a Canvas or Window. A given buffer strategy may make + * use of hardware acceleration or take advantage of features of the + * native graphics system. Examples of buffering strategies are + * double or triple buffering using either flipping or blitting. For + * the details of these algorithms see BufferCapabilities. + * + * To use a buffer strategy, you retrieve it from either the current + * GraphicsConfiguration or from the Component on which you'd like to + * draw. Then you can query the strategy's capabilities to make sure + * they're suitable. + * + * If the strategy's capabilities are suitable, you can obtain a + * graphics object and use it to draw with this strategy. Drawing + * with a buffer strategy requires extra care, however. You'll need + * to manually cause the next buffer to be shown on the output device. + * And since buffer strategies are usually implemented with a + * VolatileImage, you must frequently check that the contents of the + * buffer are valid and that the buffer still exists. + * + * A buffer strategy is usually implemented using a VolatileImage. + * + * @see VolatileImage + * @since 1.4 + */ +public abstract class BufferStrategy +{ + /** + * Creates a new buffer strategy. + */ + public BufferStrategy() + { + } + + /** + * Retrieves the capabilities of this buffer strategy. + * + * @return this buffer strategy's capabilities + */ + public abstract BufferCapabilities getCapabilities(); + + /** + * Retrieves a graphics object that can be used to draw using this + * buffer strategy. This method may not be synchronized so be + * careful when calling it from multiple threads. You also must + * manually dispose of this graphics object. + * + * @return a graphics object that can be used to draw using this + * buffer strategy + */ + public abstract Graphics getDrawGraphics(); + + /** + * Returns whether or not the buffer's resources have been reclaimed + * by the native graphics system. If the buffer resources have been + * lost then you'll need to obtain new resources before drawing + * again. For details, see the documentation for VolatileImage. + * + * @return true if the contents were lost, false otherwise + */ + public abstract boolean contentsLost(); + + /** + * Returns whether or not the buffer's resources were re-created and + * cleared to the default background color. If the buffer's + * resources have recently been re-created and initialized then the + * buffer's image may need to be re-rendered. For details, see the + * documentation for VolatileImage. + * + * @return true if the contents were restored, false otherwise + */ + public abstract boolean contentsRestored(); + + /** + * Applies this buffer strategy. In other words, this method brings + * the contents of the back or intermediate buffers to the front + * buffer. + */ + public abstract void show(); +} diff --git a/libjava/classpath/java/awt/image/BufferedImage.java b/libjava/classpath/java/awt/image/BufferedImage.java new file mode 100644 index 0000000..124b813 --- /dev/null +++ b/libjava/classpath/java/awt/image/BufferedImage.java @@ -0,0 +1,693 @@ +/* BufferedImage.java -- + Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import gnu.java.awt.ComponentDataBlitOp; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Transparency; +import java.awt.color.ColorSpace; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Vector; + +/** + * A buffered image always starts at coordinates (0, 0). + * + * The buffered image is not subdivided into multiple tiles. Instead, + * the image consists of one large tile (0,0) with the width and + * height of the image. This tile is always considered to be checked + * out. + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public class BufferedImage extends Image + implements WritableRenderedImage +{ + public static final int TYPE_CUSTOM = 0, + TYPE_INT_RGB = 1, + TYPE_INT_ARGB = 2, + TYPE_INT_ARGB_PRE = 3, + TYPE_INT_BGR = 4, + TYPE_3BYTE_BGR = 5, + TYPE_4BYTE_ABGR = 6, + TYPE_4BYTE_ABGR_PRE = 7, + TYPE_USHORT_565_RGB = 8, + TYPE_USHORT_555_RGB = 9, + TYPE_BYTE_GRAY = 10, + TYPE_USHORT_GRAY = 11, + TYPE_BYTE_BINARY = 12, + TYPE_BYTE_INDEXED = 13; + + static final int[] bits3 = { 8, 8, 8 }; + static final int[] bits4 = { 8, 8, 8 }; + static final int[] bits1byte = { 8 }; + static final int[] bits1ushort = { 16 }; + + static final int[] masks_int = { 0x00ff0000, + 0x0000ff00, + 0x000000ff, + DataBuffer.TYPE_INT }; + static final int[] masks_565 = { 0xf800, + 0x07e0, + 0x001f, + DataBuffer.TYPE_USHORT}; + static final int[] masks_555 = { 0x7c00, + 0x03e0, + 0x001f, + DataBuffer.TYPE_USHORT}; + + Vector observers; + + public BufferedImage(int w, int h, int type) + { + ColorModel cm = null; + + boolean alpha = false; + boolean premultiplied = false; + switch (type) + { + case TYPE_4BYTE_ABGR_PRE: + case TYPE_INT_ARGB_PRE: + premultiplied = true; + // fall through + case TYPE_INT_ARGB: + case TYPE_4BYTE_ABGR: + alpha = true; + } + + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + switch (type) + { + case TYPE_INT_RGB: + case TYPE_INT_ARGB: + case TYPE_INT_ARGB_PRE: + case TYPE_USHORT_565_RGB: + case TYPE_USHORT_555_RGB: + int[] masks = null; + switch (type) + { + case TYPE_INT_RGB: + case TYPE_INT_ARGB: + case TYPE_INT_ARGB_PRE: + masks = masks_int; + break; + case TYPE_USHORT_565_RGB: + masks = masks_565; + break; + case TYPE_USHORT_555_RGB: + masks = masks_555; + break; + } + + cm = new DirectColorModel(cs, + 32, // 32 bits in an int + masks[0], // r + masks[1], // g + masks[2], // b + alpha ? 0xff000000 : 0, + premultiplied, + masks[3] // data type + ); + break; + + case TYPE_INT_BGR: + String msg = + "FIXME: Programmer is confused. Why (and how) does a " + + "TYPE_INT_BGR image use ComponentColorModel to store " + + "8-bit values? Is data type TYPE_INT or TYPE_BYTE. What " + + "is the difference between TYPE_INT_BGR and TYPE_3BYTE_BGR?"; + throw new UnsupportedOperationException(msg); + + case TYPE_3BYTE_BGR: + case TYPE_4BYTE_ABGR: + case TYPE_4BYTE_ABGR_PRE: + case TYPE_BYTE_GRAY: + case TYPE_USHORT_GRAY: + int[] bits = null; + int dataType = DataBuffer.TYPE_BYTE; + switch (type) { + case TYPE_3BYTE_BGR: + bits = bits3; + break; + case TYPE_4BYTE_ABGR: + case TYPE_4BYTE_ABGR_PRE: + bits = bits4; + break; + case TYPE_BYTE_GRAY: + bits = bits1byte; + break; + case TYPE_USHORT_GRAY: + bits = bits1ushort; + dataType = DataBuffer.TYPE_USHORT; + break; + } + cm = new ComponentColorModel(cs, bits, alpha, premultiplied, + alpha ? + Transparency.TRANSLUCENT: + Transparency.OPAQUE, + dataType); + break; + case TYPE_BYTE_BINARY: + byte[] vals = { 0, (byte) 0xff }; + cm = new IndexColorModel(8, 2, vals, vals, vals); + break; + case TYPE_BYTE_INDEXED: + String msg2 = "type not implemented yet"; + throw new UnsupportedOperationException(msg2); + // FIXME: build color-cube and create color model + } + + init(cm, + cm.createCompatibleWritableRaster(w, h), + premultiplied, + null, // no properties + type + ); + } + + public BufferedImage(int w, int h, int type, + IndexColorModel indexcolormodel) + { + if ((type != TYPE_BYTE_BINARY) && (type != TYPE_BYTE_INDEXED)) + throw new IllegalArgumentException("type must be binary or indexed"); + + init(indexcolormodel, + indexcolormodel.createCompatibleWritableRaster(w, h), + false, // not premultiplied (guess) + null, // no properties + type); + } + + public BufferedImage(ColorModel colormodel, + WritableRaster writableraster, + boolean premultiplied, + Hashtable properties) + { + init(colormodel, writableraster, premultiplied, properties, + TYPE_CUSTOM); + // TODO: perhaps try to identify type? + } + + WritableRaster raster; + ColorModel colorModel; + Hashtable properties; + boolean isPremultiplied; + int type; + + private void init(ColorModel cm, + WritableRaster writableraster, + boolean premultiplied, + Hashtable properties, + int type) + { + raster = writableraster; + colorModel = cm; + this.properties = properties; + isPremultiplied = premultiplied; + this.type = type; + } + + //public void addTileObserver(TileObserver tileobserver) {} + + public void coerceData(boolean premultiplied) + { + colorModel = colorModel.coerceData(raster, premultiplied); + } + + public WritableRaster copyData(WritableRaster dest) + { + if (dest == null) + dest = raster.createCompatibleWritableRaster(getMinX(), getMinY(), + getWidth(),getHeight()); + + int x = dest.getMinX(); + int y = dest.getMinY(); + int w = dest.getWidth(); + int h = dest.getHeight(); + + // create a src child that has the right bounds... + WritableRaster src = + raster.createWritableChild(x, y, w, h, x, y, + null // same bands + ); + if (src.getSampleModel () instanceof ComponentSampleModel + && dest.getSampleModel () instanceof ComponentSampleModel) + // Refer to ComponentDataBlitOp for optimized data blitting: + ComponentDataBlitOp.INSTANCE.filter(src, dest); + else + { + // slower path + int samples[] = src.getPixels (x, y, w, h, (int [])null); + dest.setPixels (x, y, w, h, samples); + } + return dest; + } + + public Graphics2D createGraphics() + { + GraphicsEnvironment env; + env = GraphicsEnvironment.getLocalGraphicsEnvironment (); + return env.createGraphics (this); + } + + public void flush() { + } + + public WritableRaster getAlphaRaster() + { + return colorModel.getAlphaRaster(raster); + } + + public ColorModel getColorModel() + { + return colorModel; + } + + public Raster getData() + { + return copyData(null); + /* TODO: this might be optimized by returning the same + raster (not writable) as long as image data doesn't change. */ + } + + public Raster getData(Rectangle rectangle) + { + WritableRaster dest = + raster.createCompatibleWritableRaster(rectangle); + return copyData(dest); + } + + public Graphics getGraphics() + { + return createGraphics(); + } + + public int getHeight() + { + return raster.getHeight(); + } + + public int getHeight(ImageObserver imageobserver) + { + return getHeight(); + } + + public int getMinTileX() + { + return 0; + } + + public int getMinTileY() + { + return 0; + } + + public int getMinX() + { + return 0; + } + + public int getMinY() + { + return 0; + } + + public int getNumXTiles() + { + return 1; + } + + public int getNumYTiles() + { + return 1; + } + + public Object getProperty(String string) + { + if (properties == null) + return null; + return properties.get(string); + } + + public Object getProperty(String string, ImageObserver imageobserver) + { + return getProperty(string); + } + + + public String[] getPropertyNames() + { + // FIXME: implement + return null; + } + + public int getRGB(int x, int y) + { + Object rgbElem = raster.getDataElements(x, y, + null // create as needed + ); + return colorModel.getRGB(rgbElem); + } + + public int[] getRGB(int startX, int startY, int w, int h, + int[] rgbArray, + int offset, int scanlineStride) + { + if (rgbArray == null) + { + /* + 000000000000000000 + 00000[#######----- [ = start + -----########----- ] = end + -----#######]00000 + 000000000000000000 */ + int size = (h-1)*scanlineStride + w; + rgbArray = new int[size]; + } + + int endX = startX + w; + int endY = startY + h; + + /* *TODO*: + Opportunity for optimization by examining color models... + + Perhaps wrap the rgbArray up in a WritableRaster with packed + sRGB color model and perform optimized rendering into the + array. */ + + Object rgbElem = null; + for (int y=startY; y<endY; y++) + { + int xoffset = offset; + for (int x=startX; x<endX; x++) + { + int rgb; + rgbElem = raster.getDataElements(x, y, rgbElem); + rgb = colorModel.getRGB(rgbElem); + rgbArray[xoffset++] = rgb; + } + offset += scanlineStride; + } + return rgbArray; + } + + public WritableRaster getRaster() + { + return raster; + } + + public SampleModel getSampleModel() + { + return raster.getSampleModel(); + } + + public ImageProducer getSource() + { + return new ImageProducer() { + + Vector consumers = new Vector(); + + public void addConsumer(ImageConsumer ic) + { + if(!consumers.contains(ic)) + consumers.add(ic); + } + + public boolean isConsumer(ImageConsumer ic) + { + return consumers.contains(ic); + } + + public void removeConsumer(ImageConsumer ic) + { + consumers.remove(ic); + } + + public void startProduction(ImageConsumer ic) + { + int x = 0; + int y = 0; + int width = getWidth(); + int height = getHeight(); + int stride = width; + int offset = 0; + int[] pixels = getRGB(x, y, + width, height, + (int[])null, offset, stride); + ColorModel model = getColorModel(); + + consumers.add(ic); + + for(int i=0;i<consumers.size();i++) + { + ImageConsumer c = (ImageConsumer) consumers.elementAt(i); + c.setHints(ImageConsumer.SINGLEPASS); + c.setDimensions(getWidth(), getHeight()); + c.setPixels(x, y, width, height, model, pixels, offset, stride); + c.imageComplete(ImageConsumer.STATICIMAGEDONE); + } + } + + public void requestTopDownLeftRightResend(ImageConsumer ic) + { + startProduction(ic); + } + + }; + } + + public Vector getSources() + { + return null; + } + + public BufferedImage getSubimage(int x, int y, int w, int h) + { + WritableRaster subRaster = + getRaster().createWritableChild(x, y, w, h, 0, 0, null); + + return new BufferedImage(getColorModel(), + subRaster, + isPremultiplied, + properties); + } + + public Raster getTile(int tileX, int tileY) + { + return getWritableTile(tileX, tileY); + } + + public int getTileGridXOffset() + { + return 0; // according to javadocs + } + + public int getTileGridYOffset() + { + return 0; // according to javadocs + } + + public int getTileHeight() + { + return getHeight(); // image is one big tile + } + + public int getTileWidth() + { + return getWidth(); // image is one big tile + } + + public int getType() + { + return type; + } + + public int getWidth() + { + return raster.getWidth(); + } + + public int getWidth(ImageObserver imageobserver) + { + return getWidth(); + } + + public WritableRaster getWritableTile(int tileX, int tileY) + { + isTileWritable(tileX, tileY); // for exception + return raster; + } + + private static final Point[] tileIndices = { new Point() }; + + public Point[] getWritableTileIndices() + { + return tileIndices; + } + + public boolean hasTileWriters() + { + return true; + } + + public boolean isAlphaPremultiplied() + { + return isPremultiplied; + } + + public boolean isTileWritable(int tileX, int tileY) + { + if ((tileX != 0) || (tileY != 0)) + throw new ArrayIndexOutOfBoundsException("only tile is (0,0)"); + return true; + } + + public void releaseWritableTile(int tileX, int tileY) + { + isTileWritable(tileX, tileY); // for exception + } + + //public void removeTileObserver(TileObserver tileobserver) {} + + public void setData(Raster src) + { + int x = src.getMinX(); + int y = src.getMinY(); + int w = src.getWidth(); + int h = src.getHeight(); + + // create a dest child that has the right bounds... + WritableRaster dest = + raster.createWritableChild(x, y, w, h, x, y, + null // same bands + ); + + if (src.getSampleModel () instanceof ComponentSampleModel + && dest.getSampleModel () instanceof ComponentSampleModel) + + // Refer to ComponentDataBlitOp for optimized data blitting: + ComponentDataBlitOp.INSTANCE.filter(src, dest); + else + { + // slower path + int samples[] = src.getPixels (x, y, w, h, (int [])null); + dest.setPixels (x, y, w, h, samples); + } + } + + public void setRGB(int x, int y, int argb) + { + Object rgbElem = colorModel.getDataElements(argb, null); + raster.setDataElements(x, y, rgbElem); + } + + public void setRGB(int startX, int startY, int w, int h, + int[] argbArray, int offset, int scanlineStride) + { + int endX = startX + w; + int endY = startY + h; + + Object rgbElem = null; + for (int y=startY; y<endY; y++) + { + int xoffset = offset; + for (int x=startX; x<endX; x++) + { + int argb = argbArray[xoffset++]; + rgbElem = colorModel.getDataElements(argb, rgbElem); + raster.setDataElements(x, y, rgbElem); + } + offset += scanlineStride; + } + } + + public String toString() + { + StringBuffer buf; + + buf = new StringBuffer(/* estimated length */ 120); + buf.append("BufferedImage@"); + buf.append(Integer.toHexString(hashCode())); + buf.append(": type="); + buf.append(type); + buf.append(' '); + buf.append(colorModel); + buf.append(' '); + buf.append(raster); + + return buf.toString(); + } + + + /** + * Adds a tile observer. If the observer is already present, it receives + * multiple notifications. + * + * @param to The TileObserver to add. + */ + public void addTileObserver (TileObserver to) + { + if (observers == null) + observers = new Vector (); + + observers.add (to); + } + + /** + * Removes a tile observer. If the observer was not registered, + * nothing happens. If the observer was registered for multiple + * notifications, it is now registered for one fewer notification. + * + * @param to The TileObserver to remove. + */ + public void removeTileObserver (TileObserver to) + { + if (observers == null) + return; + + observers.remove (to); + } +} diff --git a/libjava/classpath/java/awt/image/BufferedImageFilter.java b/libjava/classpath/java/awt/image/BufferedImageFilter.java new file mode 100644 index 0000000..50d627d --- /dev/null +++ b/libjava/classpath/java/awt/image/BufferedImageFilter.java @@ -0,0 +1,110 @@ +/* Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +import java.awt.Point; + +/** + * The BufferedImageFilter class wraps BufferedImageOp objects in a Filter. + * + * When pixels are pushed through the filter, we create a BufferedImage, + * apply the BufferedImageOp, and pass the filtered pixels to the base class. + * + * @author jlquinn@optonline.net + */ +public class BufferedImageFilter extends ImageFilter implements Cloneable +{ + private BufferedImageOp op; + + /** + * + */ + public BufferedImageFilter(BufferedImageOp op) + { + super(); + if (op == null) + throw new NullPointerException("BufferedImageFilter null" + + " op in constructor"); + this.op = op; + } + + /** + * @return Returns the contained BufferedImageOp. + */ + public BufferedImageOp getBufferedImageOp() + { + return op; + } + + // FIXME: Definitely not sure this is the right thing. I'm not sure how to + // create a compatible sample model that incorporates scansize != w. I + // asume off is handled by the db itself. + public void setPixels(int x, int y, int w, int h, ColorModel model, + byte[] pixels, int off, int scansize) + { + // Create an input BufferedImage + DataBufferByte db = new DataBufferByte(pixels, scansize * h + off, off); + SampleModel sm = model.createCompatibleSampleModel(scansize, h); + WritableRaster wr = new WritableRaster(sm, db, new Point(0, 0)); + BufferedImage in = + new BufferedImage(model, wr, model.isAlphaPremultiplied(), null); + BufferedImage out = op.createCompatibleDestImage(in, model); + op.filter(in, out); + DataBuffer dbout = out.getRaster().getDataBuffer(); + super.setPixels(0, 0, w, h, model, ((DataBufferByte)dbout).getData(), 0, + scansize); + } + + // FIXME: Definitely not sure this is the right thing. I'm not sure how + // to create a compatible sample model that incorporates + // scansize != w. I asume off is handled by the db itself. + public void setPixels(int x, int y, int w, int h, ColorModel model, + int[] pixels, int off, int scansize) + { + // Create an input BufferedImage + DataBufferInt db = new DataBufferInt(pixels, scansize * h + off, off); + SampleModel sm = model.createCompatibleSampleModel(scansize, h); + WritableRaster wr = new WritableRaster(sm, db, new Point(0, 0)); + BufferedImage in = + new BufferedImage(model, wr, model.isAlphaPremultiplied(), null); + BufferedImage out = op.createCompatibleDestImage(in, model); + op.filter(in, out); + DataBuffer dbout = out.getRaster().getDataBuffer(); + super.setPixels(0, 0, w, h, model, ((DataBufferInt)dbout).getData(), 0, + scansize); + } +} diff --git a/libjava/classpath/java/awt/image/BufferedImageOp.java b/libjava/classpath/java/awt/image/BufferedImageOp.java new file mode 100644 index 0000000..2ecbec0 --- /dev/null +++ b/libjava/classpath/java/awt/image/BufferedImageOp.java @@ -0,0 +1,55 @@ +/* BufferedImageOp.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +/** + * NEEDS DOCUMENTATION + */ +public interface BufferedImageOp +{ + BufferedImage filter(BufferedImage src, BufferedImage dst); + Rectangle2D getBounds2D(BufferedImage src); + BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM); + Point2D getPoint2D(Point2D src, Point2D dst); + RenderingHints getRenderingHints(); +} // interface BufferedImageOp diff --git a/libjava/classpath/java/awt/image/ByteLookupTable.java b/libjava/classpath/java/awt/image/ByteLookupTable.java new file mode 100644 index 0000000..df02d0a --- /dev/null +++ b/libjava/classpath/java/awt/image/ByteLookupTable.java @@ -0,0 +1,166 @@ +/* ByteLookupTable.java -- Java class for a pixel translation table. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +/** + * ByteLookupTable represents translation arrays for pixel values. It wraps + * one or more data arrays for each layer (or component) in an image, such as + * Alpha, R, G, and B. When doing translation, the offset is subtracted from + * the pixel values to allow a subset of an array to be used. + * + * @author Jerry Quinn (jlquinn@optonline.net) + * @version 1.0 + */ +public class ByteLookupTable extends LookupTable +{ + // Array of translation tables. + private byte data[][]; + + /** + * Creates a new <code>ByteLookupTable</code> instance. + * + * Offset is subtracted from pixel values when looking up in the translation + * tables. If data.length is one, the same table is applied to all pixel + * components. + * + * @param offset Offset to be subtracted. + * @param data Array of lookup tables. + * @exception IllegalArgumentException if offset < 0 or data.length < 1. + */ + public ByteLookupTable(int offset, byte[][] data) + throws IllegalArgumentException + { + super(offset, data.length); + this.data = data; + } + + /** + * Creates a new <code>ByteLookupTable</code> instance. + * + * Offset is subtracted from pixel values when looking up in the translation + * table. The same table is applied to all pixel components. + * + * @param offset Offset to be subtracted. + * @param data Lookup table for all components. + * @exception IllegalArgumentException if offset < 0. + */ + public ByteLookupTable(int offset, byte[] data) + throws IllegalArgumentException + { + super(offset, 1); + this.data = new byte[][] {data}; + } + + /** + * Return the lookup tables. + * + * @return the tables + */ + public final byte[][] getTable() + { + return data; + } + + /** + * Return translated values for a pixel. + * + * For each value in the pixel src, use the value minus offset as an index + * in the component array and copy the value there to the output for the + * component. If dest is null, the output is a new array, otherwise the + * translated values are written to dest. Dest can be the same array as + * src. + * + * For example, if the pixel src is [2, 4, 3], and offset is 1, the output + * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the + * translation arrays. + * + * @param src Component values of a pixel. + * @param dst Destination array for values, or null. + * @return Translated values for the pixel. + */ + public int[] lookupPixel(int[] src, int[] dst) + throws ArrayIndexOutOfBoundsException + { + if (dst == null) + dst = new int[src.length]; + + if (data.length == 1) + for (int i=0; i < src.length; i++) + dst[i] = data[0][src[i] - offset]; + else + for (int i=0; i < src.length; i++) + dst[i] = data[i][src[i] - offset]; + + return dst; + } + + /** + * Return translated values for a pixel. + * + * For each value in the pixel src, use the value minus offset as an index + * in the component array and copy the value there to the output for the + * component. If dest is null, the output is a new array, otherwise the + * translated values are written to dest. Dest can be the same array as + * src. + * + * For example, if the pixel src is [2, 4, 3], and offset is 1, the output + * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the + * translation arrays. + * + * @param src Component values of a pixel. + * @param dst Destination array for values, or null. + * @return Translated values for the pixel. + */ + public byte[] lookupPixel(byte[] src, byte[] dst) + throws ArrayIndexOutOfBoundsException + { + if (dst == null) + dst = new byte[src.length]; + + if (data.length == 1) + for (int i=0; i < src.length; i++) + dst[i] = data[0][((int)src[i]) - offset]; + else + for (int i=0; i < src.length; i++) + dst[i] = data[i][((int)src[i]) - offset]; + + return dst; + + } +} diff --git a/libjava/classpath/java/awt/image/ColorConvertOp.java b/libjava/classpath/java/awt/image/ColorConvertOp.java new file mode 100644 index 0000000..18609e0 --- /dev/null +++ b/libjava/classpath/java/awt/image/ColorConvertOp.java @@ -0,0 +1,319 @@ +/* ColorModel.java -- + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.color.ColorSpace; +import java.awt.color.ICC_ColorSpace; +import java.awt.color.ICC_Profile; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +/** + * ColorConvertOp is a filter for converting an image from one colorspace to + * another colorspace. The filter can convert the image through a sequence + * of colorspaces or just from source to destination. + * + * Color conversion is done on the color components without alpha. Thus + * if a BufferedImage has alpha premultiplied, this is divided out before + * color conversion, and premultiplication applied if the destination + * requires it. + * + * Color rendering and dithering hints may be applied if specified. This is + * likely platform-dependent. + * + * @author jlquinn@optonline.net + */ +public class ColorConvertOp implements BufferedImageOp, RasterOp +{ + private ColorSpace srccs; + private ColorSpace dstcs; + private RenderingHints hints; + private ICC_Profile[] profiles; + private ColorSpace[] spaces; + private boolean rasterValid; + + + /** + * Convert BufferedImage through a ColorSpace. + * + * This filter version is only valid for BufferedImages. The source image + * is converted to cspace. If the destination is not null, it is then + * converted to the destination colorspace. Normally this filter will only + * be used with a null destination. + * + * @param cspace The target color space. + * @param hints Rendering hints to use in conversion, or null. + */ + public ColorConvertOp(ColorSpace cspace, RenderingHints hints) + { + if (cspace == null) + throw new NullPointerException(); + spaces = new ColorSpace[]{cspace}; + this.hints = hints; + rasterValid = false; + } + + public ColorConvertOp(ColorSpace srcCspace, ColorSpace dstCspace, + RenderingHints hints) + { + if (srcCspace == null || dstCspace == null) + throw new NullPointerException(); + spaces = new ColorSpace[]{srcCspace, dstCspace}; + this.hints = hints; + } + + /** + * Convert from a source image destination image color space. + * + * This constructor builds a ColorConvertOp from an array of ICC_Profiles. + * The source image will be converted through the sequence of color spaces + * defined by the profiles. If the sequence of profiles doesn't give a + * well-defined conversion, throws IllegalArgumentException. + * + * NOTE: Sun's docs don't clearly define what a well-defined conversion is + * - or perhaps someone smarter can come along and sort it out. + * + * For BufferedImages, when the first and last profiles match the + * requirements of the source and destination color space respectively, the + * corresponding conversion is unnecessary. TODO: code this up. I don't + * yet understand how you determine this. + * + * For Rasters, the first and last profiles must have the same number of + * bands as the source and destination Rasters, respectively. If this is + * not the case, or there fewer than 2 profiles, an IllegalArgumentException + * will be thrown. + * + * @param profiles + * @param hints + */ + public ColorConvertOp(ICC_Profile[] profiles, RenderingHints hints) + { + if (profiles == null) + throw new NullPointerException(); + this.hints = hints; + this.profiles = profiles; + // TODO: Determine if this is well-defined. + // Create colorspace array with space for src and dest colorspace + spaces = new ColorSpace[profiles.length]; + for (int i = 0; i < profiles.length; i++) + spaces[i] = new ICC_ColorSpace(profiles[i]); + } + + /** Convert from source image color space to destination image color space. + * + * Only valid for BufferedImage objects, this Op converts from the source + * color space to the destination color space. The destination can't be + * null for this operation. + * + * @param hints Rendering hints to use during conversion, or null. + */ + public ColorConvertOp(RenderingHints hints) + { + this.hints = hints; + srccs = null; + dstcs = null; + rasterValid = false; + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, + java.awt.image.BufferedImage) + */ + public final BufferedImage filter(BufferedImage src, BufferedImage dst) + { + // TODO: The plan is to create a scanline buffer for intermediate buffers. + // For now we just suck it up and create intermediate buffers. + + if (dst == null && spaces.length == 0) + throw new IllegalArgumentException(); + + // Make sure input isn't premultiplied by alpha + if (src.isAlphaPremultiplied()) + { + BufferedImage tmp = createCompatibleDestImage(src, src.getColorModel()); + copyimage(src, tmp); + tmp.coerceData(false); + src = tmp; + } + + ColorModel scm = src.getColorModel(); + for (int i = 0; i < spaces.length; i++) + { + ColorModel cm = scm.cloneColorModel(spaces[i]); + BufferedImage tmp = createCompatibleDestImage(src, cm); + copyimage(src, tmp); + src = tmp; + } + + // Intermediate conversions leave result in src + if (dst == null) + return src; + + // Apply final conversion + copyimage(src, dst); + return dst; + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel) + */ + public BufferedImage createCompatibleDestImage(BufferedImage src, + ColorModel dstCM) + { + // FIXME: set properties to those in src + return new BufferedImage(dstCM, + src.getRaster().createCompatibleWritableRaster(), + src.isPremultiplied, + null); + } + + public final ICC_Profile[] getICC_Profiles() + { + return profiles; + } + + /** Return the rendering hints for this op. */ + public final RenderingHints getRenderingHints() + { + return hints; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster) + */ + public final WritableRaster filter(Raster src, WritableRaster dest) + { + if (!rasterValid) + throw new IllegalArgumentException(); + + // Need to iterate through each color space - there must be at least 2 + for (int i = 1; i < spaces.length - 1; i++) + { + // FIXME: this is wrong. tmp needs to have the same number of bands as + // spaces[i] has. + WritableRaster tmp = createCompatibleDestRaster(src); + copyraster(src, spaces[i - 1], tmp, spaces[i]); + src = tmp; + } + + // FIXME: this is wrong. dst needs to have the same number of bands as + // spaces[i] has. + if (dest == null) + dest = createCompatibleDestRaster(src); + copyraster(src, spaces[spaces.length - 2], + dest, spaces[spaces.length - 1]); + + return dest; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster) + */ + public WritableRaster createCompatibleDestRaster(Raster src) + { + return src.createCompatibleWritableRaster(); + } + + /** Return corresponding destination point for source point. + * + * LookupOp will return the value of src unchanged. + * @param src The source point. + * @param dst The destination point. + * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D) + */ + public final Point2D getPoint2D(Point2D src, Point2D dst) + { + if (dst == null) return (Point2D)src.clone(); + dst.setLocation(src); + return dst; + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage) + */ + public final Rectangle2D getBounds2D(BufferedImage src) + { + return src.getRaster().getBounds(); + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster) + */ + public final Rectangle2D getBounds2D(Raster src) + { + return src.getBounds(); + } + + // According to Sven de Marothy, we need to copy the src into the dest + // using Graphics2D, in order to use the rendering hints. + private void copyimage(BufferedImage src, BufferedImage dst) + { + Graphics2D gg = dst.createGraphics(); + gg.setRenderingHints(hints); + gg.drawImage(src, 0, 0, null); + gg.dispose(); + } + + private void copyraster(Raster src, ColorSpace scs, WritableRaster dst, + ColorSpace dcs) + { + float[] sbuf = new float[src.getNumBands()]; + + if (hints.get(RenderingHints.KEY_COLOR_RENDERING) == + RenderingHints.VALUE_COLOR_RENDER_QUALITY) + { + // use cie for accuracy + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + dst.setPixel(x, y, + dcs.fromCIEXYZ(scs.toCIEXYZ(src.getPixel(x, y, sbuf)))); + } + else + { + // use rgb - it's probably faster + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + dst.setPixel(x, y, + dcs.fromRGB(scs.toRGB(src.getPixel(x, y, sbuf)))); + } + } + +} diff --git a/libjava/classpath/java/awt/image/ColorModel.java b/libjava/classpath/java/awt/image/ColorModel.java new file mode 100644 index 0000000..1ebcb98 --- /dev/null +++ b/libjava/classpath/java/awt/image/ColorModel.java @@ -0,0 +1,758 @@ +/* ColorModel.java -- + Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import gnu.java.awt.Buffers; + +import java.awt.Point; +import java.awt.Transparency; +import java.awt.color.ColorSpace; +import java.lang.reflect.Constructor; +import java.util.Arrays; + +/** + * A color model operates with colors in several formats: + * + * <ul> + * <li>normalized: component samples are in range [0.0, 1.0].</li> + * + * <li>color model pixel value: all the color component samples for a + * sigle pixel packed/encoded in a way natural for the color + * model.</li> + * + * <li>color model pixel int value: only makes sense if the natural + * encoding of a single pixel can fit in a single int value.</li> + * + * <li>array of transferType containing a single pixel: the pixel is + * encoded in the natural way of the color model, taking up as many + * array elements as needed.</li> + * + * <li>sRGB pixel int value: a pixel in sRGB color space, encoded in + * default 0xAARRGGBB format, assumed not alpha premultiplied.</li> + * + * <li>single [0, 255] scaled int samples from default sRGB color + * space. These are always assumed to be alpha non-premultiplied.</li> + * + * <li>arrays of unnormalized component samples of single pixel: these + * samples are scaled and multiplied according to the color model, but + * is otherwise not packed or encoded. Each element of the array is one + * separate component sample. The color model only operate on the + * components from one pixel at a time, but using offsets, allows + * manipulation of arrays that contain the components of more than one + * pixel.</li> + * + * </ul> + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + * @author C. Brian Jones (cbj@gnu.org) + */ +public abstract class ColorModel implements Transparency +{ + protected int pixel_bits; + protected int transferType; + + int[] bits; + ColorSpace cspace; + int transparency; + boolean hasAlpha; + boolean isAlphaPremultiplied; + + static int[] nArray(int value, int times) + { + int[] array = new int[times]; + java.util.Arrays.fill(array, value); + return array; + } + + static byte[] nArray(byte value, int times) + { + byte[] array = new byte[times]; + java.util.Arrays.fill(array, value); + return array; + } + + /** + * Constructs the default color model. The default color model + * can be obtained by calling <code>getRGBdefault</code> of this + * class. + * @param bits the number of bits wide used for bit size of pixel values + */ + public ColorModel(int bits) + { + this(bits * 4, // total bits, sRGB, four channels + nArray(bits, 4), // bits for each channel + ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB + true, // has alpha + false, // not premultiplied + TRANSLUCENT, + Buffers.smallestAppropriateTransferType(bits * 4)); + } + + /** + * Constructs a ColorModel that translates pixel values to + * color/alpha components. + * + * @exception IllegalArgumentException If the length of the bit array is less + * than the number of color or alpha components in this ColorModel, or if the + * transparency is not a valid value, or if the sum of the number of bits in + * bits is less than 1 or if any of the elements in bits is less than 0. + */ + protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace, + boolean hasAlpha, boolean isAlphaPremultiplied, + int transparency, int transferType) + { + int bits_sum = 0; + for (int i = 0; i < bits.length; i++) + { + if (bits [i] < 0) + throw new IllegalArgumentException (); + + bits_sum |= bits [i]; + } + + if ((bits.length < cspace.getNumComponents()) + || (bits_sum < 1)) + throw new IllegalArgumentException (); + + this.pixel_bits = pixel_bits; + this.bits = bits; + this.cspace = cspace; + this.hasAlpha = hasAlpha; + this.isAlphaPremultiplied = isAlphaPremultiplied; + this.transparency = transparency; + this.transferType = transferType; + } + + // This is a hook for ColorConvertOp to create a colormodel with + // a new colorspace + ColorModel cloneColorModel(ColorSpace cspace) + { + Class cls = this.getClass(); + ColorModel cm; + try { + // This constructor will exist. + Constructor ctor = + cls.getConstructor(new Class[]{int.class, int[].class, + ColorSpace.class, boolean.class, + boolean.class, int.class, int.class}); + cm = (ColorModel)ctor. + newInstance(new Object[]{new Integer(pixel_bits), + bits, cspace, Boolean.valueOf(hasAlpha), + Boolean.valueOf(isAlphaPremultiplied), + new Integer(transparency), + new Integer(transferType)}); + } + catch (Exception e) + { + throw new IllegalArgumentException(); + } + return cm; + } + + public void finalize() + { + // Do nothing here. + } + + /** + * Returns the default color model which in Sun's case is an instance + * of <code>DirectColorModel</code>. + */ + public static ColorModel getRGBdefault() + { + return new DirectColorModel(32, 0xff0000, 0xff00, 0xff, 0xff000000); + } + + public final boolean hasAlpha() + { + return hasAlpha; + } + + public final boolean isAlphaPremultiplied() + { + return isAlphaPremultiplied; + } + + /** + * Get get number of bits wide used for the bit size of pixel values + */ + public int getPixelSize() + { + return pixel_bits; + } + + public int getComponentSize(int componentIdx) + { + return bits[componentIdx]; + } + + public int[] getComponentSize() + { + return bits; + } + + public int getTransparency() + { + return transparency; + } + + public int getNumComponents() + { + return getNumColorComponents() + (hasAlpha ? 1 : 0); + } + + public int getNumColorComponents() + { + return cspace.getNumComponents(); + } + + /** + * Converts pixel value to sRGB and extract red int sample scaled + * to range [0, 255]. + * + * @param pixel pixel value that will be interpreted according to + * the color model, (assumed alpha premultiplied if color model says + * so.) + * + * @return red sample scaled to range [0, 255], from default color + * space sRGB, alpha non-premultiplied. + */ + public abstract int getRed(int pixel); + + /** + * Converts pixel value to sRGB and extract green int sample + * scaled to range [0, 255]. + * + * @see #getRed(int) + */ + public abstract int getGreen(int pixel); + + /** + * Converts pixel value to sRGB and extract blue int sample + * scaled to range [0, 255]. + * + * @see #getRed(int) + */ + public abstract int getBlue(int pixel); + + /** + * Extract alpha int sample from pixel value, scaled to [0, 255]. + * + * @param pixel pixel value that will be interpreted according to + * the color model. + * + * @return alpha sample, scaled to range [0, 255]. + */ + public abstract int getAlpha(int pixel); + + /** + * Converts a pixel int value of the color space of the color + * model to a sRGB pixel int value. + * + * This method is typically overriden in subclasses to provide a + * more efficient implementation. + * + * @param pixel pixel value that will be interpreted according to + * the color model. + * + * @return a pixel in sRGB color space, encoded in default + * 0xAARRGGBB format. */ + public int getRGB(int pixel) + { + return + ((getAlpha(pixel) & 0xff) << 24) | + (( getRed(pixel) & 0xff) << 16) | + ((getGreen(pixel) & 0xff) << 8) | + (( getBlue(pixel) & 0xff) << 0); + } + + + /** + * In this color model we know that the whole pixel value will + * always be contained within the first element of the pixel + * array. + */ + final int getPixelFromArray(Object inData) { + DataBuffer data = + Buffers.createBufferFromData(transferType, inData, 1); + Object da = Buffers.getData(data); + + return data.getElem(0); + } + + /** + * Converts pixel in the given array to sRGB and extract blue int + * sample scaled to range [0-255]. + * + * This method is typically overriden in subclasses to provide a + * more efficient implementation. + * + * @param inData array of transferType containing a single pixel. The + * pixel should be encoded in the natural way of the color model. + */ + public int getRed(Object inData) + { + return getRed(getPixelFromArray(inData)); + } + + /** + * @see #getRed(Object) + */ + public int getGreen(Object inData) + { + return getGreen(getPixelFromArray(inData)); + } + + /** + * @see #getRed(Object) + */ + public int getBlue(Object inData) { + return getBlue(getPixelFromArray(inData)); + } + + /** + * @see #getRed(Object) + */ + public int getAlpha(Object inData) { + return getAlpha(getPixelFromArray(inData)); + } + + /** + * Converts a pixel in the given array of the color space of the + * color model to an sRGB pixel int value. + * + * <p>This method performs the inverse function of + * <code>getDataElements(int rgb, Object pixel)</code>. + * I.e. <code>(rgb == cm.getRGB(cm.getDataElements(rgb, + * null)))</code>. + * + * @param inData array of transferType containing a single pixel. The + * pixel should be encoded in the natural way of the color model. + * + * @return a pixel in sRGB color space, encoded in default + * 0xAARRGGBB format. + * + * @see #getDataElements(int, Object) + */ + public int getRGB(Object inData) + { + return + ((getAlpha(inData) & 0xff) << 24) | + (( getRed(inData) & 0xff) << 16) | + ((getGreen(inData) & 0xff) << 8) | + (( getBlue(inData) & 0xff) << 0); + } + + /** + * Converts an sRGB pixel int value to an array containing a + * single pixel of the color space of the color model. + * + * <p>This method performs the inverse function of + * <code>getRGB(Object inData)</code>. + * + * Outline of conversion process: + * + * <ol> + * + * <li>Convert rgb to normalized [0.0, 1.0] sRGB values.</li> + * + * <li>Convert to color space components using fromRGB in + * ColorSpace.</li> + * + * <li>If color model has alpha and should be premultiplied, + * multiply color space components with alpha value</li> + * + * <li>Scale the components to the correct number of bits.</li> + * + * <li>Arrange the components in the output array</li> + * + * </ol> + * + * @param rgb The color to be converted to dataElements. A pixel + * in sRGB color space, encoded in default 0xAARRGGBB format, + * assumed not alpha premultiplied. + * + * @param pixel to avoid needless creation of arrays, an array to + * use to return the pixel can be given. If null, a suitable array + * will be created. + * + * @return An array of transferType values representing the color, + * in the color model format. The color model defines whether the + * + * @see #getRGB(Object) + */ + public Object getDataElements(int rgb, Object pixel) + { + // subclasses has to implement this method. + throw new UnsupportedOperationException(); + } + + /** + * Fills an array with the unnormalized component samples from a + * pixel value. I.e. decompose the pixel, but not perform any + * color conversion. + * + * This method is typically overriden in subclasses to provide a + * more efficient implementation. + * + * @param pixel pixel value encoded according to the color model. + * + * @return arrays of unnormalized component samples of single + * pixel. The scale and multiplication state of the samples are + * according to the color model. Each component sample is stored + * as a separate element in the array. + */ + public int[] getComponents(int pixel, int[] components, int offset) + { + // subclasses has to implement this method. + throw new UnsupportedOperationException(); + } + + /** + * Fills an array with the unnormalized component samples from an + * array of transferType containing a single pixel. I.e. decompose + * the pixel, but not perform any color conversion. + * + * This method is typically overriden in subclasses to provide a + * more efficient implementation. + * + * @param array of transferType containing a single pixel. The + * pixel should be encoded in the natural way of the color model. + * + * @return arrays of unnormalized component samples of single + * pixel. The scale and multiplication state of the samples are + * according to the color model. Each component sample is stored + * as a separate element in the array. + */ + public int[] getComponents(Object pixel, int[] components, int offset) + { + // subclasses has to implement this method. + throw new UnsupportedOperationException(); + } + + /** + * Convert normalized components to unnormalized components. + */ + public int[] getUnnormalizedComponents(float[] normComponents, + int normOffset, + int[] components, + int offset) + { + int numComponents = getNumComponents(); + if (components == null) + { + components = new int[offset + numComponents]; + } + + for (int i=0; i<numComponents; i++) + { + float in = normComponents[normOffset++]; + int out = (int) (in * ((1<<getComponentSize(i)) - 1)); + components[offset++] = out; + } + return components; + } + + /** + * Convert unnormalized components to normalized components. + */ + public float[] getNormalizedComponents(int[] components, + int offset, + float[] normComponents, + int normOffset) + { + int numComponents = getNumComponents(); + if (normComponents == null) + { + normComponents = new float[normOffset + numComponents]; + } + + for (int i=0; i<numComponents; i++) + { + float in = components[offset++]; + float out = in / ((1<<getComponentSize(i)) - 1); + normComponents[normOffset++] = out; + } + return normComponents; + } + + /** + * Convert unnormalized components to normalized components. + * + * @since 1.4 + */ + public float[] getNormalizedComponents (Object pixel, + float[] normComponents, + int normOffset) + { + // subclasses has to implement this method. + throw new UnsupportedOperationException(); + } + + /** + * Converts the unnormalized component samples from an array to a + * pixel value. I.e. composes the pixel from component samples, but + * does not perform any color conversion or scaling of the samples. + * + * This method performs the inverse function of + * <code>getComponents(int pixel, int[] components, + * int offset)</code>. I.e. + * + * <code>(pixel == cm.getDataElement(cm.getComponents(pixel, null, + * 0), 0))</code>. + * + * This method is overriden in subclasses since this abstract class throws + * UnsupportedOperationException(). + * + * @param components Array of unnormalized component samples of single + * pixel. The scale and multiplication state of the samples are according + * to the color model. Each component sample is stored as a separate element + * in the array. + * @param offset Position of the first value of the pixel in components. + * + * @return pixel value encoded according to the color model. + */ + public int getDataElement(int[] components, int offset) + { + // subclasses have to implement this method. + throw new UnsupportedOperationException(); + } + + /** + * Converts the normalized component samples from an array to a pixel + * value. I.e. composes the pixel from component samples, but does not + * perform any color conversion or scaling of the samples. + * + * This method is typically overriden in subclasses to provide a + * more efficient implementation. The method provided by this abstract + * class converts the components to unnormalized form and returns + * getDataElement(int[], int). + * + * @param components Array of normalized component samples of single pixel. + * The scale and multiplication state of the samples are according to the + * color model. Each component sample is stored as a separate element in the + * array. + * @param offset Position of the first value of the pixel in components. + * + * @return pixel value encoded according to the color model. + * @since 1.4 + */ + public int getDataElement (float[] components, int offset) + { + return + getDataElement(getUnnormalizedComponents(components, offset, null, 0), + 0); + } + + public Object getDataElements(int[] components, int offset, Object obj) + { + // subclasses have to implement this method. + throw new UnsupportedOperationException(); + } + + /** + * Converts the normalized component samples from an array to an array of + * TransferType values. I.e. composes the pixel from component samples, but + * does not perform any color conversion or scaling of the samples. + * + * If obj is null, a new array of TransferType is allocated and returned. + * Otherwise the results are stored in obj and obj is returned. If obj is + * not long enough, ArrayIndexOutOfBounds is thrown. If obj is not an array + * of primitives, ClassCastException is thrown. + * + * This method is typically overriden in subclasses to provide a + * more efficient implementation. The method provided by this abstract + * class converts the components to unnormalized form and returns + * getDataElement(int[], int, Object). + * + * @param components Array of normalized component samples of single pixel. + * The scale and multiplication state of the samples are according to the + * color model. Each component sample is stored as a separate element in the + * array. + * @param offset Position of the first value of the pixel in components. + * @param obj Array of TransferType or null. + * + * @return pixel value encoded according to the color model. + * @throws ArrayIndexOutOfBounds + * @throws ClassCastException + * @since 1.4 + */ + public Object getDataElements(float[] components, int offset, Object obj) + { + return + getDataElements(getUnnormalizedComponents(components, offset, null, 0), + 0, obj); + } + + public boolean equals(Object obj) + { + if (!(obj instanceof ColorModel)) return false; + + ColorModel o = (ColorModel) obj; + return + (pixel_bits == o.pixel_bits) && + (transferType == o.transferType) && + (transparency == o.transparency) && + (hasAlpha == o.hasAlpha) && + (isAlphaPremultiplied == o.isAlphaPremultiplied) && + Arrays.equals(bits, o.bits) && + (cspace.equals(o.cspace)); + } + + public final ColorSpace getColorSpace() + { + return cspace; + } + + // Typically overridden + public ColorModel coerceData(WritableRaster raster, + boolean isAlphaPremultiplied) + { + if (this.isAlphaPremultiplied == isAlphaPremultiplied) + return this; + + int w = raster.getWidth(); + int h = raster.getHeight(); + int x = raster.getMinX(); + int y = raster.getMinY(); + int size = w*h; + int numColors = getNumColorComponents(); + int numComponents = getNumComponents(); + int alphaScale = (1<<getComponentSize(numColors)) - 1; + double[] pixels = raster.getPixels(x, y, w, h, (double[]) null); + + for (int i=0; i<size; i++) + { + double alpha = pixels[i*numComponents+numColors]*alphaScale; + for (int c=0; c<numColors; c++) + { + int offset = i*numComponents+c; + if (isAlphaPremultiplied) + pixels[offset] = pixels[offset]/alpha; + else + pixels[offset] = pixels[offset]*alpha; + } + } + + raster.setPixels(0, 0, w, h, pixels); + + // FIXME: what can we return? + return null; + } + + /** + * Checks if the given raster has a compatible data-layout (SampleModel). + * @param raster The Raster to test. + * @return true if raster is compatible. + */ + public boolean isCompatibleRaster(Raster raster) + { + SampleModel sampleModel = raster.getSampleModel(); + return isCompatibleSampleModel(sampleModel); + } + + // Typically overridden + public WritableRaster createCompatibleWritableRaster(int w, int h) + { + return new WritableRaster(createCompatibleSampleModel(w, h), + new Point(0, 0)); + } + + // Typically overridden + public SampleModel createCompatibleSampleModel(int w, int h) + { + throw new UnsupportedOperationException(); + } + + // Typically overridden + public boolean isCompatibleSampleModel(SampleModel sm) + { + return sm.getTransferType() == transferType; + } + + public final int getTransferType () + { + return transferType; + } + + /** + * Subclasses must override this method if it is possible for the + * color model to have an alpha channel. + * + * @return null, as per JDK 1.3 doc. Subclasses will only return + * null if no alpha raster exists. + */ + public WritableRaster getAlphaRaster(WritableRaster raster) + { + return null; + + /* It is a mystery to me why we couldn't use the following code... + + + if (!hasAlpha()) return null; + + SampleModel sm = raster.getSampleModel(); + int[] alphaBand = { sm.getNumBands() - 1 }; + SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand); + DataBuffer buffer = raster.getDataBuffer(); + Point origin = new Point(0, 0); + return Raster.createWritableRaster(alphaModel, buffer, origin); + + + ...here, and avoided overriding the method in subclasses, + but the Sun docs state that this method always will return + null, and that overriding is required. Oh, well. + */ + } + + String stringParam() + { + return "pixel_bits=" + pixel_bits + + ", cspace=" + cspace + + ", transferType=" + transferType + + ", transparency=" + transparency + + ", hasAlpha=" + hasAlpha + + ", isAlphaPremultiplied=" + isAlphaPremultiplied; + } + + public String toString() + { + return getClass().getName() + "[" + stringParam() + "]"; + } +} diff --git a/libjava/classpath/java/awt/image/ComponentColorModel.java b/libjava/classpath/java/awt/image/ComponentColorModel.java new file mode 100644 index 0000000..f56688f --- /dev/null +++ b/libjava/classpath/java/awt/image/ComponentColorModel.java @@ -0,0 +1,391 @@ +/* ComponentColorModel.java -- + Copyright (C) 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import gnu.java.awt.Buffers; + +import java.awt.Point; +import java.awt.color.ColorSpace; + +public class ComponentColorModel extends ColorModel +{ + private static int sum(int[] values) + { + int sum = 0; + for (int i=0; i<values.length; i++) + sum += values[i]; + return sum; + } + + public ComponentColorModel(ColorSpace colorSpace, int[] bits, + boolean hasAlpha, + boolean isAlphaPremultiplied, + int transparency, int transferType) + { + super(sum(bits), bits, colorSpace, hasAlpha, isAlphaPremultiplied, + transparency, transferType); + } + + /** + * Construct a new ComponentColorModel. + * + * This constructor makes all bits of each sample significant, so for a + * transferType of DataBuffer.BYTE, the bits per sample is 8, etc. If + * both hasAlpha and isAlphaPremultiplied are true, color samples are + * assumed to be premultiplied by the alpha component. Transparency may be + * one of OPAQUE, BITMASK, or TRANSLUCENT. + * + * @param colorSpace The colorspace for this color model. + * @param hasAlpha True if there is an alpha component. + * @param isAlphaPremultiplied True if colors are already multiplied by + * alpha. + * @param transparency The type of alpha values. + * @param transferType Data type of pixel sample values. + * @since 1.4 + */ + public ComponentColorModel(ColorSpace colorSpace, + boolean hasAlpha, + boolean isAlphaPremultiplied, + int transparency, int transferType) + { + this(colorSpace, null, hasAlpha, isAlphaPremultiplied, + transparency, transferType); + } + + public int getRed(int pixel) + { + if (getNumComponents()>1) throw new IllegalArgumentException(); + return (int) getRGBFloat(pixel)[0]; + } + + public int getGreen(int pixel) + { + if (getNumComponents()>1) throw new IllegalArgumentException(); + return (int) getRGBFloat(pixel)[0]; + } + + public int getBlue(int pixel) + { + if (getNumComponents()>1) throw new IllegalArgumentException(); + return (int) getRGBFloat(pixel)[0]; + } + + public int getAlpha(int pixel) + { + if (getNumComponents()>1) throw new IllegalArgumentException(); + int shift = 8 - getComponentSize(getNumColorComponents()); + if (shift >= 0) return pixel << shift; + return pixel >> (-shift); + } + + public int getRGB(int pixel) + { + float[] rgb = getRGBFloat(pixel); + int ret = getRGB(rgb); + if (hasAlpha()) ret |= getAlpha(pixel) << 24; + return ret; + } + + + /* Note, it's OK to pass a to large array to toRGB(). Extra + elements are ignored. */ + + private float[] getRGBFloat(int pixel) + { + float[] data = { pixel }; + return cspace.toRGB(data); + } + + private float[] getRGBFloat(Object inData) + { + DataBuffer buffer = + Buffers.createBufferFromData(transferType, inData, + getNumComponents()); + int colors = getNumColorComponents(); + float[] data = new float[colors]; + + // FIXME: unpremultiply data that is premultiplied + for (int i=0; i<colors; i++) + { + float maxValue = (1<<getComponentSize(i))-1; + data[i] = buffer.getElemFloat(i)/maxValue; + } + float[] rgb = cspace.toRGB(data); + return rgb; + } + + public int getRed(Object inData) + { + return (int) getRGBFloat(inData)[0]*255; + } + + public int getGreen(Object inData) + { + return (int) getRGBFloat(inData)[1]*255; + } + + public int getBlue(Object inData) + { + return (int) getRGBFloat(inData)[2]*255; + } + + public int getAlpha(Object inData) + { + DataBuffer buffer = + Buffers.createBufferFromData(transferType, inData, + getNumComponents()); + int shift = 8 - getComponentSize(getNumColorComponents()); + int alpha = buffer.getElem(getNumColorComponents()); + if (shift >= 0) return alpha << shift; + return alpha >> (-shift); + } + + private int getRGB(float[] rgb) + { + /* NOTE: We could cast to byte instead of int here. This would + avoid bits spilling over from one bit field to + another. But, if we assume that floats are in the [0.0, + 1.0] range, this will never happen anyway. */ + + /* Remember to multiply BEFORE casting to int, otherwise, decimal + point data will be lost. */ + int ret = + (((int) (rgb[0]*255F)) << 16) | + (((int) (rgb[1]*255F)) << 8) | + (((int) (rgb[2]*255F)) << 0); + return ret; + } + + /** + * @param inData pixel data of transferType, as returned by the + * getDataElements method in SampleModel. + */ + public int getRGB(Object inData) + { + float[] rgb = getRGBFloat(inData); + int ret = getRGB(rgb); + if (hasAlpha()) ret |= getAlpha(inData) << 24; + return ret; + } + + public Object getDataElements(int rgb, Object pixel) + { + // Convert rgb to [0.0, 1.0] sRGB values. + float[] rgbFloats = { + ((rgb >> 16)&0xff)/255.0F, + ((rgb >> 8)&0xff)/255.0F, + ((rgb >> 0)&0xff)/255.0F + }; + + // Convert from rgb to color space components. + float[] data = cspace.fromRGB(rgbFloats); + DataBuffer buffer = Buffers.createBuffer(transferType, pixel, + getNumComponents()); + int numColors = getNumColorComponents(); + + if (hasAlpha()) + { + float alpha = ((rgb >> 24)&0xff)/255.0F; + + /* If color model has alpha and should be premultiplied, multiply + color space components with alpha value. */ + if (isAlphaPremultiplied()) { + for (int i=0; i<numColors; i++) + data[i] *= alpha; + } + // Scale the alpha sample to the correct number of bits. + alpha *= (1<<(bits[numColors]-1)); + // Arrange the alpha sample in the output array. + buffer.setElemFloat(numColors, alpha); + } + for (int i=0; i<numColors; i++) + { + // Scale the color samples to the correct number of bits. + float value = data[i]*(1<<(bits[i]-1)); + // Arrange the color samples in the output array. + buffer.setElemFloat(i, value); + } + return Buffers.getData(buffer); + } + + public int[] getComponents(int pixel, int[] components, int offset) + { + if (getNumComponents()>1) throw new IllegalArgumentException(); + if (components == null) + components = new int[getNumComponents() + offset]; + components[offset] = pixel; + return components; + } + + public int[] getComponents(Object pixel, int[] components, int offset) + { + DataBuffer buffer = Buffers.createBuffer(transferType, pixel, + getNumComponents()); + int numComponents = getNumComponents(); + + if (components == null) + components = new int[numComponents + offset]; + + for (int i=0; i<numComponents; i++) + components[offset++] = buffer.getElem(i); + + return components; + } + + public int getDataElement(int[] components, int offset) + { + if (getNumComponents()>1) throw new IllegalArgumentException(); + return components[offset]; + } + + public Object getDataElements(int[] components, int offset, Object obj) + { + DataBuffer buffer = Buffers.createBuffer(transferType, obj, + getNumComponents()); + int numComponents = getNumComponents(); + + for (int i=0; i<numComponents; i++) + buffer.setElem(i, components[offset++]); + + return Buffers.getData(buffer); + } + + public ColorModel coerceData(WritableRaster raster, + boolean isAlphaPremultiplied) { + if (this.isAlphaPremultiplied == isAlphaPremultiplied) + return this; + + /* TODO: provide better implementation based on the + assumptions we can make due to the specific type of the + color model. */ + super.coerceData(raster, isAlphaPremultiplied); + + return new ComponentColorModel(cspace, bits, hasAlpha(), + isAlphaPremultiplied, // argument + transparency, transferType); + } + + public boolean isCompatibleRaster(Raster raster) + { + return super.isCompatibleRaster(raster); + // FIXME: Should we test something more here? (Why override?) + } + + public WritableRaster createCompatibleWritableRaster(int w, int h) + { + SampleModel sm = createCompatibleSampleModel(w, h); + Point origin = new Point(0, 0); + return Raster.createWritableRaster(sm, origin); + } + + + /** + * Creates a <code>SampleModel</code> whose arrangement of pixel + * data is compatible to this <code>ColorModel</code>. + * + * @param w the number of pixels in the horizontal direction. + * @param h the number of pixels in the vertical direction. + */ + public SampleModel createCompatibleSampleModel(int w, int h) + { + int pixelStride, scanlineStride; + int[] bandOffsets; + + pixelStride = getNumComponents(); + scanlineStride = pixelStride * w; + + /* We might be able to re-use the same bandOffsets array among + * multiple calls to this method. However, this optimization does + * not seem worthwile because setting up descriptive data + * structures (such as SampleModels) is neglectible in comparision + * to shuffling around masses of pixel data. + */ + bandOffsets = new int[pixelStride]; + for (int i = 0; i < pixelStride; i++) + bandOffsets[i] = i; + + /* FIXME: Think about whether it would make sense to return the + * possibly more efficient PixelInterleavedSampleModel for other + * transferTypes as well. It seems unlikely that this would break + * any user applications, so the Mauve tests on this method + * might be too restrictive. + */ + switch (transferType) + { + case DataBuffer.TYPE_BYTE: + case DataBuffer.TYPE_USHORT: + return new PixelInterleavedSampleModel(transferType, w, h, + pixelStride, + scanlineStride, + bandOffsets); + + default: + return new ComponentSampleModel(transferType, w, h, + pixelStride, + scanlineStride, + bandOffsets); + } + } + + + public boolean isCompatibleSampleModel(SampleModel sm) + { + return + (sm instanceof ComponentSampleModel) && + super.isCompatibleSampleModel(sm); + } + + public WritableRaster getAlphaRaster(WritableRaster raster) + { + if (!hasAlpha()) return null; + + SampleModel sm = raster.getSampleModel(); + int[] alphaBand = { sm.getNumBands() - 1 }; + SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand); + DataBuffer buffer = raster.getDataBuffer(); + Point origin = new Point(0, 0); + return Raster.createWritableRaster(alphaModel, buffer, origin); + } + + public boolean equals(Object obj) + { + if (!(obj instanceof ComponentColorModel)) return false; + return super.equals(obj); + } +} diff --git a/libjava/classpath/java/awt/image/ComponentSampleModel.java b/libjava/classpath/java/awt/image/ComponentSampleModel.java new file mode 100644 index 0000000..953f63c --- /dev/null +++ b/libjava/classpath/java/awt/image/ComponentSampleModel.java @@ -0,0 +1,544 @@ +/* Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +import gnu.java.awt.Buffers; + +/* FIXME: This class does not yet support data type TYPE_SHORT */ + +/** + * ComponentSampleModel supports a flexible organization of pixel samples in + * memory, permitting pixel samples to be interleaved by band, by scanline, + * and by pixel. + * + * A DataBuffer for this sample model has K banks of data. Pixels have N + * samples, so there are N bands in the DataBuffer. Each band is completely + * contained in one bank of data, but a bank may contain more than one band. + * Each pixel sample is stored in a single data element. + * + * Within a bank, each band begins at an offset stored in bandOffsets. The + * banks containing the band is given by bankIndices. Within the bank, there + * are three dimensions - band, pixel, and scanline. The dimension ordering + * is controlled by bandOffset, pixelStride, and scanlineStride, which means + * that any combination of interleavings is supported. + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public class ComponentSampleModel extends SampleModel +{ + protected int[] bandOffsets; + protected int[] bankIndices; + + // FIXME: Should we really shadow the numBands in the superclass? + //protected int numBands; + + /** Used when creating data buffers. */ + protected int numBanks; + + protected int scanlineStride; + + protected int pixelStride; + + private boolean tightPixelPacking = false; + + public ComponentSampleModel(int dataType, + int w, int h, + int pixelStride, + int scanlineStride, + int[] bandOffsets) + { + this(dataType, w, h, pixelStride, scanlineStride, + new int[bandOffsets.length], bandOffsets); + } + + public ComponentSampleModel(int dataType, + int w, int h, + int pixelStride, + int scanlineStride, + int[] bankIndices, + int[] bandOffsets) + { + super(dataType, w, h, bandOffsets.length); + if ((pixelStride<0) || (scanlineStride<0) || + (bandOffsets.length<1) || + (bandOffsets.length != bankIndices.length)) + throw new IllegalArgumentException(); + + this.bandOffsets = bandOffsets; + this.bankIndices = bankIndices; + + this.numBanks = 0; + for (int b=0; b<bankIndices.length; b++) + this.numBanks = Math.max(this.numBanks, bankIndices[b]+1); + + this.scanlineStride = scanlineStride; + this.pixelStride = pixelStride; + + // See if we can use some speedups + + /* FIXME: May these checks should be reserved for the + PixelInterleavedSampleModel? */ + + if (pixelStride == numBands) + { + tightPixelPacking = true; + for (int b=0; b<numBands; b++) { + if ((bandOffsets[b] != b) || (bankIndices[b] !=0)) + { + tightPixelPacking = false; + break; + } + } + } + } + + public SampleModel createCompatibleSampleModel(int w, int h) + { + return new ComponentSampleModel(dataType, w, h, pixelStride, + scanlineStride, bankIndices, + bandOffsets); + } + + public SampleModel createSubsetSampleModel(int[] bands) + { + int numBands = bands.length; + + int[] bankIndices = new int[numBands]; + int[] bandOffsets = new int[numBands]; + for (int b=0; b<numBands; b++) + { + bankIndices[b] = this.bankIndices[bands[b]]; + bandOffsets[b] = this.bandOffsets[bands[b]]; + } + + return new ComponentSampleModel(dataType, width, height, pixelStride, + scanlineStride, bankIndices, + bandOffsets); + } + + public DataBuffer createDataBuffer() + { + // Maybe this value should be precalculated in the constructor? + int highestOffset = 0; + for (int b=0; b<numBands; b++) + { + highestOffset = Math.max(highestOffset, bandOffsets[b]); + } + int size = pixelStride*(width-1) + scanlineStride*(height-1) + + highestOffset + 1; + + return Buffers.createBuffer(getDataType(), size, numBanks); + } + + public int getOffset(int x, int y) + { + return getOffset(x, y, 0); + } + + public int getOffset(int x, int y, int b) + { + return bandOffsets[b] + pixelStride*x + scanlineStride*y; + } + + public final int[] getSampleSize() + { + int size = DataBuffer.getDataTypeSize(getDataType()); + int[] sizes = new int[numBands]; + + java.util.Arrays.fill(sizes, size); + return sizes; + } + + public final int getSampleSize(int band) + { + return DataBuffer.getDataTypeSize(getDataType()); + } + + public final int[] getBankIndices() + { + return bankIndices; + } + + public final int[] getBandOffsets() + { + return bandOffsets; + } + + public final int getScanlineStride() + { + return scanlineStride; + } + + public final int getPixelStride() + { + return pixelStride; + } + + public final int getNumDataElements() + { + return numBands; + } + + public Object getDataElements(int x, int y, Object obj, DataBuffer data) + { + int xyOffset = pixelStride*x + scanlineStride*y; + + int[] totalBandDataOffsets = new int[numBands]; + + /* Notice that band and bank offsets are different. Band offsets + are managed by the sample model, and bank offsets are managed + by the data buffer. Both must be accounted for. */ + + /* FIXME: For single pixels, it is probably easier to simple + call getElem instead of calculating the bank offset ourself. + + On the other hand, then we need to push the value through + the int type returned by the getElem method. */ + + int[] bankOffsets = data.getOffsets(); + + for (int b=0; b<numBands; b++) + { + totalBandDataOffsets[b] = + bandOffsets[b]+bankOffsets[bankIndices[b]] + xyOffset; + } + + try + { + switch (getTransferType()) + { + case DataBuffer.TYPE_BYTE: + DataBufferByte inByte = (DataBufferByte) data; + byte[] outByte = (byte[]) obj; + if (outByte == null) outByte = new byte[numBands]; + + for (int b=0; b<numBands; b++) + { + int dOffset = totalBandDataOffsets[b]; + outByte[b] = inByte.getData(bankIndices[b])[dOffset]; + } + return outByte; + + case DataBuffer.TYPE_USHORT: + DataBufferUShort inUShort = (DataBufferUShort) data; + short[] outUShort = (short[]) obj; + if (outUShort == null) outUShort = new short[numBands]; + + for (int b=0; b<numBands; b++) + { + int dOffset = totalBandDataOffsets[b]; + outUShort[b] = inUShort.getData(bankIndices[b])[dOffset]; + } + return outUShort; + + case DataBuffer.TYPE_SHORT: + DataBufferShort inShort = (DataBufferShort) data; + short[] outShort = (short[]) obj; + if (outShort == null) outShort = new short[numBands]; + + for (int b=0; b<numBands; b++) + { + int dOffset = totalBandDataOffsets[b]; + outShort[b] = inShort.getData(bankIndices[b])[dOffset]; + } + return outShort; + + case DataBuffer.TYPE_INT: + DataBufferInt inInt = (DataBufferInt) data; + int[] outInt = (int[]) obj; + if (outInt == null) outInt = new int[numBands]; + + for (int b=0; b<numBands; b++) + { + int dOffset = totalBandDataOffsets[b]; + outInt[b] = inInt.getData(bankIndices[b])[dOffset]; + } + return outInt; + + case DataBuffer.TYPE_FLOAT: + DataBufferFloat inFloat = (DataBufferFloat) data; + float[] outFloat = (float[]) obj; + if (outFloat == null) outFloat = new float[numBands]; + + for (int b=0; b<numBands; b++) + { + int dOffset = totalBandDataOffsets[b]; + outFloat[b] = inFloat.getData(bankIndices[b])[dOffset]; + } + return outFloat; + + case DataBuffer.TYPE_DOUBLE: + DataBufferDouble inDouble = (DataBufferDouble) data; + double[] outDouble = (double[]) obj; + if (outDouble == null) outDouble = new double[numBands]; + + for (int b=0; b<numBands; b++) + { + int dOffset = totalBandDataOffsets[b]; + outDouble[b] = inDouble.getData(bankIndices[b])[dOffset]; + } + return outDouble; + + default: + throw new IllegalStateException("unknown transfer type " + + getTransferType()); + } + } + catch (ArrayIndexOutOfBoundsException aioobe) + { + String msg = "While reading data elements, " + + "x=" + x + ", y=" + y +", " + ", xyOffset=" + xyOffset + + ", data.getSize()=" + data.getSize() + ": " + aioobe; + throw new ArrayIndexOutOfBoundsException(msg); + } + } + + public Object getDataElements(int x, int y, int w, int h, Object obj, + DataBuffer data) + { + if (!tightPixelPacking) + { + return super.getDataElements(x, y, w, h, obj, data); + } + + // using get speedup + + // We can copy whole rows + int rowSize = w*numBands; + int dataSize = rowSize*h; + + DataBuffer transferBuffer = + Buffers.createBuffer(getTransferType(), obj, dataSize); + obj = Buffers.getData(transferBuffer); + + int inOffset = + pixelStride*x + + scanlineStride*y + + data.getOffset(); // Assumes only one band is used + + /* We don't add band offsets since we assume that bands have + offsets 0, 1, 2, ... */ + + // See if we can copy everything in one go + if (scanlineStride == rowSize) + { + // Collapse scan lines: + rowSize *= h; + // We ignore scanlineStride since it won't be of any use + h = 1; + } + + int outOffset = 0; + Object inArray = Buffers.getData(data); + for (int yd = 0; yd<h; yd++) + { + System.arraycopy(inArray, inOffset, obj, outOffset, rowSize); + inOffset += scanlineStride; + outOffset += rowSize; + } + return obj; + } + + public void setDataElements(int x, int y, int w, int h, + Object obj, DataBuffer data) + { + if (!tightPixelPacking) + { + super.setDataElements(x, y, w, h, obj, data); + return; + } + + // using set speedup, we can copy whole rows + int rowSize = w*numBands; + int dataSize = rowSize*h; + + DataBuffer transferBuffer = + Buffers.createBufferFromData(getTransferType(), obj, dataSize); + + int[] bankOffsets = data.getOffsets(); + + int outOffset = + pixelStride*x + + scanlineStride*y + + bankOffsets[0]; // same assuptions as in get... + + // See if we can copy everything in one go + if (scanlineStride == rowSize) + { + // Collapse scan lines: + rowSize *= h; + h = 1; + } + + int inOffset = 0; + Object outArray = Buffers.getData(data); + for (int yd = 0; yd<h; yd++) + { + System.arraycopy(obj, inOffset, outArray, outOffset, rowSize); + outOffset += scanlineStride; + inOffset += rowSize; + } + } + + public int[] getPixel(int x, int y, int[] iArray, DataBuffer data) + { + int offset = pixelStride*x + scanlineStride*y; + if (iArray == null) iArray = new int[numBands]; + for (int b=0; b<numBands; b++) + { + iArray[b] = data.getElem(bankIndices[b], offset+bandOffsets[b]); + } + return iArray; + } + + public int[] getPixels(int x, int y, int w, int h, int[] iArray, + DataBuffer data) + { + int offset = pixelStride*x + scanlineStride*y; + if (iArray == null) iArray = new int[numBands*w*h]; + int outOffset = 0; + for (y=0; y<h; y++) + { + int lineOffset = offset; + for (x=0; x<w; x++) + { + for (int b=0; b<numBands; b++) + { + iArray[outOffset++] = + data.getElem(bankIndices[b], lineOffset+bandOffsets[b]); + } + lineOffset += pixelStride; + } + offset += scanlineStride; + } + return iArray; + } + + public int getSample(int x, int y, int b, DataBuffer data) + { + return data.getElem(bankIndices[b], getOffset(x, y, b)); + } + + public void setDataElements(int x, int y, Object obj, DataBuffer data) + { + int offset = pixelStride*x + scanlineStride*y; + int[] totalBandDataOffsets = new int[numBands]; + int[] bankOffsets = data.getOffsets(); + for (int b=0; b<numBands; b++) + totalBandDataOffsets[b] = + bandOffsets[b]+bankOffsets[bankIndices[b]] + offset; + + switch (getTransferType()) + { + case DataBuffer.TYPE_BYTE: + { + DataBufferByte out = (DataBufferByte) data; + byte[] in = (byte[]) obj; + + for (int b=0; b<numBands; b++) + out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b]; + + return; + } + case DataBuffer.TYPE_USHORT: + { + DataBufferUShort out = (DataBufferUShort) data; + short[] in = (short[]) obj; + + for (int b=0; b<numBands; b++) + out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b]; + + return; + } + case DataBuffer.TYPE_SHORT: + { + DataBufferShort out = (DataBufferShort) data; + short[] in = (short[]) obj; + + for (int b=0; b<numBands; b++) + out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b]; + + return; + } + case DataBuffer.TYPE_INT: + { + DataBufferInt out = (DataBufferInt) data; + int[] in = (int[]) obj; + + for (int b=0; b<numBands; b++) + out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b]; + + return; + } + case DataBuffer.TYPE_FLOAT: + { + DataBufferFloat out = (DataBufferFloat) data; + float[] in = (float[]) obj; + + for (int b=0; b<numBands; b++) + out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b]; + + return; + } + case DataBuffer.TYPE_DOUBLE: + { + DataBufferDouble out = (DataBufferDouble) data; + double[] in = (double[]) obj; + + for (int b=0; b<numBands; b++) + out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b]; + + return; + } + default: + throw new UnsupportedOperationException("transfer type not " + + "implemented"); + } + } + + public void setPixel(int x, int y, int[] iArray, DataBuffer data) + { + int offset = pixelStride*x + scanlineStride*y; + for (int b=0; b<numBands; b++) + data.setElem(bankIndices[b], offset+bandOffsets[b], iArray[b]); + } + + public void setSample(int x, int y, int b, int s, DataBuffer data) + { + data.setElem(bankIndices[b], getOffset(x, y, b), s); + } +} diff --git a/libjava/classpath/java/awt/image/ConvolveOp.java b/libjava/classpath/java/awt/image/ConvolveOp.java new file mode 100644 index 0000000..f841c13 --- /dev/null +++ b/libjava/classpath/java/awt/image/ConvolveOp.java @@ -0,0 +1,337 @@ +/* ConvolveOp.java -- + Copyright (C) 2004 Free Software Foundation -- ConvolveOp + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Arrays; + +/** + * Convolution filter. + * + * ConvolveOp convolves the source image with a Kernel to generate a + * destination image. This involves multiplying each pixel and its neighbors + * with elements in the kernel to compute a new pixel. + * + * Each band in a Raster is convolved and copied to the destination Raster. + * + * For BufferedImages, convolution is applied to all components. If the + * source is not premultiplied, the data will be premultiplied before + * convolving. Premultiplication will be undone if the destination is not + * premultiplied. Color conversion will be applied if needed. + * + * @author jlquinn@optonline.net + */ +public class ConvolveOp implements BufferedImageOp, RasterOp +{ + /** Edge pixels are set to 0. */ + public static final int EDGE_ZERO_FILL = 0; + + /** Edge pixels are copied from the source. */ + public static final int EDGE_NO_OP = 1; + + private Kernel kernel; + private int edge; + private RenderingHints hints; + + /** + * Construct a ConvolveOp. + * + * The edge condition specifies that pixels outside the area that can be + * filtered are either set to 0 or copied from the source image. + * + * @param kernel The kernel to convolve with. + * @param edgeCondition Either EDGE_ZERO_FILL or EDGE_NO_OP. + * @param hints Rendering hints for color conversion, or null. + */ + public ConvolveOp(Kernel kernel, + int edgeCondition, + RenderingHints hints) + { + this.kernel = kernel; + edge = edgeCondition; + this.hints = hints; + } + + /** + * Construct a ConvolveOp. + * + * The edge condition defaults to EDGE_ZERO_FILL. + * + * @param kernel The kernel to convolve with. + */ + public ConvolveOp(Kernel kernel) + { + this.kernel = kernel; + edge = EDGE_ZERO_FILL; + hints = null; + } + + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, + * java.awt.image.BufferedImage) + */ + public BufferedImage filter(BufferedImage src, BufferedImage dst) + { + if (src == dst) + throw new IllegalArgumentException(); + + if (dst == null) + dst = createCompatibleDestImage(src, src.getColorModel()); + + // Make sure source image is premultiplied + BufferedImage src1 = src; + if (!src.isPremultiplied) + { + src1 = createCompatibleDestImage(src, src.getColorModel()); + src.copyData(src1.getRaster()); + src1.coerceData(true); + } + + BufferedImage dst1 = dst; + if (!src.getColorModel().equals(dst.getColorModel())) + dst1 = createCompatibleDestImage(src, src.getColorModel()); + + filter(src1.getRaster(), dst1.getRaster()); + + if (dst1 != dst) + { + // Convert between color models. + // TODO Check that premultiplied alpha is handled correctly here. + Graphics2D gg = dst.createGraphics(); + gg.setRenderingHints(hints); + gg.drawImage(dst1, 0, 0, null); + gg.dispose(); + } + + return dst; + } + + /* (non-Javadoc) + * @see + * java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, + * java.awt.image.ColorModel) + */ + public BufferedImage createCompatibleDestImage(BufferedImage src, + ColorModel dstCM) + { + // FIXME: set properties to those in src + return new BufferedImage(dstCM, + src.getRaster().createCompatibleWritableRaster(), + src.isPremultiplied, null); + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getRenderingHints() + */ + public RenderingHints getRenderingHints() + { + return hints; + } + + /** + * @return The edge condition. + */ + public int getEdgeCondition() + { + return edge; + } + + /** + * @return The convolution kernel. + */ + public Kernel getKernel() + { + return kernel; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, + * java.awt.image.WritableRaster) + */ + public WritableRaster filter(Raster src, WritableRaster dest) { + if (src.numBands != dest.numBands) + throw new ImagingOpException(null); + if (src == dest) + throw new IllegalArgumentException(); + if (src.getWidth() < kernel.getWidth() || + src.getHeight() < kernel.getHeight()) + throw new ImagingOpException(null); + + if (dest == null) + dest = createCompatibleDestRaster(src); + + // Deal with bottom edge + if (edge == EDGE_ZERO_FILL) + { + float[] zeros = new float[src.getNumBands() * src.getWidth() + * (kernel.getYOrigin() - 1)]; + Arrays.fill(zeros, 0); + dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(), + kernel.getYOrigin() - 1, zeros); + } + else + { + float[] vals = new float[src.getNumBands() * src.getWidth() + * (kernel.getYOrigin() - 1)]; + src.getPixels(src.getMinX(), src.getMinY(), src.getWidth(), + kernel.getYOrigin() - 1, vals); + dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(), + kernel.getYOrigin() - 1, vals); + } + + // Handle main section + float[] kvals = kernel.getKernelData(null); + + float[] tmp = new float[kernel.getWidth() * kernel.getHeight()]; + for (int y = src.getMinY() + kernel.getYOrigin(); + y < src.getMinY() + src.getHeight() - kernel.getYOrigin() / 2; y++) + { + // Handle unfiltered edge pixels at start of line + float[] t1 = new float[(kernel.getXOrigin() - 1) * src.getNumBands()]; + if (edge == EDGE_ZERO_FILL) + Arrays.fill(t1, 0); + else + src.getPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1); + dest.setPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1); + + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + { + // FIXME: This needs a much more efficient implementation + for (int b = 0; b < src.getNumBands(); b++) + { + float v = 0; + src.getSamples(x, y, kernel.getWidth(), kernel.getHeight(), b, tmp); + for (int i=0; i < tmp.length; i++) + v += tmp[i] * kvals[i]; + dest.setSample(x, y, b, v); + } + } + + // Handle unfiltered edge pixels at end of line + float[] t2 = new float[(kernel.getWidth() / 2) * src.getNumBands()]; + if (edge == EDGE_ZERO_FILL) + Arrays.fill(t2, 0); + else + src.getPixels(src.getMinX() + src.getWidth() + - (kernel.getWidth() / 2), + y, kernel.getWidth() / 2, 1, t2); + dest.setPixels(src.getMinX() + src.getWidth() - (kernel.getWidth() / 2), + y, kernel.getWidth() / 2, 1, t2); + } + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++) + { + + } + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++) + { + + } + + // Handle top edge + if (edge == EDGE_ZERO_FILL) + { + float[] zeros = new float[src.getNumBands() * src.getWidth() * + (kernel.getHeight() / 2)]; + Arrays.fill(zeros, 0); + dest.setPixels(src.getMinX(), + src.getHeight() + src.getMinY() - (kernel.getHeight() / 2), + src.getWidth(), kernel.getHeight() / 2, zeros); + } + else + { + float[] vals = new float[src.getNumBands() * src.getWidth() * + (kernel.getHeight() / 2)]; + src.getPixels(src.getMinX(), + src.getHeight() + src.getMinY() + - (kernel.getHeight() / 2), + src.getWidth(), kernel.getHeight() / 2, vals); + dest.setPixels(src.getMinX(), + src.getHeight() + src.getMinY() + - (kernel.getHeight() / 2), + src.getWidth(), kernel.getHeight() / 2, vals); + } + + return dest; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster) + */ + public WritableRaster createCompatibleDestRaster(Raster src) + { + return src.createCompatibleWritableRaster(); + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage) + */ + public Rectangle2D getBounds2D(BufferedImage src) + { + return src.getRaster().getBounds(); + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster) + */ + public Rectangle2D getBounds2D(Raster src) + { + return src.getBounds(); + } + + /** Return corresponding destination point for source point. + * + * ConvolveOp will return the value of src unchanged. + * @param src The source point. + * @param dst The destination point. + * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, + * java.awt.geom.Point2D) + */ + public Point2D getPoint2D(Point2D src, Point2D dst) + { + if (dst == null) return (Point2D)src.clone(); + dst.setLocation(src); + return dst; + } +} diff --git a/libjava/classpath/java/awt/image/CropImageFilter.java b/libjava/classpath/java/awt/image/CropImageFilter.java new file mode 100644 index 0000000..490f43c --- /dev/null +++ b/libjava/classpath/java/awt/image/CropImageFilter.java @@ -0,0 +1,180 @@ +/* CropImageFilter.java -- Java class for cropping image filter + Copyright (C) 1999, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.Rectangle; +import java.util.Hashtable; + +/** + * Currently this filter does almost nothing and needs to be implemented. + * + * @author C. Brian Jones (cbj@gnu.org) + */ +public class CropImageFilter extends ImageFilter +{ + int x; + int y; + int width; + int height; + + /** + * Construct a new <code>CropImageFilter</code> instance. + * + * @param x the x-coordinate location of the top-left of the cropped rectangle + * @param y the y-coordinate location of the top-left of the cropped rectangle + * @param width the width of the cropped rectangle + * @param height the height of the cropped rectangle + */ + public CropImageFilter(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + /** + * An <code>ImageProducer</code> indicates the size of the image + * being produced using this method. This filter overrides this + * method in order to set the dimentions to the size of the + * cropped rectangle instead of the size of the image. + * + * @param width the width of the image + * @param height the height of the image + */ + public void setDimensions(int width, int height) + { + consumer.setDimensions(this.width, this.height); + } + + /** + * An <code>ImageProducer</code> can set a list of properties + * associated with this image by using this method. + * <br> + * FIXME - What property is set for this class? + * + * @param props the list of properties associated with this image + */ + public void setProperties(Hashtable props) + { + props.put("filters", "CropImageFilter"); + consumer.setProperties(props); + } + + /** + * This function delivers a rectangle of pixels where any + * pixel(m,n) is stored in the array as a <code>byte</code> at + * index (n * scansize + m + offset). + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param model the <code>ColorModel</code> used to translate the pixels + * @param pixels the array of pixel values + * @param offset the index of the first pixels in the <code>pixels</code> array + * @param scansize the width to use in extracting pixels from the <code>pixels</code> array + */ + public void setPixels(int x, int y, int w, int h, + ColorModel model, byte[] pixels, int offset, int scansize) + { + Rectangle filterBounds = new Rectangle(this.x, this.y, + this.width, this.height); + Rectangle pixelBounds = new Rectangle(x, y, w, h); + + if (filterBounds.intersects(pixelBounds)) + { + Rectangle bounds = filterBounds.intersection(pixelBounds); + + byte[] cropped = new byte[bounds.width * bounds.height]; + for (int i = 0; i < bounds.height; i++) + { + int start = (bounds.y - pixelBounds.y + i) * scansize + offset; + + for (int j = 0; j < bounds.width; j++) + cropped[i * bounds.width + j] = pixels[start + bounds.x + j]; + } + + consumer.setPixels(bounds.x, bounds.y, + bounds.width, bounds.height, + model, cropped, 0, bounds.width); + } + } + + /** + * This function delivers a rectangle of pixels where any + * pixel(m,n) is stored in the array as an <code>int</code> at + * index (n * scansize + m + offset). + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param model the <code>ColorModel</code> used to translate the pixels + * @param pixels the array of pixel values + * @param offset the index of the first pixels in the <code>pixels</code> array + * @param scansize the width to use in extracting pixels from the <code>pixels</code> array + */ + public void setPixels(int x, int y, int w, int h, + ColorModel model, int[] pixels, int offset, int scansize) + { + Rectangle filterBounds = new Rectangle(this.x, this.y, + this.width, this.height); + Rectangle pixelBounds = new Rectangle(x, y, w, h); + + if (filterBounds.intersects(pixelBounds)) + { + Rectangle bounds = filterBounds.intersection(pixelBounds); + + int[] cropped = new int[bounds.width * bounds.height]; + for (int i = 0; i < bounds.height; i++) + { + int start = (bounds.y - pixelBounds.y + i) * scansize + offset; + + for (int j = 0; j < bounds.width; j++) + cropped[i * bounds.width + j] = pixels[start + bounds.x + j]; + } + + consumer.setPixels(bounds.x, bounds.y, + bounds.width, bounds.height, + model, cropped, 0, bounds.width); + } + } + +} + diff --git a/libjava/classpath/java/awt/image/DataBuffer.java b/libjava/classpath/java/awt/image/DataBuffer.java new file mode 100644 index 0000000..9e4f714 --- /dev/null +++ b/libjava/classpath/java/awt/image/DataBuffer.java @@ -0,0 +1,436 @@ +/* Copyright (C) 2000, 2002, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +/** + * Class that manages arrays of data elements. A data buffer consists + * of one or more banks. A bank is a continuous region of data + * elements. + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public abstract class DataBuffer +{ + /** + * A constant representing a data type that uses <code>byte</code> primitives + * as the storage unit. + */ + public static final int TYPE_BYTE = 0; + + /** + * A constant representing a data type that uses <code>short</code> + * primitives as the storage unit. + */ + public static final int TYPE_USHORT = 1; + + /** + * A constant representing a data type that uses <code>short</code> + * primitives as the storage unit. + */ + public static final int TYPE_SHORT = 2; + + /** + * A constant representing a data type that uses <code>int</code> + * primitives as the storage unit. + */ + public static final int TYPE_INT = 3; + + /** + * A constant representing a data type that uses <code>float</code> + * primitives as the storage unit. + */ + public static final int TYPE_FLOAT = 4; + + /** + * A constant representing a data type that uses <code>double</code> + * primitives as the storage unit. + */ + public static final int TYPE_DOUBLE = 5; + + /** + * A constant representing an undefined data type. + */ + public static final int TYPE_UNDEFINED = 32; + + /** The type of the data elements stored in the data buffer. */ + protected int dataType; + + /** The number of banks in this buffer. */ + protected int banks = 1; + + /** Offset into the default (0'th) bank). */ + protected int offset; // FIXME: Is offsets[0] always mirrored in offset? + + /** The size of the banks. */ + protected int size; + + /** Offset into each bank. */ + protected int[] offsets; + + /** + * Creates a new <code>DataBuffer</code> with the specified data type and + * size. The <code>dataType</code> should be one of the constants + * {@link #TYPE_BYTE}, {@link #TYPE_SHORT}, {@link #TYPE_USHORT}, + * {@link #TYPE_INT}, {@link #TYPE_FLOAT} and {@link #TYPE_DOUBLE}. + * <p> + * The physical (array-based) storage is allocated by a subclass. + * + * @param dataType the data type. + * @param size the number of elements in the buffer. + */ + protected DataBuffer(int dataType, int size) + { + this.dataType = dataType; + this.size = size; + } + + /** + * Creates a new <code>DataBuffer</code> with the specified data type, + * size and number of banks. The <code>dataType</code> should be one of + * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT}, + * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and + * {@link #TYPE_DOUBLE}. + * <p> + * The physical (array-based) storage is allocated by a subclass. + * + * @param dataType the data type. + * @param size the number of elements in the buffer. + * @param numBanks the number of data banks. + */ + protected DataBuffer(int dataType, int size, int numBanks) { + this(dataType, size); + banks = numBanks; + offsets = new int[numBanks]; + } + + /** + * Creates a new <code>DataBuffer</code> with the specified data type, + * size and number of banks. An offset (which applies to all banks) is + * also specified. The <code>dataType</code> should be one of + * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT}, + * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and + * {@link #TYPE_DOUBLE}. + * <p> + * The physical (array-based) storage is allocated by a subclass. + * + * @param dataType the data type. + * @param size the number of elements in the buffer. + * @param numBanks the number of data banks. + * @param offset the offset to the first element for all banks. + */ + protected DataBuffer(int dataType, int size, int numBanks, int offset) { + this(dataType, size, numBanks); + + java.util.Arrays.fill(offsets, offset); + + this.offset = offset; + } + + /** + * Creates a new <code>DataBuffer</code> with the specified data type, + * size and number of banks. An offset (which applies to all banks) is + * also specified. The <code>dataType</code> should be one of + * the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT}, + * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and + * {@link #TYPE_DOUBLE}. + * <p> + * The physical (array-based) storage is allocated by a subclass. + * + * @param dataType the data type. + * @param size the number of elements in the buffer. + * @param numBanks the number of data banks. + * @param offsets the offsets to the first element for all banks. + * + * @throws ArrayIndexOutOfBoundsException if + * <code>numBanks != offsets.length</code>. + */ + protected DataBuffer(int dataType, int size, int numBanks, int[] offsets) { + this(dataType, size); + if (numBanks != offsets.length) + throw new ArrayIndexOutOfBoundsException(); + + banks = numBanks; + this.offsets = offsets; + + offset = offsets[0]; + } + + /** + * Returns the size (number of bits) of the specified data type. Valid types + * are defined by the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT}, + * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and + * {@link #TYPE_DOUBLE}. + * + * @param dataType the data type. + * @return The number of bits for the specified data type. + * @throws IllegalArgumentException if <code>dataType < 0</code> or + * <code>dataType > TYPE_DOUBLE</code>. + */ + public static int getDataTypeSize(int dataType) { + // Maybe this should be a lookup table instead. + switch (dataType) + { + case TYPE_BYTE: + return 8; + case TYPE_USHORT: + case TYPE_SHORT: + return 16; + case TYPE_INT: + case TYPE_FLOAT: + return 32; + case TYPE_DOUBLE: + return 64; + default: + throw new IllegalArgumentException(); + } + } + + /** + * Returns the type of the data elements in the data buffer. Valid types + * are defined by the constants {@link #TYPE_BYTE}, {@link #TYPE_SHORT}, + * {@link #TYPE_USHORT}, {@link #TYPE_INT}, {@link #TYPE_FLOAT} and + * {@link #TYPE_DOUBLE}. + * + * @return The type. + */ + public int getDataType() + { + return dataType; + } + + /** + * Returns the size of the data buffer. + * + * @return The size. + */ + public int getSize() + { + return size; + } + + /** + * Returns the element offset for the first data bank. + * + * @return The element offset. + */ + public int getOffset() + { + return offset; + } + + /** + * Returns the offsets for all the data banks used by this + * <code>DataBuffer</code>. + * + * @return The offsets. + */ + public int[] getOffsets() + { + if (offsets == null) + { + // is this necessary? + offsets = new int[1]; + offsets[0] = offset; + } + return offsets; + } + + /** + * Returns the number of data banks for this <code>DataBuffer</code>. + * @return The number of data banks. + */ + public int getNumBanks() + { + return banks; + } + + /** + * Returns an element from the first data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param i the element index. + * @return The element. + */ + public int getElem(int i) + { + return getElem(0, i); + } + + /** + * Returns an element from a particular data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param bank the bank index. + * @param i the element index. + * @return The element. + */ + public abstract int getElem(int bank, int i); + + /** + * Sets an element in the first data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int i, int val) + { + setElem(0, i, val); + } + + /** + * Sets an element in a particular data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param bank the data bank index. + * @param i the element index. + * @param val the new element value. + */ + public abstract void setElem(int bank, int i, int val); + + /** + * Returns an element from the first data bank, converted to a + * <code>float</code>. The offset (specified in the constructor) is added + * to <code>i</code> before accessing the underlying data array. + * + * @param i the element index. + * @return The element. + */ + public float getElemFloat(int i) + { + return getElem(i); + } + + /** + * Returns an element from a particular data bank, converted to a + * <code>float</code>. The offset (specified in the constructor) is + * added to <code>i</code> before accessing the underlying data array. + * + * @param bank the bank index. + * @param i the element index. + * @return The element. + */ + public float getElemFloat(int bank, int i) + { + return getElem(bank, i); + } + + /** + * Sets an element in the first data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param i the element index. + * @param val the new element value. + */ + public void setElemFloat(int i, float val) + { + setElem(i, (int) val); + } + + /** + * Sets an element in a particular data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param bank the data bank index. + * @param i the element index. + * @param val the new element value. + */ + public void setElemFloat(int bank, int i, float val) + { + setElem(bank, i, (int) val); + } + + /** + * Returns an element from the first data bank, converted to a + * <code>double</code>. The offset (specified in the constructor) is added + * to <code>i</code> before accessing the underlying data array. + * + * @param i the element index. + * @return The element. + */ + public double getElemDouble(int i) + { + return getElem(i); + } + + /** + * Returns an element from a particular data bank, converted to a + * <code>double</code>. The offset (specified in the constructor) is + * added to <code>i</code> before accessing the underlying data array. + * + * @param bank the bank index. + * @param i the element index. + * @return The element. + */ + public double getElemDouble(int bank, int i) + { + return getElem(bank, i); + } + + /** + * Sets an element in the first data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param i the element index. + * @param val the new element value. + */ + public void setElemDouble(int i, double val) + { + setElem(i, (int) val); + } + + /** + * Sets an element in a particular data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param bank the data bank index. + * @param i the element index. + * @param val the new element value. + */ + public void setElemDouble(int bank, int i, double val) + { + setElem(bank, i, (int) val); + } +} diff --git a/libjava/classpath/java/awt/image/DataBufferByte.java b/libjava/classpath/java/awt/image/DataBufferByte.java new file mode 100644 index 0000000..1113ebb --- /dev/null +++ b/libjava/classpath/java/awt/image/DataBufferByte.java @@ -0,0 +1,245 @@ +/* Copyright (C) 2000, 2002 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +/* This is one of several classes that are nearly identical. Maybe we + should have a central template and generate all these files. This + is one of the cases where templates or macros would have been + useful to have in Java. + + This file has been created using search-replace. My only fear is + that these classes will grow out-of-sync as of a result of changes + that are not propagated to the other files. As always, mirroring + code is a maintenance nightmare. */ + +/** + * A {@link DataBuffer} that uses an array of <code>byte</code> primitives + * to represent each of its banks. + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public final class DataBufferByte extends DataBuffer +{ + private byte[] data; + private byte[][] bankData; + + /** + * Creates a new data buffer with a single data bank containing the + * specified number of <code>byte</code> elements. + * + * @param size the number of elements in the data bank. + */ + public DataBufferByte(int size) + { + super(TYPE_BYTE, size, 1, 0); + bankData = new byte[1][]; + data = new byte[size]; + bankData[0] = data; + } + + /** + * Creates a new data buffer with the specified number of data banks, + * each containing the specified number of <code>byte</code> elements. + * + * @param size the number of elements in the data bank. + * @param numBanks the number of data banks. + */ + public DataBufferByte(int size, int numBanks) + { + super(TYPE_BYTE, size, numBanks); + bankData = new byte[numBanks][size]; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data bank. + * <p> + * Note: there is no exception when <code>dataArray</code> is + * <code>null</code>, but in that case an exception will be thrown + * later if you attempt to access the data buffer. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + */ + public DataBufferByte(byte[] dataArray, int size) + { + super(TYPE_BYTE, size, 1, 0); + bankData = new byte[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data bank, with + * the specified offset to the first element. + * <p> + * Note: there is no exception when <code>dataArray</code> is + * <code>null</code>, but in that case an exception will be thrown + * later if you attempt to access the data buffer. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + * @param offset the offset to the first element in the array. + */ + public DataBufferByte(byte[] dataArray, int size, int offset) + { + super(TYPE_BYTE, size, 1, offset); + bankData = new byte[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data banks. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferByte(byte[][] dataArray, int size) + { + super(TYPE_BYTE, size, dataArray.length); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data banks, with + * the specified offsets to the first element in each bank. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * @param offsets the offsets to the first element in each data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferByte(byte[][] dataArray, int size, int[] offsets) + { + super(TYPE_BYTE, size, dataArray.length, offsets); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Returns the first data bank. + * + * @return The first data bank. + */ + public byte[] getData() + { + return data; + } + + /** + * Returns a data bank. + * + * @param bank the bank index. + * @return A data bank. + */ + public byte[] getData(int bank) + { + return bankData[bank]; + } + + /** + * Returns the array underlying this <code>DataBuffer</code>. + * + * @return The data banks. + */ + public byte[][] getBankData() + { + return bankData; + } + + /** + * Returns an element from the first data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param i the element index. + * @return The element. + */ + public int getElem(int i) + { + return data[i+offset] & 0xff; // get unsigned byte as int + } + + /** + * Returns an element from a particular data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param bank the bank index. + * @param i the element index. + * @return The element. + */ + public int getElem(int bank, int i) + { + // get unsigned byte as int + return bankData[bank][i+offsets[bank]] & 0xff; + } + + /** + * Sets an element in the first data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int i, int val) + { + data[i+offset] = (byte) val; + } + + /** + * Sets an element in a particular data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param bank the data bank index. + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int bank, int i, int val) + { + bankData[bank][i+offsets[bank]] = (byte) val; + } +} diff --git a/libjava/classpath/java/awt/image/DataBufferDouble.java b/libjava/classpath/java/awt/image/DataBufferDouble.java new file mode 100644 index 0000000..a8c4b9d --- /dev/null +++ b/libjava/classpath/java/awt/image/DataBufferDouble.java @@ -0,0 +1,288 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +/* This is one of several classes that are nearly identical. Maybe we + should have a central template and generate all these files. This + is one of the cases where templates or macros would have been + useful to have in Java. + + This file has been created using search-replace. My only fear is + that these classes will grow out-of-sync as of a result of changes + that are not propagated to the other files. As always, mirroring + code is a maintenance nightmare. */ + +/** + * A {@link DataBuffer} that uses an array of <code>double</code> primitives + * to represent each of its banks. + * + * @since 1.4 + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public final class DataBufferDouble + extends DataBuffer +{ + private double[] data; + private double[][] bankData; + + /** + * Creates a new data buffer with a single data bank containing the + * specified number of <code>double</code> elements. + * + * @param size the number of elements in the data bank. + */ + public DataBufferDouble(int size) + { + super(TYPE_DOUBLE, size, 1, 0); + bankData = new double[1][]; + data = new double[size]; + bankData[0] = data; + } + + /** + * Creates a new data buffer with the specified number of data banks, + * each containing the specified number of <code>double</code> elements. + * + * @param size the number of elements in the data bank. + * @param numBanks the number of data banks. + */ + public DataBufferDouble(int size, int numBanks) + { + super(TYPE_DOUBLE, size, numBanks); + bankData = new double[numBanks][size]; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data bank. + * <p> + * Note: there is no exception when <code>dataArray</code> is + * <code>null</code>, but in that case an exception will be thrown + * later if you attempt to access the data buffer. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + */ + public DataBufferDouble(double[] dataArray, int size) + { + super(TYPE_DOUBLE, size, 1, 0); + bankData = new double[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data bank, with + * the specified offset to the first element. + * <p> + * Note: there is no exception when <code>dataArray</code> is + * <code>null</code>, but in that case an exception will be thrown + * later if you attempt to access the data buffer. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + * @param offset the offset to the first element in the array. + */ + public DataBufferDouble(double[] dataArray, int size, int offset) + { + super(TYPE_DOUBLE, size, 1, offset); + bankData = new double[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data banks. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferDouble(double[][] dataArray, int size) + { + super(TYPE_DOUBLE, size, dataArray.length); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data banks, with + * the specified offsets to the first element in each bank. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * @param offsets the offsets to the first element in each data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferDouble(double[][] dataArray, int size, int[] offsets) + { + super(TYPE_DOUBLE, size, dataArray.length, offsets); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Returns the first data bank. + * + * @return The first data bank. + */ + public double[] getData() + { + return data; + } + + /** + * Returns a data bank. + * + * @param bank the bank index. + * @return A data bank. + */ + public double[] getData(int bank) + { + return bankData[bank]; + } + + /** + * Returns the array underlying this <code>DataBuffer</code>. + * + * @return The data banks. + */ + public double[][] getBankData() + { + return bankData; + } + + /** + * Returns an element from the first data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param i the element index. + * @return The element. + */ + public int getElem(int i) + { + return (int) data[i+offset]; + } + + /** + * Returns an element from a particular data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param bank the bank index. + * @param i the element index. + * @return The element. + */ + public int getElem(int bank, int i) + { + return (int) bankData[bank][i+offsets[bank]]; + } + + /** + * Sets an element in the first data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int i, int val) + { + data[i+offset] = val; + } + + /** + * Sets an element in a particular data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param bank the data bank index. + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int bank, int i, int val) + { + bankData[bank][i+offsets[bank]] = val; + } + + public float getElemFloat(int i) + { + return (float) data[i+offset]; + } + + public float getElemFloat(int bank, int i) + { + return (float) bankData[bank][i+offsets[bank]]; + } + + public void setElemFloat(int i, float val) + { + data[i+offset] = val; + } + + public void setElemFloat(int bank, int i, float val) + { + bankData[bank][i+offsets[bank]] = val; + } + + public double getElemDouble(int i) + { + return data[i + offset]; + } + + public double getElemDouble(int bank, int i) + { + return bankData[bank][i + offsets[bank]]; + } + + public void setElemDouble(int i, double val) + { + data[i + offset] = val; + } + + public void setElemDouble(int bank, int i, double val) + { + bankData[bank][i + offsets[bank]] = val; + } +} diff --git a/libjava/classpath/java/awt/image/DataBufferFloat.java b/libjava/classpath/java/awt/image/DataBufferFloat.java new file mode 100644 index 0000000..9cf8784 --- /dev/null +++ b/libjava/classpath/java/awt/image/DataBufferFloat.java @@ -0,0 +1,286 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +/* This is one of several classes that are nearly identical. Maybe we + should have a central template and generate all these files. This + is one of the cases where templates or macros would have been + useful to have in Java. + + This file has been created using search-replace. My only fear is + that these classes will grow out-of-sync as of a result of changes + that are not propagated to the other files. As always, mirroring + code is a maintenance nightmare. */ + +/** + * A {@link DataBuffer} that uses an array of <code>float</code> primitives + * to represent each of its banks. + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public final class DataBufferFloat + extends DataBuffer +{ + private float[] data; + private float[][] bankData; + + /** + * Creates a new data buffer with a single data bank containing the + * specified number of <code>float</code> elements. + * + * @param size the number of elements in the data bank. + */ + public DataBufferFloat(int size) + { + super(TYPE_FLOAT, size, 1, 0); + bankData = new float[1][]; + data = new float[size]; + bankData[0] = data; + } + + /** + * Creates a new data buffer with the specified number of data banks, + * each containing the specified number of <code>float</code> elements. + * + * @param size the number of elements in the data bank. + * @param numBanks the number of data banks. + */ + public DataBufferFloat(int size, int numBanks) + { + super(TYPE_FLOAT, size, numBanks); + bankData = new float[numBanks][size]; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data bank. + * <p> + * Note: there is no exception when <code>dataArray</code> is + * <code>null</code>, but in that case an exception will be thrown + * later if you attempt to access the data buffer. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + */ + public DataBufferFloat(float[] dataArray, int size) + { + super(TYPE_FLOAT, size, 1, 0); + bankData = new float[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data bank, with + * the specified offset to the first element. + * <p> + * Note: there is no exception when <code>dataArray</code> is + * <code>null</code>, but in that case an exception will be thrown + * later if you attempt to access the data buffer. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + * @param offset the offset to the first element in the array. + */ + public DataBufferFloat(float[] dataArray, int size, int offset) + { + super(TYPE_FLOAT, size, 1, offset); + bankData = new float[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data banks. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferFloat(float[][] dataArray, int size) + { + super(TYPE_FLOAT, size, dataArray.length); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data banks, with + * the specified offsets to the first element in each bank. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * @param offsets the offsets to the first element in each data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferFloat(float[][] dataArray, int size, int[] offsets) + { + super(TYPE_FLOAT, size, dataArray.length, offsets); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Returns the first data bank. + * + * @return The first data bank. + */ + public float[] getData() + { + return data; + } + + /** + * Returns a data bank. + * + * @param bank the bank index. + * @return A data bank. + */ + public float[] getData(int bank) + { + return bankData[bank]; + } + + /** + * Returns the array underlying this <code>DataBuffer</code>. + * + * @return The data banks. + */ + public float[][] getBankData() + { + return bankData; + } + + /** + * Returns an element from the first data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param i the element index. + * @return The element. + */ + public int getElem(int i) + { + return (int) data[i+offset]; + } + + /** + * Returns an element from a particular data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param bank the bank index. + * @param i the element index. + * @return The element. + */ + public int getElem(int bank, int i) + { + return (int) bankData[bank][i+offsets[bank]]; + } + + /** + * Sets an element in the first data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int i, int val) + { + data[i+offset] = val; + } + + /** + * Sets an element in a particular data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param bank the data bank index. + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int bank, int i, int val) + { + bankData[bank][i+offsets[bank]] = val; + } + + public float getElemFloat(int i) + { + return data[i+offset]; + } + + public float getElemFloat(int bank, int i) + { + return bankData[bank][i+offsets[bank]]; + } + + public void setElemFloat(int i, float val) + { + data[i+offset] = val; + } + + public void setElemFloat(int bank, int i, float val) + { + bankData[bank][i+offsets[bank]] = val; + } + + public double getElemDouble(int i) + { + return getElemFloat(i); + } + + public double getElemDouble(int bank, int i) + { + return getElemFloat(bank, i); + } + + public void setElemDouble(int i, double val) + { + setElemFloat(i, (float) val); + } + + public void setElemDouble(int bank, int i, double val) + { + setElemFloat(bank, i, (float) val); + } +} diff --git a/libjava/classpath/java/awt/image/DataBufferInt.java b/libjava/classpath/java/awt/image/DataBufferInt.java new file mode 100644 index 0000000..0aac940 --- /dev/null +++ b/libjava/classpath/java/awt/image/DataBufferInt.java @@ -0,0 +1,244 @@ +/* Copyright (C) 2000, 2002, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +/* This is one of several classes that are nearly identical. Maybe we + should have a central template and generate all these files. This + is one of the cases where templates or macros would have been + useful to have in Java. + + This file has been created using search-replace. My only fear is + that these classes will grow out-of-sync as of a result of changes + that are not propagated to the other files. As always, mirroring + code is a maintenance nightmare. */ + +/** + * A {@link DataBuffer} that uses an array of <code>int</code> primitives + * to represent each of its banks. + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public final class DataBufferInt extends DataBuffer +{ + private int[] data; + private int[][] bankData; + + /** + * Creates a new data buffer with a single data bank containing the + * specified number of <code>int</code> elements. + * + * @param size the number of elements in the data bank. + */ + public DataBufferInt(int size) + { + super(TYPE_INT, size, 1, 0); + bankData = new int[1][]; + data = new int[size]; + bankData[0] = data; + } + + /** + * Creates a new data buffer with the specified number of data banks, + * each containing the specified number of <code>int</code> elements. + * + * @param size the number of elements in the data bank. + * @param numBanks the number of data banks. + */ + public DataBufferInt(int size, int numBanks) + { + super(TYPE_INT, size, numBanks); + bankData = new int[numBanks][size]; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data bank. + * <p> + * Note: there is no exception when <code>dataArray</code> is + * <code>null</code>, but in that case an exception will be thrown + * later if you attempt to access the data buffer. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + */ + public DataBufferInt(int[] dataArray, int size) + { + super(TYPE_INT, size, 1, 0); + bankData = new int[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data bank, with + * the specified offset to the first element. + * <p> + * Note: there is no exception when <code>dataArray</code> is + * <code>null</code>, but in that case an exception will be thrown + * later if you attempt to access the data buffer. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + * @param offset the offset to the first element in the array. + */ + public DataBufferInt(int[] dataArray, int size, int offset) + { + super(TYPE_INT, size, 1, offset); + bankData = new int[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data banks. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferInt(int[][] dataArray, int size) + { + super(TYPE_INT, size, dataArray.length); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data banks, with + * the specified offsets to the first element in each bank. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * @param offsets the offsets to the first element in each data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferInt(int[][] dataArray, int size, int[] offsets) + { + super(TYPE_INT, size, dataArray.length, offsets); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Returns the first data bank. + * + * @return The first data bank. + */ + public int[] getData() + { + return data; + } + + /** + * Returns a data bank. + * + * @param bank the bank index. + * @return A data bank. + */ + public int[] getData(int bank) + { + return bankData[bank]; + } + + /** + * Returns the array underlying this <code>DataBuffer</code>. + * + * @return The data banks. + */ + public int[][] getBankData() + { + return bankData; + } + + /** + * Returns an element from the first data bank. The <code>offset</code> is + * added to the specified index before accessing the underlying data array. + * + * @param i the element index. + * @return The element. + */ + public int getElem(int i) + { + return data[i+offset]; + } + + /** + * Returns an element from a particular data bank. The <code>offset</code> + * is added to the specified index before accessing the underlying data + * array. + * + * @param bank the bank index. + * @param i the element index. + * @return The element. + */ + public int getElem(int bank, int i) + { + // get unsigned int as int + return bankData[bank][i+offsets[bank]]; + } + + /** + * Sets an element in the first data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int i, int val) + { + data[i+offset] = val; + } + + /** + * Sets an element in a particular data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param bank the data bank index. + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int bank, int i, int val) + { + bankData[bank][i+offsets[bank]] = val; + } +} diff --git a/libjava/classpath/java/awt/image/DataBufferShort.java b/libjava/classpath/java/awt/image/DataBufferShort.java new file mode 100644 index 0000000..5c67a8d --- /dev/null +++ b/libjava/classpath/java/awt/image/DataBufferShort.java @@ -0,0 +1,245 @@ +/* DataBufferShort.java -- + Copyright (C) 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +/* This is one of several classes that are nearly identical. Maybe we + should have a central template and generate all these files. This + is one of the cases where templates or macros would have been + useful to have in Java. + + This file has been created using search-replace. My only fear is + that these classes will grow out-of-sync as of a result of changes + that are not propagated to the other files. As always, mirroring + code is a maintenance nightmare. */ + +/** + * A {@link DataBuffer} that uses an array of <code>short</code> primitives + * to represent each of its banks. + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public final class DataBufferShort extends DataBuffer +{ + private short[] data; + private short[][] bankData; + + /** + * Creates a new data buffer with a single data bank containing the + * specified number of <code>short</code> elements. + * + * @param size the number of elements in the data bank. + */ + public DataBufferShort(int size) + { + super(TYPE_SHORT, size, 1, 0); + bankData = new short[1][]; + data = new short[size]; + bankData[0] = data; + } + + /** + * Creates a new data buffer with the specified number of data banks, + * each containing the specified number of <code>short</code> elements. + * + * @param size the number of elements in the data bank. + * @param numBanks the number of data banks. + */ + public DataBufferShort(int size, int numBanks) + { + super(TYPE_SHORT, size, numBanks); + bankData = new short[numBanks][size]; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data bank. + * <p> + * Note: there is no exception when <code>dataArray</code> is + * <code>null</code>, but in that case an exception will be thrown + * later if you attempt to access the data buffer. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + */ + public DataBufferShort(short[] dataArray, int size) + { + super(TYPE_SHORT, size, 1, 0); + bankData = new short[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data bank, with + * the specified offset to the first element. + * <p> + * Note: there is no exception when <code>dataArray</code> is + * <code>null</code>, but in that case an exception will be thrown + * later if you attempt to access the data buffer. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + * @param offset the offset to the first element in the array. + */ + public DataBufferShort(short[] dataArray, int size, int offset) + { + super(TYPE_SHORT, size, 1, offset); + bankData = new short[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data banks. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferShort(short[][] dataArray, int size) + { + super(TYPE_SHORT, size, dataArray.length); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data banks, with + * the specified offsets to the first element in each bank. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * @param offsets the offsets to the first element in each data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferShort(short[][] dataArray, int size, int[] offsets) + { + super(TYPE_SHORT, size, dataArray.length, offsets); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Returns the first data bank. + * + * @return The first data bank. + */ + public short[] getData() + { + return data; + } + + /** + * Returns a data bank. + * + * @param bank the bank index. + * @return A data bank. + */ + public short[] getData(int bank) + { + return bankData[bank]; + } + + /** + * Returns the array underlying this <code>DataBuffer</code>. + * + * @return The data banks. + */ + public short[][] getBankData() + { + return bankData; + } + + /** + * Returns an element from the first data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param i the element index. + * @return The element. + */ + public int getElem(int i) + { + return data[i+offset]; + } + + /** + * Returns an element from a particular data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param bank the bank index. + * @param i the element index. + * @return The element. + */ + public int getElem(int bank, int i) + { + return bankData[bank][i+offsets[bank]]; + } + + /** + * Sets an element in the first data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int i, int val) + { + data[i+offset] = (short) val; + } + + /** + * Sets an element in a particular data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param bank the data bank index. + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int bank, int i, int val) + { + bankData[bank][i+offsets[bank]] = (short) val; + } +} diff --git a/libjava/classpath/java/awt/image/DataBufferUShort.java b/libjava/classpath/java/awt/image/DataBufferUShort.java new file mode 100644 index 0000000..981e9e9 --- /dev/null +++ b/libjava/classpath/java/awt/image/DataBufferUShort.java @@ -0,0 +1,246 @@ +/* DataBufferUShort.java -- + Copyright (C) 2000, 2002, 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +/* This is one of several classes that are nearly identical. Maybe we + should have a central template and generate all these files. This + is one of the cases where templates or macros would have been + useful to have in Java. + + This file has been created using search-replace. My only fear is + that these classes will grow out-of-sync as of a result of changes + that are not propagated to the other files. As always, mirroring + code is a maintenance nightmare. */ + +/** + * A {@link DataBuffer} that uses an array of <code>short</code> primitives + * to represent each of its banks. + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public final class DataBufferUShort extends DataBuffer +{ + private short[] data; + private short[][] bankData; + + /** + * Creates a new data buffer with a single data bank containing the + * specified number of <code>short</code> elements. + * + * @param size the number of elements in the data bank. + */ + public DataBufferUShort(int size) + { + super(TYPE_USHORT, size, 1, 0); + bankData = new short[1][]; + data = new short[size]; + bankData[0] = data; + } + + /** + * Creates a new data buffer with the specified number of data banks, + * each containing the specified number of <code>short</code> elements. + * + * @param size the number of elements in the data bank. + * @param numBanks the number of data banks. + */ + public DataBufferUShort(int size, int numBanks) + { + super(TYPE_USHORT, size, numBanks); + bankData = new short[numBanks][size]; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data bank. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + * + * @throws NullPointerException if dataArray is null + */ + public DataBufferUShort(short[] dataArray, int size) + { + super(TYPE_USHORT, size, 1, 0); + if (dataArray == null) + throw new NullPointerException(); + bankData = new short[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data bank, with + * the specified offset to the first element. + * + * @param dataArray the data bank. + * @param size the number of elements in the data bank. + * @param offset the offset to the first element in the array. + * + * @throws NullPointerException if dataArray is null + */ + public DataBufferUShort(short[] dataArray, int size, int offset) + { + super(TYPE_USHORT, size, 1, offset); + if (dataArray == null) + throw new NullPointerException(); + bankData = new short[1][]; + data = dataArray; + bankData[0] = data; + } + + /** + * Creates a new data buffer backed by the specified data banks. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferUShort(short[][] dataArray, int size) + { + super(TYPE_USHORT, size, dataArray.length); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Creates a new data buffer backed by the specified data banks, with + * the specified offsets to the first element in each bank. + * + * @param dataArray the data banks. + * @param size the number of elements in the data bank. + * @param offsets the offsets to the first element in each data bank. + * + * @throws NullPointerException if <code>dataArray</code> is + * <code>null</code>. + */ + public DataBufferUShort(short[][] dataArray, int size, int[] offsets) + { + super(TYPE_USHORT, size, dataArray.length, offsets); + bankData = dataArray; + data = bankData[0]; + } + + /** + * Returns the first data bank. + * + * @return The first data bank. + */ + public short[] getData() + { + return data; + } + + /** + * Returns a data bank. + * + * @param bank the bank index. + * @return A data bank. + */ + public short[] getData(int bank) + { + return bankData[bank]; + } + + /** + * Returns the array underlying this <code>DataBuffer</code>. + * + * @return The data banks. + */ + public short[][] getBankData() + { + return bankData; + } + + /** + * Returns an element from the first data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param i the element index. + * @return The element. + */ + public int getElem(int i) + { + return data[i+offset] & 0xffff; // get unsigned short as int + } + + /** + * Returns an element from a particular data bank. The offset (specified in + * the constructor) is added to <code>i</code> before accessing the + * underlying data array. + * + * @param bank the bank index. + * @param i the element index. + * @return The element. + */ + public int getElem(int bank, int i) + { + // get unsigned short as int + return bankData[bank][i+offsets[bank]] & 0xffff; + } + + /** + * Sets an element in the first data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int i, int val) + { + data[i+offset] = (short) val; + } + + /** + * Sets an element in a particular data bank. The offset (specified in the + * constructor) is added to <code>i</code> before updating the underlying + * data array. + * + * @param bank the data bank index. + * @param i the element index. + * @param val the new element value. + */ + public void setElem(int bank, int i, int val) + { + bankData[bank][i+offsets[bank]] = (short) val; + } +} diff --git a/libjava/classpath/java/awt/image/DirectColorModel.java b/libjava/classpath/java/awt/image/DirectColorModel.java new file mode 100644 index 0000000..c98c3f8 --- /dev/null +++ b/libjava/classpath/java/awt/image/DirectColorModel.java @@ -0,0 +1,420 @@ +/* DirectColorModel.java -- + Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import gnu.java.awt.Buffers; + +import java.awt.Point; +import java.awt.Transparency; +import java.awt.color.ColorSpace; + +/** + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + * @author C. Brian Jones (cbj@gnu.org) + * @author Mark Benvenuto (mcb54@columbia.edu) + */ +public class DirectColorModel extends PackedColorModel +{ + /** + * For the color model created with this constructor the pixels + * will have fully opaque alpha components with a value of 255. + * Each mask should describe a fully contiguous set of bits in the + * most likely order of alpha, red, green, blue from the most significant + * byte to the least significant byte. + * + * @param pixelBits the number of bits wide used for bit size of pixel values + * @param rmask the bits describing the red component of a pixel + * @param gmask the bits describing the green component of a pixel + * @param bmask the bits describing the blue component of a pixel + */ + public DirectColorModel(int pixelBits, int rmask, int gmask, int bmask) + { + this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits, + rmask, gmask, bmask, 0, + false, // not alpha premultiplied + Buffers.smallestAppropriateTransferType(pixelBits) // find type + ); + } + + /** + * For the color model created with this constructor the pixels + * will have fully opaque alpha components with a value of 255. + * Each mask should describe a fully contiguous set of bits in the + * most likely order of red, green, blue from the most significant + * byte to the least significant byte. + * + * @param pixelBits the number of bits wide used for bit size of pixel values + * @param rmask the bits describing the red component of a pixel + * @param gmask the bits describing the green component of a pixel + * @param bmask the bits describing the blue component of a pixel + * @param amask the bits describing the alpha component of a pixel + */ + public DirectColorModel(int pixelBits, + int rmask, int gmask, int bmask, int amask) + { + this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits, + rmask, gmask, bmask, amask, + false, // not alpha premultiplied + Buffers.smallestAppropriateTransferType(pixelBits) // find type + ); + } + + public DirectColorModel(ColorSpace cspace, int pixelBits, + int rmask, int gmask, int bmask, int amask, + boolean isAlphaPremultiplied, + int transferType) + { + super(cspace, pixelBits, + rmask, gmask, bmask, amask, isAlphaPremultiplied, + ((amask == 0) ? Transparency.OPAQUE : Transparency.TRANSLUCENT), + transferType); + } + + public final int getRedMask() + { + return getMask(0); + } + + public final int getGreenMask() + { + return getMask(1); + } + + public final int getBlueMask() + { + return getMask(2); + } + + public final int getAlphaMask() + { + return hasAlpha() ? getMask(3) : 0; + } + + /** + * Get the red component of the given pixel. + * <br> + */ + public final int getRed(int pixel) + { + return extractAndNormalizeSample(pixel, 0); + } + + /** + * Get the green component of the given pixel. + * <br> + */ + public final int getGreen(int pixel) + { + return extractAndNormalizeSample(pixel, 1); + } + + /** + * Get the blue component of the given pixel. + * <br> + */ + public final int getBlue(int pixel) + { + return extractAndNormalizeSample(pixel, 2); + } + + /** + * Get the alpha component of the given pixel. + * <br> + */ + public final int getAlpha(int pixel) + { + if (!hasAlpha()) + return 255; + return extractAndScaleSample(pixel, 3); + } + + private int extractAndNormalizeSample(int pixel, int component) + { + int value = extractAndScaleSample(pixel, component); + if (hasAlpha() && isAlphaPremultiplied()) + value = value*255/getAlpha(pixel); + return value; + } + + private int extractAndScaleSample(int pixel, int component) + { + int field = pixel & getMask(component); + int to8BitShift = + 8 - shifts[component] - getComponentSize(component); + return (to8BitShift>0) ? + (field << to8BitShift) : + (field >>> (-to8BitShift)); + } + + /** + * Get the RGB color value of the given pixel using the default + * RGB color model. + * <br> + * + * @param pixel a pixel value + */ + public final int getRGB(int pixel) + { + /* FIXME: The Sun docs show that this method is overridden, but I + don't see any way to improve on the superclass + implementation. */ + return super.getRGB(pixel); + } + + public int getRed(Object inData) + { + return getRed(getPixelFromArray(inData)); + } + + public int getGreen(Object inData) + { + return getGreen(getPixelFromArray(inData)); + } + + public int getBlue(Object inData) + { + return getBlue(getPixelFromArray(inData)); + } + + public int getAlpha(Object inData) + { + return getAlpha(getPixelFromArray(inData)); + } + + public int getRGB(Object inData) + { + return getRGB(getPixelFromArray(inData)); + } + + /** + * Converts a normalized pixel int value in the sRGB color + * space to an array containing a single pixel of the color space + * of the color model. + * + * <p>This method performs the inverse function of + * <code>getRGB(Object inData)</code>. + * + * @param rgb pixel as a normalized sRGB, 0xAARRGGBB value. + * + * @param pixel to avoid needless creation of arrays, an array to + * use to return the pixel can be given. If null, a suitable array + * will be created. + * + * @return array of transferType containing a single pixel. The + * pixel should be encoded in the natural way of the color model. + * + * @see #getRGB(Object) + */ + public Object getDataElements(int rgb, Object pixel) + { + // FIXME: handle alpha multiply + + int pixelValue = 0; + int a = 0; + if (hasAlpha()) { + a = (rgb >>> 24) & 0xff; + pixelValue = valueToField(a, 3, 8); + } + + if (hasAlpha() && isAlphaPremultiplied()) + { + int r, g, b; + /* if r=0xff and a=0xff, then resulting + value will be (r*a)>>>8 == 0xfe... This seems wrong. + We should divide by 255 rather than shifting >>>8 after + multiplying. + + Too bad, shifting is probably less expensive. + r = ((rgb >>> 16) & 0xff)*a; + g = ((rgb >>> 8) & 0xff)*a; + b = ((rgb >>> 0) & 0xff)*a; */ + /* The r, g, b values we calculate are 16 bit. This allows + us to avoid discarding the lower 8 bits obtained if + multiplying with the alpha band. */ + + // using 16 bit values + r = ((rgb >>> 8) & 0xff00)*a/255; + g = ((rgb >>> 0) & 0xff00)*a/255; + b = ((rgb << 8) & 0xff00)*a/255; + pixelValue |= + valueToField(r, 0, 16) | // Red + valueToField(g, 1, 16) | // Green + valueToField(b, 2, 16); // Blue + } + else + { + int r, g, b; + // using 8 bit values + r = (rgb >>> 16) & 0xff; + g = (rgb >>> 8) & 0xff; + b = (rgb >>> 0) & 0xff; + + pixelValue |= + valueToField(r, 0, 8) | // Red + valueToField(g, 1, 8) | // Green + valueToField(b, 2, 8); // Blue + } + + /* In this color model, the whole pixel fits in the first element + of the array. */ + DataBuffer buffer = Buffers.createBuffer(transferType, pixel, 1); + buffer.setElem(0, pixelValue); + return Buffers.getData(buffer); + } + + /** + * Converts a value to the correct field bits based on the + * information derived from the field masks. + * + * @param highBit the position of the most significant bit in the + * val parameter. + */ + private int valueToField(int val, int component, int highBit) + { + int toFieldShift = + getComponentSize(component) + shifts[component] - highBit; + int ret = (toFieldShift>0) ? + (val << toFieldShift) : + (val >>> (-toFieldShift)); + return ret & getMask(component); + } + + /** + * Converts a 16 bit value to the correct field bits based on the + * information derived from the field masks. + */ + private int value16ToField(int val, int component) + { + int toFieldShift = getComponentSize(component) + shifts[component] - 16; + return (toFieldShift>0) ? + (val << toFieldShift) : + (val >>> (-toFieldShift)); + } + + /** + * Fills an array with the unnormalized component samples from a + * pixel value. I.e. decompose the pixel, but not perform any + * color conversion. + */ + public final int[] getComponents(int pixel, int[] components, int offset) + { + int numComponents = getNumComponents(); + if (components == null) components = new int[offset + numComponents]; + + for (int b=0; b<numComponents; b++) + components[offset++] = (pixel&getMask(b)) >>> shifts[b]; + + return components; + } + + public final int[] getComponents(Object pixel, int[] components, + int offset) + { + return getComponents(getPixelFromArray(pixel), components, offset); + } + + public final WritableRaster createCompatibleWritableRaster(int w, int h) + { + SampleModel sm = createCompatibleSampleModel(w, h); + Point origin = new Point(0, 0); + return Raster.createWritableRaster(sm, origin); + } + + public int getDataElement(int[] components, int offset) + { + int numComponents = getNumComponents(); + int pixelValue = 0; + + for (int c=0; c<numComponents; c++) + pixelValue |= (components[offset++] << shifts[c]) & getMask(c); + + return pixelValue; + } + + public Object getDataElements(int[] components, int offset, Object obj) + { + /* In this color model, the whole pixel fits in the first element + of the array. */ + int pixelValue = getDataElement(components, offset); + + DataBuffer buffer = Buffers.createBuffer(transferType, obj, 1); + buffer.setElem(0, pixelValue); + return Buffers.getData(buffer); + } + + public final ColorModel coerceData (WritableRaster raster, + boolean isAlphaPremultiplied) + { + if (this.isAlphaPremultiplied == isAlphaPremultiplied) + return this; + + /* TODO: provide better implementation based on the + assumptions we can make due to the specific type of the + color model. */ + super.coerceData(raster, isAlphaPremultiplied); + + return new ComponentColorModel(cspace, bits, hasAlpha(), + isAlphaPremultiplied, // argument + transparency, transferType); + } + + public boolean isCompatibleRaster(Raster raster) + { + /* FIXME: the Sun docs say this method is overridden here, + but I don't see any way to improve upon the implementation + in ColorModel. */ + return super.isCompatibleRaster(raster); + } + + String stringParam() + { + return super.stringParam() + + ", redMask=" + Integer.toHexString(getRedMask()) + + ", greenMask=" + Integer.toHexString(getGreenMask()) + + ", blueMask=" + Integer.toHexString(getBlueMask()) + + ", alphaMask=" + Integer.toHexString(getAlphaMask()); + } + + public String toString() + { + /* FIXME: Again, docs say override, but how do we improve upon the + superclass implementation? */ + return super.toString(); + } +} diff --git a/libjava/classpath/java/awt/image/FilteredImageSource.java b/libjava/classpath/java/awt/image/FilteredImageSource.java new file mode 100644 index 0000000..8893e86 --- /dev/null +++ b/libjava/classpath/java/awt/image/FilteredImageSource.java @@ -0,0 +1,125 @@ +/* FilteredImageSource.java -- Java class for providing image data + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.util.Hashtable; + +/** + * + * @see ImageConsumer + * @author C. Brian Jones (cbj@gnu.org) + */ +public class FilteredImageSource implements ImageProducer +{ + ImageProducer ip; + ImageFilter filter; + Hashtable consumers = new Hashtable(); + + /** + * The given filter is applied to the given image producer + * to create a new image producer. + */ + public FilteredImageSource(ImageProducer ip, ImageFilter filter) { + this.ip = ip; + this.filter = filter; + } + + /** + * Used to register an <code>ImageConsumer</code> with this + * <code>ImageProducer</code>. + */ + public synchronized void addConsumer(ImageConsumer ic) { + if (consumers.containsKey(ic)) + return; + + ImageFilter f = filter.getFilterInstance(ic); + consumers.put(ic, f); + ip.addConsumer(f); + } + + /** + * Used to determine if the given <code>ImageConsumer</code> is + * already registered with this <code>ImageProducer</code>. + */ + public synchronized boolean isConsumer(ImageConsumer ic) { + ImageFilter f = (ImageFilter)consumers.get(ic); + if (f != null) + return ip.isConsumer(f); + return false; + } + + /** + * Used to remove an <code>ImageConsumer</code> from the list of + * registered consumers for this <code>ImageProducer</code>. + */ + public synchronized void removeConsumer(ImageConsumer ic) { + ImageFilter f = (ImageFilter)consumers.remove(ic); + if (f != null) + ip.removeConsumer(f); + } + + /** + * Used to register an <code>ImageConsumer</code> with this + * <code>ImageProducer</code> and then immediately start + * reconstruction of the image data to be delivered to all + * registered consumers. + */ + public void startProduction(ImageConsumer ic) { + ImageFilter f; + if (!(consumers.containsKey(ic))) { + f = filter.getFilterInstance(ic); + consumers.put(ic, f); + ip.addConsumer(f); + } else { + f = (ImageFilter)consumers.get( ic ); + } + ip.startProduction(f); + } + + /** + * Used to register an <code>ImageConsumer</code> with this + * <code>ImageProducer</code> and then request that this producer + * resend the image data in the order top-down, left-right. + */ + public void requestTopDownLeftRightResend(ImageConsumer ic) { + ImageFilter f = (ImageFilter)consumers.get(ic); + ip.requestTopDownLeftRightResend(f); + } +} + diff --git a/libjava/classpath/java/awt/image/ImageConsumer.java b/libjava/classpath/java/awt/image/ImageConsumer.java new file mode 100644 index 0000000..e1834c3 --- /dev/null +++ b/libjava/classpath/java/awt/image/ImageConsumer.java @@ -0,0 +1,216 @@ +/* ImageConsumer.java -- Java interface for image consumption + Copyright (C) 1999, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.util.Hashtable; + +/** + * An object implementing the <code>ImageProducer</code> interface can + * use objects implementing this interface to deliver the image data. + * + * @author C. Brian Jones (cbj@gnu.org) + */ +public interface ImageConsumer +{ + /** + * The pixel order may be random. This should be + * the default assumption of the <code>ImageConsumer</code>. + * + * @see #setHints + */ + int RANDOMPIXELORDER = 1; + + /** + * The pixel order is top-down, left-right. + * + * @see #setHints + */ + int TOPDOWNLEFTRIGHT = 2; + + /** + * The pixel order is in multiples of complete scanlines. + * + * @see #setHints + */ + int COMPLETESCANLINES = 4; + + /** + * The pixels will be delivered in a single pass. There is at + * most one call to <code>setPixels</code> for any single pixel. + * + * @see #setHints + * @see #setPixels + */ + int SINGLEPASS = 8; + + /** + * The pixels will be delivered with multiple calls to + * <code>setPixels</code>. The image contains a single frame + * which ends when <code>imageComplete</code> is called with the + * <code>STATICIMAGEDONE</code> flag. If the image is constantly + * changing such as with video then the end of each frame is + * marked by a similar call to <code>imageComplete</code> with the + * <code>SINGLEFRAMEDONE</code> flag. + * + * @see #setHints + * @see #imageComplete + */ + int SINGLEFRAME = 16; + + /** + * Indicates an error occurred while producing an image. + * + * @see #imageComplete + */ + int IMAGEERROR = 1; + + /** + * A single frame is complete but more will follow. + * + * @see #imageComplete + */ + int SINGLEFRAMEDONE = 2; + + /** + * The image is complete and no more pixels or frames will follow. + * + * @see #imageComplete + */ + int STATICIMAGEDONE = 3; + + /** + * Production of the image has been aborted. + * + * @see #imageComplete + */ + int IMAGEABORTED = 4; + + /** + * An <code>ImageProducer</code> indicates the size of the image + * being produced using this method. + * + * @param width the width of the image + * @param height the height of the image + */ + void setDimensions(int width, int height); + + /** + * An <code>ImageProducer</code> can set a list of properties + * associated with this image by using this method. + * + * @param props the list of properties associated with this image + */ + void setProperties(Hashtable props); + + /** + * This <code>ColorModel</code> should indicate the model used by + * the majority of calls to <code>setPixels</code>. Each call to + * <code>setPixels</code> could however indicate a different + * <code>ColorModel</code>. + * + * @param model the color model to be used most often by setPixels + * @see ColorModel + */ + void setColorModel(ColorModel model); + + /** + * The <code>ImageProducer</code> should call this method with a + * bit mask of hints from any of <code>RANDOMPIXELORDER</code>, + * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>, + * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>. + * + * @param flags a bit mask of hints + */ + void setHints(int flags); + + /** + * Deliver a subset of an ImageProducer's pixels to this ImageConsumer. + * + * Each element of the pixels array represents one pixel. The + * pixel data is formatted according to the color model model. + * The x and y parameters are the coordinates of the block of + * pixels being delivered to this ImageConsumer. They are + * specified relative to the top left corner of the image being + * produced. Likewise, w and h are the pixel block's dimensions. + * + * @param x x coordinate of pixel block + * @param y y coordinate of pixel block + * @param w width of pixel block + * @param h height of pixel block + * @param model color model used to interpret pixel data + * @param pixels pixel block data + * @param offset offset into pixels array + * @param scansize width of one row in the pixel block + */ + void setPixels(int x, int y, int w, int h, + ColorModel model, byte[] pixels, int offset, int scansize); + + /** + * Deliver a subset of an ImageProducer's pixels to this ImageConsumer. + * + * Each element of the pixels array represents one pixel. The + * pixel data is formatted according to the color model model. + * The x and y parameters are the coordinates of the rectangular + * region of pixels being delivered to this ImageConsumer, + * specified relative to the top left corner of the image being + * produced. Likewise, w and h are the pixel region's dimensions. + * + * @param x x coordinate of pixel block + * @param y y coordinate of pixel block + * @param w width of pixel block + * @param h height of pixel block + * @param model color model used to interpret pixel data + * @param pixels pixel block data + * @param offset offset into pixels array + * @param scansize width of one row in the pixel block + */ + void setPixels(int x, int y, int w, int h, + ColorModel model, int[] pixels, int offset, int scansize); + + /** + * The <code>ImageProducer</code> calls this method to indicate a + * single frame or the entire image is complete. The method is + * also used to indicate an error in loading or producing the + * image. + * + * @param status the status of image production, represented by a + * bitwise OR of ImageConsumer flags + */ + void imageComplete(int status); +} diff --git a/libjava/classpath/java/awt/image/ImageFilter.java b/libjava/classpath/java/awt/image/ImageFilter.java new file mode 100644 index 0000000..9940a2b --- /dev/null +++ b/libjava/classpath/java/awt/image/ImageFilter.java @@ -0,0 +1,221 @@ +/* ImageFilter.java -- Java class for filtering images + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.util.Hashtable; + +/** + * The <code>ImageFilter</code> class is a base class which can be + * extended to provide different types of filters for an image. By + * default this class does nothing to an image passing through it. + * + * @author C. Brian Jones (cbj@gnu.org) + */ +public class ImageFilter implements ImageConsumer, Cloneable +{ + /** + * The consumer this filter is filtering an image data stream for. + * It is initialized in the method <code>getFilterInstance</code>. + */ + protected ImageConsumer consumer = null; + + /** + * The <code>ImageConsumer</code> can use this method to request + * the pixels be delivered in top-down, left-right order. + * <br> + * The filter can respond in three different ways. + * <ul> + * <li>The default behavior is to forward the request to the + * <code>ImageProducer</code> + * using the method <code>requestTopDownLeftRightResend</code> + * and using the filter as the consumer.</li> + * <li>The filter has the pixels and can retransmit them in the + * top-down, left-right order.</li> + * <li>The filter can do nothing when this method is called.</li> + * </ul> + */ + public void resendTopDownLeftRight(ImageProducer ip) + { + ip.requestTopDownLeftRightResend(this); + } + + /** + * By default, returns a shallow copy of the object created by + * <code>Object.clone()</code> + * + * @see java.lang.Object#clone () + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + // This should never happen as this class implements the + // Cloneable interface. + throw new InternalError (); + } + } + + /** + * This is the only method which can set the + * <code>ImageConsumer</code> for this filter. By default a clone + * of this filter with the appropriate consumer set is returned. + * + * @see #clone () + */ + public ImageFilter getFilterInstance(ImageConsumer ic) + { + if ( ic == null ) + throw new IllegalArgumentException("null argument for ImageFilter.getFilterInstance(ImageConsumer)"); + + consumer = ic; + ImageFilter f = (ImageFilter)clone(); + consumer = null; + return f; + } + + /** + * An <code>ImageProducer</code> indicates the size of the image + * being produced using this method. A filter can override this + * method to intercept these calls from the producer in order to + * change either the width or the height before in turn calling + * the consumer's <code>setDimensions</code> method. + * + * @param width the width of the image + * @param height the height of the image + */ + public void setDimensions(int width, int height) + { + consumer.setDimensions(width, height); + } + + /** + * An <code>ImageProducer</code> can set a list of properties + * associated with this image by using this method. + * + * @param props the list of properties associated with this image + */ + public void setProperties(Hashtable props) + { + props.put("filters", "ImageFilter"); + consumer.setProperties(props); + } + + /** + * Override this method to process calls to this method from the + * <code>ImageProducer</code>. By default the <code>setColorModel</code> + * method of the consumer is called with the specified <code>model</code>. + * + * @param model the color model to be used most often by setPixels + * @see ColorModel */ + public void setColorModel(ColorModel model) + { + consumer.setColorModel(model); + } + + /** + * The <code>ImageProducer</code> should call this method with a + * bit mask of hints from any of <code>RANDOMPIXELORDER</code>, + * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>, + * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code> from the + * <code>ImageConsumer</code> interface. + * + * @param flags a bit mask of hints + * @see ImageConsumer + */ + public void setHints(int flags) + { + consumer.setHints(flags); + } + + /** + * This function delivers a rectangle of pixels where any + * pixel(m,n) is stored in the array as a <code>byte</code> at + * index (n * scansize + m + offset). + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param model the <code>ColorModel</code> used to translate the pixels + * @param pixels the array of pixel values + * @param offset the index of the first pixels in the <code>pixels</code> array + * @param scansize the width to use in extracting pixels from the <code>pixels</code> array + */ + public void setPixels(int x, int y, int w, int h, + ColorModel model, byte[] pixels, int offset, int scansize) + { + consumer.setPixels(x, y, w, h, model, pixels, offset, scansize); + } + + /** + * This function delivers a rectangle of pixels where any + * pixel(m,n) is stored in the array as an <code>int</code> at + * index (n * scansize + m + offset). + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param model the <code>ColorModel</code> used to translate the pixels + * @param pixels the array of pixel values + * @param offset the index of the first pixels in the <code>pixels</code> array + * @param scansize the width to use in extracting pixels from the <code>pixels</code> array + */ + public void setPixels(int x, int y, int w, int h, + ColorModel model, int[] pixels, int offset, int scansize) + { + consumer.setPixels(x, y, w, h, model, pixels, offset, scansize); + } + + /** + * The <code>ImageProducer</code> calls this method to indicate a + * single frame or the entire image is complete. The method is + * also used to indicate an error in loading or producing the + * image. + */ + public void imageComplete(int status) + { + consumer.imageComplete(status); + } +} + diff --git a/libjava/classpath/java/awt/image/ImageObserver.java b/libjava/classpath/java/awt/image/ImageObserver.java new file mode 100644 index 0000000..36dd013 --- /dev/null +++ b/libjava/classpath/java/awt/image/ImageObserver.java @@ -0,0 +1,129 @@ +/* ImageObserver.java -- Java interface for asynchronous updates to an image + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.Image; + +/** + * An object implementing the <code>ImageObserver</code> interface can + * receive updates on image construction from an + * <code>ImageProducer</code> asynchronously. + * + * @see ImageProducer + * @author C. Brian Jones (cbj@gnu.org) + */ +public interface ImageObserver +{ + /** + * The width of the image has been provided as the + * <code>width</code> argument to <code>imageUpdate</code>. + * + * @see #imageUpdate + */ + int WIDTH = 1; + + /** + * The height of the image has been provided as the + * <code>height</code> argument to <code>imageUpdate</code>. + * + * @see #imageUpdate + */ + int HEIGHT = 2; + + /** + * The properties of the image have been provided. + * + * @see #imageUpdate + * @see java.awt.Image#getProperty (java.lang.String, java.awt.image.ImageObserver) + */ + int PROPERTIES = 4; + + /** + * More pixels are now available for drawing a scaled variation of + * the image. + * + * @see #imageUpdate + */ + int SOMEBITS = 8; + + /** + * All the pixels needed to draw a complete frame of a multi-frame + * image are available. + * + * @see #imageUpdate + */ + int FRAMEBITS = 16; + + /** + * An image with a single frame, a static image, is complete. + * + * @see #imageUpdate + */ + int ALLBITS = 32; + + /** + * An error was encountered while producing the image. + * + * @see #imageUpdate + */ + int ERROR = 64; + + /** + * Production of the image was aborted. + * + * @see #imageUpdate + */ + int ABORT = 128; + + /** + * This is a callback method for an asynchronous image producer to + * provide updates on the production of the image as it happens. + * + * @param image the image the update refers to + * @param flags a bit mask indicating what is provided with this update + * @param x the x coordinate of the image + * @param y the y coordinate of the image + * @param width the width of the image + * @param height the height of the image + * + * @see java.awt.Image + */ + boolean imageUpdate(Image image, int flags, int x, + int y, int width, int height); +} diff --git a/libjava/classpath/java/awt/image/ImageProducer.java b/libjava/classpath/java/awt/image/ImageProducer.java new file mode 100644 index 0000000..4984668 --- /dev/null +++ b/libjava/classpath/java/awt/image/ImageProducer.java @@ -0,0 +1,85 @@ +/* ImageProducer.java -- Java interface for image production + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +/** + * An object implementing the <code>ImageProducer</code> interface can + * produce data for images. Each image has a corresponding + * <code>ImageProducer</code> which is needed for things such as + * resizing the image. + * + * @see ImageConsumer + * @author C. Brian Jones (cbj@gnu.org) + */ +public interface ImageProducer +{ + /** + * Used to register an <code>ImageConsumer</code> with this + * <code>ImageProducer</code>. + */ + void addConsumer(ImageConsumer ic); + + /** + * Used to determine if the given <code>ImageConsumer</code> is + * already registered with this <code>ImageProducer</code>. + */ + boolean isConsumer(ImageConsumer ic); + + /** + * Used to remove an <code>ImageConsumer</code> from the list of + * registered consumers for this <code>ImageProducer</code>. + */ + void removeConsumer(ImageConsumer ic); + + /** + * Used to register an <code>ImageConsumer</code> with this + * <code>ImageProducer</code> and then immediately start + * reconstruction of the image data to be delivered to all + * registered consumers. + */ + void startProduction(ImageConsumer ic); + + /** + * Used to register an <code>ImageConsumer</code> with this + * <code>ImageProducer</code> and then request that this producer + * resend the image data in the order top-down, left-right. + */ + void requestTopDownLeftRightResend(ImageConsumer ic); +} + diff --git a/libjava/classpath/java/awt/image/ImagingOpException.java b/libjava/classpath/java/awt/image/ImagingOpException.java new file mode 100644 index 0000000..ca40e9e --- /dev/null +++ b/libjava/classpath/java/awt/image/ImagingOpException.java @@ -0,0 +1,66 @@ +/* ImagingOpException.java -- indicates an imaging filter failure + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +/** + * This exception is thrown when <code>BufferedImageOp</code> or + * <code>RasterOp</code> filters cannot process an image. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see BufferedImageOp + * @see RasterOp + * @status updated to 1.4 + */ +public class ImagingOpException extends RuntimeException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 8026288481846276658L; + + /** + * Create a new instance with a descriptive error message. + * + * @param message the descriptive error message + */ + public ImagingOpException(String message) + { + super(message); + } +} // class ImagingOpException diff --git a/libjava/classpath/java/awt/image/IndexColorModel.java b/libjava/classpath/java/awt/image/IndexColorModel.java new file mode 100644 index 0000000..299b4dc --- /dev/null +++ b/libjava/classpath/java/awt/image/IndexColorModel.java @@ -0,0 +1,697 @@ +/* IndexColorModel.java -- Java class for interpreting Pixel objects + Copyright (C) 1999, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +import gnu.java.awt.Buffers; + +import java.awt.color.ColorSpace; +import java.math.BigInteger; + +/** + * Color model similar to pseudo visual in X11. + * <br><br> + * This color model maps linear pixel values to actual RGB and alpha colors. + * Thus, pixel values are indexes into the color map. Each color component is + * an 8-bit unsigned value. + * <br><br> + * The <code>IndexColorModel</code> supports a map of valid pixels, allowing + * the representation of holes in the the color map. The valid map is + * represented as a {@link BigInteger} where each bit indicates the validity + * of the map entry with the same index. + * <br><br> + * Colors can have alpha components for transparency support. If alpha + * component values aren't given, color values are opaque. The model also + * supports a reserved pixel value to represent completely transparent colors, + * no matter what the actual color component values are. + * <br><br> + * <code>IndexColorModel</code> supports anywhere from 1 to 16 bit index + * values. The allowed transfer types are {@link DataBuffer#TYPE_BYTE} and + * {@link DataBuffer#TYPE_USHORT}. + * + * @author C. Brian Jones (cbj@gnu.org) + */ +public class IndexColorModel extends ColorModel +{ + private int map_size; + private boolean opaque; // no alpha, but doesn't account for trans + private int trans = -1; + private int[] rgb; + private BigInteger validBits = BigInteger.ZERO; + + /** + * Creates a new indexed color model for <code>size</code> color elements + * with no alpha component. Each array must contain at least + * <code>size</code> elements. For each array, the i-th color is described + * by reds[i], greens[i] and blues[i]. + * + * @param bits the number of bits needed to represent <code>size</code> + * colors. + * @param size the number of colors in the color map. + * @param reds the red component of all colors. + * @param greens the green component of all colors. + * @param blues the blue component of all colors. + * + * @throws IllegalArgumentException if <code>bits</code> < 1 or + * <code>bits</code> > 16. + * @throws NullPointerException if any of the arrays is <code>null</code>. + * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater + * than the length of the component arrays. + */ + public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, + byte[] blues) + { + this(bits, size, reds, greens, blues, (byte[]) null); + } + + /** + * Creates a new indexed color model for <code>size</code> color elements. + * Each array must contain at least <code>size</code> elements. For each + * array, the i-th color is described by reds[i], greens[i] and blues[i]. + * All the colors are opaque except for the transparent color. + * + * @param bits the number of bits needed to represent <code>size</code> + * colors + * @param size the number of colors in the color map + * @param reds the red component of all colors + * @param greens the green component of all colors + * @param blues the blue component of all colors + * @param trans the index of the transparent color (use -1 for no + * transparent color). + * + * @throws IllegalArgumentException if <code>bits</code> < 1 or + * <code>bits</code> > 16. + * @throws NullPointerException if any of the arrays is <code>null</code>. + * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater + * than the length of the component arrays. + */ + public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, + byte[] blues, int trans) + { + super(bits, nArray(8, (0 <= trans && trans < size) ? 4 : 3), + ColorSpace.getInstance(ColorSpace.CS_sRGB), + (0 <= trans && trans < size), // hasAlpha + false, OPAQUE, + Buffers.smallestAppropriateTransferType(bits)); + if (bits < 1) + throw new IllegalArgumentException("bits < 1"); + if (bits > 16) + throw new IllegalArgumentException("bits > 16"); + if (size < 1) + throw new IllegalArgumentException("size < 1"); + map_size = size; + if (0 <= trans && trans < size) { + this.trans = trans; + transparency = BITMASK; + } + rgb = new int[size]; + for (int i = 0; i < size; i++) + { + rgb[i] = (0xff000000 + | ((reds[i] & 0xff) << 16) + | ((greens[i] & 0xff) << 8) + | (blues[i] & 0xff)); + } + // Generate a bigint with 1's for every pixel + validBits = validBits.setBit(size).subtract(BigInteger.ONE); + } + + /** + * Creates a new indexed color model for <code>size</code> color elements + * including alpha. Each array must contain at least <code>size</code> + * elements. For each array, the i-th color is described + * by reds[i], greens[i], blues[i] and alphas[i]. + * + * @param bits the number of bits needed to represent <code>size</code> + * colors. + * @param size the number of colors in the color map. + * @param reds the red component of all colors. + * @param greens the green component of all colors. + * @param blues the blue component of all colors. + * @param alphas the alpha component of all colors (<code>null</code> + * permitted). + * + * @throws IllegalArgumentException if <code>bits</code> < 1 or + * <code>bits</code> > 16. + * @throws NullPointerException if <code>reds</code>, <code>greens</code> or + * <code>blues</code> is <code>null</code>. + * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater + * than the length of the component arrays. + */ + public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, + byte[] blues, byte[] alphas) + { + super(bits, nArray(8, (alphas == null ? 3 : 4)), + ColorSpace.getInstance(ColorSpace.CS_sRGB), + (alphas != null), false, TRANSLUCENT, + Buffers.smallestAppropriateTransferType(bits)); + if (bits < 1) + throw new IllegalArgumentException("bits < 1"); + if (bits > 16) + throw new IllegalArgumentException("bits > 16"); + if (size < 1) + throw new IllegalArgumentException("size < 1"); + map_size = size; + opaque = (alphas == null); + + rgb = new int[size]; + if (alphas == null) + { + for (int i = 0; i < size; i++) + { + rgb[i] = (0xff000000 + | ((reds[i] & 0xff) << 16) + | ((greens[i] & 0xff) << 8) + | (blues[i] & 0xff)); + } + transparency = OPAQUE; + } + else + { + byte alphaZero = (byte) 0x00; + byte alphaOne = (byte) 0xFF; + for (int i = 0; i < size; i++) + { + alphaZero = (byte) (alphaZero | alphas[i]); + alphaOne = (byte) (alphaOne & alphas[i]); + rgb[i] = ((alphas[i] & 0xff) << 24 + | ((reds[i] & 0xff) << 16) + | ((greens[i] & 0xff) << 8) + | (blues[i] & 0xff)); + } + if ((alphaZero == (byte) 0x00) || (alphaOne == (byte) 0xFF)) + transparency = BITMASK; + else + transparency = TRANSLUCENT; + } + + // Generate a bigint with 1's for every pixel + validBits = validBits.setBit(size).subtract(BigInteger.ONE); + } + + /** + * Creates a new indexed color model using the color components in + * <code>cmap</code>. If <code>hasAlpha</code> is <code>true</code> then + * <code>cmap</code> contains an alpha component after each of the red, green + * and blue components. + * + * @param bits the number of bits needed to represent <code>size</code> + * colors + * @param size the number of colors in the color map + * @param cmap packed color components + * @param start the offset of the first color component in <code>cmap</code> + * @param hasAlpha <code>cmap</code> has alpha values + * @throws IllegalArgumentException if bits < 1, bits > 16, or size + * < 1. + * @throws NullPointerException if <code>cmap</code> is <code>null</code>. + */ + public IndexColorModel(int bits, int size, byte[] cmap, int start, + boolean hasAlpha) + { + this(bits, size, cmap, start, hasAlpha, -1); + } + + /** + * Construct an IndexColorModel from an array of red, green, blue, and + * optional alpha components. The component values are interleaved as RGB(A). + * + * @param bits the number of bits needed to represent <code>size</code> + * colors + * @param size the number of colors in the color map + * @param cmap interleaved color components + * @param start the offset of the first color component in <code>cmap</code> + * @param hasAlpha <code>cmap</code> has alpha values + * @param trans the index of the transparent color + * @throws IllegalArgumentException if bits < 1, bits > 16, or size + * < 1. + * @throws NullPointerException if <code>cmap</code> is <code>null</code>. + */ + public IndexColorModel(int bits, int size, byte[] cmap, int start, + boolean hasAlpha, int trans) + { + super(bits, nArray(8, hasAlpha || (0 <= trans && trans < size) ? 4 : 3), + ColorSpace.getInstance(ColorSpace.CS_sRGB), + hasAlpha || (0 <= trans && trans < size), false, OPAQUE, + Buffers.smallestAppropriateTransferType(bits)); + if (bits < 1) + throw new IllegalArgumentException("bits < 1"); + if (bits > 16) + throw new IllegalArgumentException("bits > 16"); + if (size < 1) + throw new IllegalArgumentException("size < 1"); + map_size = size; + opaque = !hasAlpha; + if (0 <= trans && trans < size) + this.trans = trans; + + rgb = new int[size]; + if (hasAlpha) + { + int alpha; + int alphaZero = 0x00; // use to detect all zeros + int alphaOne = 0xff; // use to detect all ones + for (int i = 0; i < size; i++) { + alpha = cmap[4 * i + 3 + start] & 0xff; + alphaZero = alphaZero | alpha; + alphaOne = alphaOne & alpha; + rgb[i] = + ( alpha << 24 + // red + | ((cmap[4 * i + start] & 0xff) << 16) + // green + | ((cmap[4 * i + 1 + start] & 0xff) << 8) + // blue + | (cmap[4 * i + 2 + start] & 0xff)); + } + if (alphaZero == 0) + transparency = BITMASK; + else if (alphaOne == 255) + transparency = (trans != -1 ? BITMASK : OPAQUE); + else + transparency = TRANSLUCENT; + } + else + { + for (int i = 0; i < size; i++) + rgb[i] = (0xff000000 + // red + | ((cmap[3 * i + start] & 0xff) << 16) + // green + | ((cmap[3 * i + 1 + start] & 0xff) << 8) + // blue + | (cmap[3 * i + 2 + start] & 0xff)); + if (trans != -1) + transparency = BITMASK; + } + + // Generate a bigint with 1's for every pixel + validBits = validBits.setBit(size).subtract(BigInteger.ONE); + } + + /** + * Construct an IndexColorModel from an array of <code>size</code> packed + * colors. Each int element contains 8-bit red, green, blue, and optional + * alpha values packed in order. If hasAlpha is false, then all the colors + * are opaque except for the transparent color. + * + * @param bits the number of bits needed to represent <code>size</code> + * colors + * @param size the number of colors in the color map + * @param cmap packed color components + * @param start the offset of the first color component in <code>cmap</code> + * @param hasAlpha <code>cmap</code> has alpha values + * @param trans the index of the transparent color + * @param transferType {@link DataBuffer#TYPE_BYTE} or + {@link DataBuffer#TYPE_USHORT}. + * @throws IllegalArgumentException if bits < 1, bits > 16, or size + * < 1. + * @throws IllegalArgumentException if <code>transferType</code> is something + * other than {@link DataBuffer#TYPE_BYTE} or + * {@link DataBuffer#TYPE_USHORT}. + */ + public IndexColorModel(int bits, int size, int[] cmap, int start, + boolean hasAlpha, int trans, int transferType) + { + super(bits, + nArray(8, 4), // bits for each channel + ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB + true, // has alpha + false, // not premultiplied + TRANSLUCENT, transferType); + if (transferType != DataBuffer.TYPE_BYTE + && transferType != DataBuffer.TYPE_USHORT) + throw new IllegalArgumentException(); + if (bits > 16) + throw new IllegalArgumentException("bits > 16"); + if (size < 1) + throw new IllegalArgumentException("size < 1"); + map_size = size; + opaque = !hasAlpha; + if (0 <= trans && trans < size) + this.trans = trans; + + rgb = new int[size]; + if (!hasAlpha) + for (int i = 0; i < size; i++) + rgb[i] = cmap[i + start] | 0xff000000; + else + System.arraycopy(cmap, start, rgb, 0, size); + + // Generate a bigint with 1's for every pixel + validBits = validBits.setBit(size).subtract(BigInteger.ONE); + } + + /** + * Construct an IndexColorModel using a colormap with holes. + * <br><br> + * The IndexColorModel is built from the array of ints defining the + * colormap. Each element contains red, green, blue, and alpha + * components. The ColorSpace is sRGB. The transparency value is + * automatically determined. + * <br><br> + * This constructor permits indicating which colormap entries are valid, + * using the validBits argument. Each entry in cmap is valid if the + * corresponding bit in validBits is set. + * + * @param bits the number of bits needed to represent <code>size</code> + * colors. + * @param size the number of colors in the color map. + * @param cmap packed color components. + * @param start the offset of the first color component in <code>cmap</code>. + * @param transferType {@link DataBuffer#TYPE_BYTE} or + * {@link DataBuffer#TYPE_USHORT}. + * @param validBits a map of the valid entries in <code>cmap</code>. + * @throws IllegalArgumentException if bits < 1, bits > 16, or size + * < 1. + * @throws IllegalArgumentException if transferType is something other than + * {@link DataBuffer#TYPE_BYTE} or {@link DataBuffer#TYPE_USHORT}. + */ + public IndexColorModel(int bits, int size, int[] cmap, int start, + int transferType, BigInteger validBits) + { + super(bits, // total bits, sRGB, four channels + nArray(8, 4), // bits for each channel + ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB + true, // has alpha + false, // not premultiplied + TRANSLUCENT, transferType); + if (transferType != DataBuffer.TYPE_BYTE + && transferType != DataBuffer.TYPE_USHORT) + throw new IllegalArgumentException(); + if (bits > 16) + throw new IllegalArgumentException("bits > 16"); + if (size < 1) + throw new IllegalArgumentException("size < 1"); + map_size = size; + opaque = false; + this.trans = -1; + this.validBits = validBits; + + rgb = new int[size]; + if (!hasAlpha) + for (int i = 0; i < size; i++) + rgb[i] = cmap[i + start] | 0xff000000; + else + System.arraycopy(cmap, start, rgb, 0, size); + } + + /** + * Returns the size of the color lookup table. + * + * @return The size of the color lookup table. + */ + public final int getMapSize() + { + return map_size; + } + + /** + * Get the index of the transparent color in this color model. + * + * @return The index of the color that is considered transparent, or -1 if + * there is no transparent color. + */ + public final int getTransparentPixel() + { + return trans; + } + + /** + * Fills the supplied array with the red component of each color in the + * lookup table. + * + * @param r an array that is at least as large as {@link #getMapSize()}. + * @throws NullPointerException if <code>r</code> is <code>null</code>. + * @throws ArrayIndexOutOfBoundsException if <code>r</code> has less + * than {@link #getMapSize()} elements. + */ + public final void getReds(byte[] r) + { + int i; + for (i = 0; i < map_size; i++) + r[i] = (byte) ((0x00FF0000 & rgb[i]) >> 16); + } + + /** + * Fills the supplied array with the green component of each color in the + * lookup table. + * + * @param g an array that is at least as large as {@link #getMapSize()}. + * @throws NullPointerException if <code>g</code> is <code>null</code>. + * @throws ArrayIndexOutOfBoundsException if <code>g</code> has less + * than {@link #getMapSize()} elements. + */ + public final void getGreens(byte[] g) + { + int i; + for (i = 0; i < map_size; i++) + g[i] = (byte) ((0x0000FF00 & rgb[i]) >> 8); + } + + /** + * Fills the supplied array with the blue component of each color in the + * lookup table. + * + * @param b an array that is at least as large as {@link #getMapSize()}. + * @throws NullPointerException if <code>b</code> is <code>null</code>. + * @throws ArrayIndexOutOfBoundsException if <code>b</code> has less + * than {@link #getMapSize()} elements. + */ + public final void getBlues(byte[] b) + { + int i; + for (i = 0; i < map_size; i++) + b[i] = (byte) (0x000000FF & rgb[i]); + } + + /** + * Fills the supplied array with the alpha component of each color in the + * lookup table. If the model has a transparent pixel specified, the alpha + * for that pixel will be 0. + * + * @param a an array that is at least as large as {@link #getMapSize()}. + * @throws NullPointerException if <code>a</code> is <code>null</code>. + * @throws ArrayIndexOutOfBoundsException if <code>a</code> has less + * than {@link #getMapSize()} elements. + */ + public final void getAlphas(byte[] a) + { + int i; + for (i = 0; i < map_size; i++) + if (i == trans) + a[i] = (byte) 0; + else + a[i] = (byte) ((0xFF000000 & rgb[i]) >> 24); + } + + /** + * Returns the red component of the color in the lookup table for the + * given pixel value. + * + * @param pixel the pixel lookup value. + * + * @return The red component of the color in the lookup table. + * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. + */ + public final int getRed(int pixel) + { + if (pixel < map_size) + return (0x00FF0000 & rgb[pixel]) >> 16; + + return 0; + } + + /** + * Returns the green component of the color in the lookup table for the + * given pixel value. + * + * @param pixel the pixel lookup value. + * + * @return The green component of the color in the lookup table. + * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. + */ + public final int getGreen(int pixel) + { + if (pixel < map_size) + return (0x0000FF00 & rgb[pixel]) >> 8; + + return 0; + } + + /** + * Returns the blue component of the color in the lookup table for the + * given pixel value. + * + * @param pixel the pixel lookup value. + * + * @return The blue component of the color in the lookup table. + * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. + */ + public final int getBlue(int pixel) + { + if (pixel < map_size) + return 0x000000FF & rgb[pixel]; + + return 0; + } + + /** + * Returns the alpha component of the color in the lookup table for the + * given pixel value. If no alpha channel was specified when the color model + * was created, then 255 is returned for all pixels except the transparent + * pixel (if one is defined - see {@link #getTransparentPixel()}) which + * returns an alpha of 0. + * + * @param pixel the pixel lookup value. + * + * @return The alpha component of the color in the lookup table (in the + * range 0 to 255). + * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. + */ + public final int getAlpha(int pixel) + { + if (opaque && pixel != trans) + return 255; + if ((pixel == trans && trans != -1) || pixel >= map_size) + return 0; + + return (0xFF000000 & rgb[pixel]) >> 24; + } + + /** + * Get the RGB color value of the given pixel using the default + * RGB color model. + * + * @param pixel the pixel lookup value. + * @return The RGB color value. + * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. + */ + public final int getRGB(int pixel) + { + if (pixel >= 0 && pixel < map_size) + return rgb[pixel]; + + return 0; + } + + /** + * Get the RGB color values of all pixels in the map using the default + * RGB color model. + * + * @param rgb The destination array. + */ + public final void getRGBs(int[] rgb) + { + System.arraycopy(this.rgb, 0, rgb, 0, map_size); + } + + /** + * Return <code>true</code> if the lookup table contains valid data for + * <code>pixel</code>, and <code>false</code> otherwise. + * + * @param pixel the pixel value used to index the color lookup table. + * @return <code>true</code> if <code>pixel</code> is valid, + * <code>false</code> otherwise. + */ + public boolean isValid(int pixel) + { + if (pixel >= 0) + return validBits.testBit(pixel); + return false; + } + + /** + * Return <code>true</code> if all pixels are valid, <code>false</code> + * otherwise. + * + * @return <code>true</code> if all pixels are valid, <code>false</code> + * otherwise. + */ + public boolean isValid() + { + // Generate a bigint with 1's for every pixel + BigInteger allbits = new BigInteger("0"); + allbits = allbits.setBit(map_size); + allbits = allbits.subtract(new BigInteger("1")); + return allbits.equals(validBits); + } + + /** + * Returns a binary value ({@link BigInteger}) where each bit represents an + * entry in the color lookup table. If the bit is on, the entry is valid. + * + * @return The binary value. + */ + public BigInteger getValidPixels() + { + return validBits; + } + + /** + * Construct a {@link BufferedImage} with rgb pixel values from a + * {@link Raster}. + * + * Constructs a new BufferedImage in which each pixel is an RGBA int from + * a Raster with index-valued pixels. If this model has no alpha component + * or transparent pixel, the type of the new BufferedImage is TYPE_INT_RGB. + * Otherwise the type is TYPE_INT_ARGB. If forceARGB is true, the type is + * forced to be TYPE_INT_ARGB no matter what. + * + * @param raster The source of pixel values. + * @param forceARGB True if type must be TYPE_INT_ARGB. + * @return New BufferedImage with RBGA int pixel values. + */ + public BufferedImage convertToIntDiscrete(Raster raster, boolean forceARGB) + { + int type = forceARGB ? BufferedImage.TYPE_INT_ARGB + : ((opaque && trans == -1) ? BufferedImage.TYPE_INT_RGB : + BufferedImage.TYPE_INT_ARGB); + + // FIXME: assuming that raster has only 1 band since pixels are supposed + // to be int indexes. + // FIXME: it would likely be more efficient to fetch a complete array, + // but it would take much more memory. + // FIXME: I'm not sure if transparent pixels or alpha values need special + // handling here. + BufferedImage im = new BufferedImage(raster.width, raster.height, type); + for (int x = raster.minX; x < raster.width + raster.minX; x++) + for (int y = raster.minY; y < raster.height + raster.minY; y++) + im.setRGB(x, y, rgb[raster.getSample(x, y, 0)]); + + return im; + } +} diff --git a/libjava/classpath/java/awt/image/Kernel.java b/libjava/classpath/java/awt/image/Kernel.java new file mode 100644 index 0000000..f7c29c3 --- /dev/null +++ b/libjava/classpath/java/awt/image/Kernel.java @@ -0,0 +1,143 @@ +/* Kernel.java -- Java class for an image processing kernel + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +/** + * Kernel represents an image processing kernel. It gets used to hold + * convolution filters among other purposes. It stores an array of float + * values representing a 2-dimensional array in row-major order. + * + * @author Jerry Quinn (jlquinn@optonline.net) + * @version 1.0 + */ +public class Kernel implements Cloneable +{ + private final int width; + private final int height; + private final float[] data; + + /** + * Creates a new <code>Kernel</code> instance. + * + * @param width The 2D width of data. + * @param height The 2D height of data. + * @param data The source data array. + * @exception IllegalArgumentException if width * height < data.length. + */ + public Kernel(int width, int height, float[] data) + throws IllegalArgumentException + { + this.width = width; + this.height = height; + if (data.length < width * height || width < 0 || height < 0) + throw new IllegalArgumentException(); + this.data = new float[width * height]; + System.arraycopy(data, 0, this.data, 0, width * height); + } + + /** + * Return the X origin: (width - 1) / 2 + */ + public final int getXOrigin() + { + return (width - 1) / 2; + } + + /** + * Return the Y origin: (height - 1) / 2 + */ + public final int getYOrigin() + { + return (height - 1) / 2; + } + + /** + * @return The kernel width. + */ + public final int getWidth() + { + return width; + } + + /** + * @return The kernel height. + */ + public final int getHeight() + { + return height; + } + + /** + * Return the kernel data. + * + * If data is null, allocates a new array and returns it. Otherwise, the + * kernel values are copied into data. + * + * @param data Array to copy values into, or null. + * @return The array with copied values. + * @exception IllegalArgumentException if data != null and too small. + */ + public final float[] getKernelData(float[] data) + throws IllegalArgumentException + { + if (data == null) + return (float[])this.data.clone(); + + if (data.length < this.data.length) + throw new IllegalArgumentException(); + + System.arraycopy(this.data, 0, data, 0, this.data.length); + return data; + } + + /** + * @return a clone of this Kernel. + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // Impossible + } + } +} diff --git a/libjava/classpath/java/awt/image/LookupOp.java b/libjava/classpath/java/awt/image/LookupOp.java new file mode 100644 index 0000000..f131daa --- /dev/null +++ b/libjava/classpath/java/awt/image/LookupOp.java @@ -0,0 +1,252 @@ +/* LookupOp.java -- Filter that converts each pixel using a lookup table. + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +/** + * LookupOp is a filter that converts each pixel using a lookup table. + * + * For filtering Rasters, the lookup table must have either one component + * that is applied to all bands, or one component for every band in the + * Rasters. + * + * For BufferedImages, the lookup table may apply to both color and alpha + * components. If the lookup table contains one component, or if there are + * the same number of components as color components in the source, the table + * applies to all color components. Otherwise the table applies to all + * components including alpha. Alpha premultiplication is ignored during the + * lookup filtering. + * + * After filtering, if color conversion is necessary, the conversion happens, + * taking alpha premultiplication into account. + * + * @author jlquinn + */ +public class LookupOp implements BufferedImageOp, RasterOp +{ + private LookupTable lut; + private RenderingHints hints; + + /** Construct a new LookupOp. + * + * @param lookup LookupTable to use. + * @param hints Rendering hints (can be null). + */ + public LookupOp(LookupTable lookup, RenderingHints hints) + { + lut = lookup; + this.hints = hints; + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, java.awt.image.BufferedImage) + */ + public BufferedImage filter(BufferedImage src, BufferedImage dst) + { + if (src.getColorModel() instanceof IndexColorModel) + throw new IllegalArgumentException("LookupOp.filter: IndexColorModel " + + "not allowed"); + if (dst == null) + dst = createCompatibleDestImage(src, src.getColorModel()); + + // Set up for potential colormodel mismatch + BufferedImage tgt; + if (dst.getColorModel().equals(src.getColorModel())) + tgt = dst; + else + tgt = createCompatibleDestImage(src, src.getColorModel()); + + Raster sr = src.getRaster(); + WritableRaster dr = tgt.getRaster(); + + if (src.getColorModel().hasAlpha() && + (lut.getNumComponents() == 1 || + lut.getNumComponents() == src.getColorModel().getNumColorComponents())) + { + // Need to ignore alpha for lookup + int[] dbuf = new int[src.getColorModel().getNumComponents()]; + int tmpBands = src.getColorModel().getNumColorComponents(); + int[] tmp = new int[tmpBands]; + + // Filter the pixels + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + { + // Filter only color components, but also copy alpha + sr.getPixel(x, y, dbuf); + System.arraycopy(dbuf, 0, tmp, 0, tmpBands); + dr.setPixel(x, y, lut.lookupPixel(tmp, dbuf)); + } + } + else if (lut.getNumComponents() != 1 + && + lut.getNumComponents() != src.getColorModel().getNumComponents()) + throw new IllegalArgumentException("LookupOp.filter: " + + "Incompatible lookup " + + "table and source image"); + + // No alpha to ignore + int[] dbuf = new int[src.getColorModel().getNumComponents()]; + + // Filter the pixels + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + dr.setPixel(x, y, lut.lookupPixel(sr.getPixel(x, y, dbuf), dbuf)); + + if (tgt != dst) + { + // Convert between color models. + // TODO Check that premultiplied alpha is handled correctly here. + Graphics2D gg = dst.createGraphics(); + gg.setRenderingHints(hints); + gg.drawImage(tgt, 0, 0, null); + gg.dispose(); + } + + return dst; + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage) + */ + public Rectangle2D getBounds2D(BufferedImage src) + { + return src.getRaster().getBounds(); + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel) + */ + public BufferedImage createCompatibleDestImage(BufferedImage src, + ColorModel dstCM) + { + // FIXME: set properties to those in src + return new BufferedImage(dstCM, + src.getRaster().createCompatibleWritableRaster(), + src.isPremultiplied, null); + } + + /** Return corresponding destination point for source point. + * + * LookupOp will return the value of src unchanged. + * @param src The source point. + * @param dst The destination point. + * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D) + */ + public Point2D getPoint2D(Point2D src, Point2D dst) + { + if (dst == null) + return (Point2D) src.clone(); + + dst.setLocation(src); + return dst; + } + + /** Return the LookupTable for this op. */ + public LookupTable getTable() + { + return lut; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getRenderingHints() + */ + public RenderingHints getRenderingHints() + { + return hints; + } + + /** Filter a raster through a lookup table. + * + * Applies the lookup table for this Rasterop to each pixel of src and + * puts the results in dest. If dest is null, a new Raster is created and + * returned. + * + * @param src The source raster. + * @param dest The destination raster. + * @return The WritableRaster with the filtered pixels. + * @throws IllegalArgumentException if lookup table has more than one + * component but not the same as src and dest. + * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster) + */ + public WritableRaster filter(Raster src, WritableRaster dest) + { + if (dest == null) + // Allocate a raster if needed + dest = createCompatibleDestRaster(src); + else + if (src.getNumBands() != dest.getNumBands()) + throw new IllegalArgumentException(); + + if (lut.getNumComponents() != 1 + && lut.getNumComponents() != src.getNumBands()) + throw new IllegalArgumentException(); + + + // Allocate pixel storage. + int[] tmp = new int[src.getNumBands()]; + + // Filter the pixels + for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) + for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + dest.setPixel(x, y, lut.lookupPixel(src.getPixel(x, y, tmp), tmp)); + return dest; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster) + */ + public Rectangle2D getBounds2D(Raster src) + { + return src.getBounds(); + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster) + */ + public WritableRaster createCompatibleDestRaster(Raster src) + { + return src.createCompatibleWritableRaster(); + } + +} diff --git a/libjava/classpath/java/awt/image/LookupTable.java b/libjava/classpath/java/awt/image/LookupTable.java new file mode 100644 index 0000000..f814b8e --- /dev/null +++ b/libjava/classpath/java/awt/image/LookupTable.java @@ -0,0 +1,109 @@ +/* LookupTable.java -- Java class for a pixel translation table. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +/** + * LookupTable represents translation arrays for pixel values. It wraps one + * or more data arrays for each layer (or component) in an image, such as + * Alpha, R, G, and B. When doing translation, the offset is subtracted from + * the pixel values to allow a subset of an array to be used. + * + * @see ByteLookupTable + * @see ShortLookupTable + * + * @author Jerry Quinn (jlquinn@optonline.net) + * @version 1.0 + */ +public abstract class LookupTable +{ + // Not protected since that's part of the public API. + int offset; + int numComponents; + + /** + * Creates a new <code>LookupTable</code> instance. + * + * If numComponents is 1, the same translation table is used for all pixel + * components. + * + * @param offset Offset to be subtracted. + * @param numComponents Number of image components. + * @exception IllegalArgumentException if offset < 0 or numComponents < 1. + */ + protected LookupTable(int offset, int numComponents) + throws IllegalArgumentException + { + if (offset < 0 || numComponents < 1) + throw new IllegalArgumentException(); + this.offset = offset; + this.numComponents = numComponents; + } + + /** Return the number of components. */ + public int getNumComponents() + { + return numComponents; + } + + /** Return the offset. */ + public int getOffset() + { + return offset; + } + + + /** + * Return translated values for a pixel. + * + * For each value in the pixel src, use the value minus offset as an index + * in the component array and copy the value there to the output for the + * component. If dest is null, the output is a new array, otherwise the + * translated values are written to dest. Dest can be the same array as + * src. + * + * For example, if the pixel src is [2, 4, 3], and offset is 1, the output + * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the + * translation arrays. + * + * @param src Component values of a pixel. + * @param dest Destination array for values, or null. + * @return Translated values for the pixel. + */ + public abstract int[] lookupPixel(int[] src, int[] dest); +} diff --git a/libjava/classpath/java/awt/image/MemoryImageSource.java b/libjava/classpath/java/awt/image/MemoryImageSource.java new file mode 100644 index 0000000..c27e0bf --- /dev/null +++ b/libjava/classpath/java/awt/image/MemoryImageSource.java @@ -0,0 +1,373 @@ +/* MemoryImageSource.java -- Java class for providing image data + Copyright (C) 1999, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.util.Hashtable; +import java.util.Vector; + +public class MemoryImageSource implements ImageProducer +{ + private boolean animated = false; + private boolean fullbuffers = false; + private int[] pixeli; + private int width; + private int height; + private int offset; + private int scansize; + private byte[] pixelb; + private ColorModel cm; + private Hashtable props = new Hashtable(); + private Vector consumers = new Vector(); + + /** + * Construct an image producer that reads image data from a byte + * array. + * + * @param w width of image + * @param h height of image + * @param cm the color model used to represent pixel values + * @param pix a byte array of pixel values + * @param off the offset into the array at which the first pixel is stored + * @param scan the number of array elements that represents a single pixel row + */ + public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off, + int scan) + { + this(w, h, cm, pix, off, scan, null); + } + + /** + * Constructs an ImageProducer from memory + */ + public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off, + int scan, Hashtable props) + { + width = w; + height = h; + this.cm = cm; + offset = off; + scansize = scan; + this.props = props; + int max = ((scansize > width) ? scansize : width); + pixelb = pix; + } + + /** + * Construct an image producer that reads image data from an + * integer array. + * + * @param w width of image + * @param h height of image + * @param cm the color model used to represent pixel values + * @param pix an integer array of pixel values + * @param off the offset into the array at which the first pixel is stored + * @param scan the number of array elements that represents a single pixel row + */ + public MemoryImageSource(int w, int h, ColorModel cm, int[] pix, int off, + int scan) + { + this(w, h, cm, pix, off, scan, null); + } + + /** + Constructs an ImageProducer from memory + */ + public MemoryImageSource(int w, int h, ColorModel cm, int[] pix, int off, + int scan, Hashtable props) + { + width = w; + height = h; + this.cm = cm; + offset = off; + scansize = scan; + this.props = props; + int max = ((scansize > width) ? scansize : width); + pixeli = pix; + } + + /** + * Constructs an ImageProducer from memory using the default RGB ColorModel + */ + public MemoryImageSource(int w, int h, int[] pix, int off, int scan, + Hashtable props) + { + this(w, h, ColorModel.getRGBdefault(), pix, off, scan, props); + } + + /** + * Constructs an ImageProducer from memory using the default RGB ColorModel + */ + public MemoryImageSource(int w, int h, int[] pix, int off, int scan) + { + this(w, h, ColorModel.getRGBdefault(), pix, off, scan, null); + } + + /** + * Used to register an <code>ImageConsumer</code> with this + * <code>ImageProducer</code>. + */ + public synchronized void addConsumer(ImageConsumer ic) + { + if (consumers.contains(ic)) + return; + + consumers.addElement(ic); + } + + /** + * Used to determine if the given <code>ImageConsumer</code> is + * already registered with this <code>ImageProducer</code>. + */ + public synchronized boolean isConsumer(ImageConsumer ic) + { + if (consumers.contains(ic)) + return true; + return false; + } + + /** + * Used to remove an <code>ImageConsumer</code> from the list of + * registered consumers for this <code>ImageProducer</code>. + */ + public synchronized void removeConsumer(ImageConsumer ic) + { + consumers.removeElement(ic); + } + + /** + * Used to register an <code>ImageConsumer</code> with this + * <code>ImageProducer</code> and then immediately start + * reconstruction of the image data to be delivered to all + * registered consumers. + */ + public void startProduction(ImageConsumer ic) + { + if (! (consumers.contains(ic))) + consumers.addElement(ic); + + Vector list = (Vector) consumers.clone(); + for (int i = 0; i < list.size(); i++) + { + ic = (ImageConsumer) list.elementAt(i); + sendPicture(ic); + if (animated) + ic.imageComplete(ImageConsumer.SINGLEFRAME); + else + ic.imageComplete(ImageConsumer.STATICIMAGEDONE); + } + } + + /** + * Used to register an <code>ImageConsumer</code> with this + * <code>ImageProducer</code> and then request that this producer + * resend the image data in the order top-down, left-right. + */ + public void requestTopDownLeftRightResend(ImageConsumer ic) + { + startProduction(ic); + } + + /** + * Changes a flag to indicate whether this MemoryImageSource supports + * animations. + * + * @param animated A flag indicating whether this class supports animations + */ + public synchronized void setAnimated(boolean animated) + { + this.animated = animated; + } + + /** + * A flag to indicate whether or not to send full buffer updates when + * sending animation. If this flag is set then full buffers are sent + * in the newPixels methods instead of just regions. + * + * @param fullbuffers - a flag indicating whether to send the full buffers + */ + public synchronized void setFullBufferUpdates(boolean fullbuffers) + { + this.fullbuffers = fullbuffers; + } + + /** + * Send an animation frame to the image consumers. + */ + public void newPixels() + { + if (animated == true) + { + ImageConsumer ic; + Vector list = (Vector) consumers.clone(); + for (int i = 0; i < list.size(); i++) + { + ic = (ImageConsumer) list.elementAt(i); + sendPicture(ic); + ic.imageComplete(ImageConsumer.SINGLEFRAME); + } + } + } + + private void sendPicture(ImageConsumer ic) + { + ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT); + if (props != null) + ic.setProperties(props); + ic.setDimensions(width, height); + ic.setColorModel(cm); + if (pixeli != null) + ic.setPixels(0, 0, width, height, cm, pixeli, offset, scansize); + else + ic.setPixels(0, 0, width, height, cm, pixelb, offset, scansize); + } + + /** + * Send an animation frame to the image consumers containing the specified + * pixels unless setFullBufferUpdates is set. + */ + public synchronized void newPixels(int x, int y, int w, int h) + { + if (animated == true) + { + if (fullbuffers) + newPixels(); + else + { + ImageConsumer ic; + Vector list = (Vector) consumers.clone(); + for (int i = 0; i < list.size(); i++) + { + ic = (ImageConsumer) list.elementAt(i); + ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT); + if (props != null) + ic.setProperties(props); + if (pixeli != null) + { + int[] pixelbuf = new int[w * h]; + for (int row = y; row < y + h; row++) + System.arraycopy(pixeli, row * scansize + x + offset, + pixelbuf, 0, w * h); + ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w); + } + else + { + byte[] pixelbuf = new byte[w * h]; + for (int row = y; row < y + h; row++) + System.arraycopy(pixelb, row * scansize + x + offset, + pixelbuf, 0, w * h); + + ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w); + } + ic.imageComplete(ImageConsumer.SINGLEFRAME); + } + } + } + } + + /** + * Send an animation frame to the image consumers containing the specified + * pixels unless setFullBufferUpdates is set. + * + * If framenotify is set then a notification is sent when the frame + * is sent otherwise no status is sent. + */ + public synchronized void newPixels(int x, int y, int w, int h, + boolean framenotify) + { + if (animated == true) + { + if (fullbuffers) + newPixels(); + else + { + ImageConsumer ic; + Vector list = (Vector) consumers.clone(); + for (int i = 0; i < list.size(); i++) + { + ic = (ImageConsumer) list.elementAt(i); + ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT); + if (props != null) + ic.setProperties(props); + if (pixeli != null) + { + int[] pixelbuf = new int[w * h]; + for (int row = y; row < y + h; row++) + System.arraycopy(pixeli, row * scansize + x + offset, + pixelbuf, 0, w * h); + ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w); + } + else + { + byte[] pixelbuf = new byte[w * h]; + for (int row = y; row < y + h; row++) + System.arraycopy(pixelb, row * scansize + x + offset, + pixelbuf, 0, w * h); + ic.setPixels(x, y, w, h, cm, pixelbuf, 0, w); + } + if (framenotify == true) + ic.imageComplete(ImageConsumer.SINGLEFRAME); + } + } + } + } + + public synchronized void newPixels(byte[] newpix, ColorModel newmodel, + int offset, int scansize) + { + pixeli = null; + pixelb = newpix; + cm = newmodel; + this.offset = offset; + this.scansize = scansize; + if (animated == true) + newPixels(); + } + + public synchronized void newPixels(int[] newpix, ColorModel newmodel, + int offset, int scansize) + { + pixelb = null; + pixeli = newpix; + cm = newmodel; + this.offset = offset; + this.scansize = scansize; + if (animated == true) + newPixels(); + } +} diff --git a/libjava/classpath/java/awt/image/MultiPixelPackedSampleModel.java b/libjava/classpath/java/awt/image/MultiPixelPackedSampleModel.java new file mode 100644 index 0000000..18a6e55 --- /dev/null +++ b/libjava/classpath/java/awt/image/MultiPixelPackedSampleModel.java @@ -0,0 +1,388 @@ +/* Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +import gnu.java.awt.Buffers; + +/** + * MultiPixelPackedSampleModel provides a single band model that supports + * multiple pixels in a single unit. Pixels have 2^n bits and 2^k pixels fit + * per data element. + * + * @author Jerry Quinn (jlquinn@optonline.net) + */ +public class MultiPixelPackedSampleModel extends SampleModel +{ + private int scanlineStride; + private int[] bitMasks; + private int[] bitOffsets; + private int[] sampleSize; + private int dataBitOffset; + private int elemBits; + private int numberOfBits; + private int numElems; + + public MultiPixelPackedSampleModel(int dataType, int w, int h, + int numberOfBits) + { + this(dataType, w, h, numberOfBits, 0, 0); + } + + public MultiPixelPackedSampleModel(int dataType, int w, int h, + int numberOfBits, int scanlineStride, + int dataBitOffset) + { + super(dataType, w, h, 1); + + switch (dataType) + { + case DataBuffer.TYPE_BYTE: + elemBits = 8; + break; + case DataBuffer.TYPE_USHORT: + elemBits = 16; + break; + case DataBuffer.TYPE_INT: + elemBits = 32; + break; + default: + throw new IllegalArgumentException("MultiPixelPackedSampleModel" + + " unsupported dataType"); + } + + this.dataBitOffset = dataBitOffset; + + this.numberOfBits = numberOfBits; + if (numberOfBits > elemBits) + throw new RasterFormatException("MultiPixelPackedSampleModel pixel size" + + " larger than dataType"); + switch (numberOfBits) + { + case 1: case 2: case 4: case 8: case 16: case 32: break; + default: + throw new RasterFormatException("MultiPixelPackedSampleModel pixel" + + " size not 2^n bits"); + } + numElems = elemBits / numberOfBits; + + // Compute scan line large enough for w pixels. + if (scanlineStride == 0) + scanlineStride = ((dataBitOffset + w * numberOfBits) / elemBits); + this.scanlineStride = scanlineStride; + + + sampleSize = new int[1]; + sampleSize[0] = numberOfBits; + + bitMasks = new int[numElems]; + bitOffsets = new int[numElems]; + for (int i=0; i < numElems; i++) + { + bitOffsets[numElems - i- 1] = numberOfBits * i; + bitMasks[numElems - i - 1] = ((1 << numberOfBits) - 1) << + bitOffsets[numElems - i - 1]; + } + } + + public SampleModel createCompatibleSampleModel(int w, int h) + { + /* FIXME: We can avoid recalculation of bit offsets and sample + sizes here by passing these from the current instance to a + special private constructor. */ + return new MultiPixelPackedSampleModel(dataType, w, h, numberOfBits); + } + + + /** + * Creates a DataBuffer for holding pixel data in the format and + * layout described by this SampleModel. The returned buffer will + * consist of one single bank. + */ + public DataBuffer createDataBuffer() + { + int size; + + // FIXME: The comment refers to SinglePixelPackedSampleModel. See if the + // same can be done for MultiPixelPackedSampleModel. + // We can save (scanlineStride - width) pixels at the very end of + // the buffer. The Sun reference implementation (J2SE 1.3.1 and + // 1.4.1_01) seems to do this; tested with Mauve test code. + size = scanlineStride * height; + + return Buffers.createBuffer(getDataType(), size); + } + + + public int getNumDataElements() + { + return 1; + } + + public int[] getSampleSize() + { + return sampleSize; + } + + public int getSampleSize(int band) + { + return sampleSize[0]; + } + + public int getOffset(int x, int y) + { + return scanlineStride * y + ((dataBitOffset + x*numberOfBits) / elemBits); + } + + public int getBitOffset(int x) + { + return (dataBitOffset + x*numberOfBits) % elemBits; + } + + public int getDataBitOffset() + { + return dataBitOffset; + } + + public int getScanlineStride() + { + return scanlineStride; + } + + public int getPixelBitStride() + { + return numberOfBits; + } + + + public SampleModel createSubsetSampleModel(int[] bands) + { + int numBands = bands.length; + if (numBands != 1) + throw new RasterFormatException("MultiPixelPackedSampleModel only" + + " supports one band"); + + return new MultiPixelPackedSampleModel(dataType, width, height, + numberOfBits, scanlineStride, + dataBitOffset); + } + + /** + * Extract one pixel and return in an array of transfer type. + * + * Extracts the pixel at x, y from data and stores into the 0th index of the + * array obj, since there is only one band. If obj is null, a new array of + * getTransferType() is created. + * + * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>. + * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>. + * @param obj The primitive array to store the pixels into or null to force creation. + * @param data The DataBuffer that is the source of the pixel data. + * @return The primitive array containing the pixel data. + * @see java.awt.image.SampleModel#getDataElements(int, int, java.lang.Object, java.awt.image.DataBuffer) + */ + public Object getDataElements(int x, int y, Object obj, + DataBuffer data) + { + int pixel = getSample(x, y, 0, data); + switch (getTransferType()) + { + case DataBuffer.TYPE_BYTE: + if (obj == null) obj = new byte[1]; + ((byte[])obj)[0] = (byte)pixel; + return obj; + case DataBuffer.TYPE_USHORT: + if (obj == null) obj = new short[1]; + ((short[])obj)[0] = (short)pixel; + return obj; + case DataBuffer.TYPE_INT: + if (obj == null) obj = new int[1]; + ((int[])obj)[0] = pixel; + return obj; + default: + // Seems like the only sensible thing to do. + throw new ClassCastException(); + } + } + + public int[] getPixel(int x, int y, int[] iArray, DataBuffer data) + { + if (iArray == null) iArray = new int[1]; + iArray[0] = getSample(x, y, 0, data); + + return iArray; + } + + public int[] getPixels(int x, int y, int w, int h, int[] iArray, + DataBuffer data) + { + int offset = getOffset(x, y); + if (iArray == null) iArray = new int[w*h]; + int outOffset = 0; + for (y=0; y<h; y++) + { + int lineOffset = offset; + for (x=0; x<w;) + { + int samples = data.getElem(lineOffset++); + for (int b=0; b<numElems && x<w; b++) + { + iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b]; + x++; + } + } + offset += scanlineStride; + } + return iArray; + } + + public int getSample(int x, int y, int b, DataBuffer data) + { + int pos = + ((dataBitOffset + x * numberOfBits) % elemBits) / numberOfBits; + int offset = getOffset(x, y); + int samples = data.getElem(offset); + return (samples & bitMasks[pos]) >>> bitOffsets[pos]; + } + + /** + * Set the pixel at x, y to the value in the first element of the primitive + * array obj. + * + * @param x The x-coordinate of the data elements in <code>obj</code>. + * @param y The y-coordinate of the data elements in <code>obj</code>. + * @param obj The primitive array containing the data elements to set. + * @param data The DataBuffer to store the data elements into. + * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer) + */ + public void setDataElements(int x, int y, Object obj, DataBuffer data) + { + int transferType = getTransferType(); + if (getTransferType() != data.getDataType()) + { + throw new IllegalArgumentException("transfer type ("+ + getTransferType()+"), "+ + "does not match data "+ + "buffer type (" + + data.getDataType() + + ")."); + } + + int offset = getOffset(x, y); + + try + { + switch (transferType) + { + case DataBuffer.TYPE_BYTE: + { + DataBufferByte out = (DataBufferByte) data; + byte[] in = (byte[]) obj; + out.getData()[offset] = in[0]; + return; + } + case DataBuffer.TYPE_USHORT: + { + DataBufferUShort out = (DataBufferUShort) data; + short[] in = (short[]) obj; + out.getData()[offset] = in[0]; + return; + } + case DataBuffer.TYPE_INT: + { + DataBufferInt out = (DataBufferInt) data; + int[] in = (int[]) obj; + out.getData()[offset] = in[0]; + return; + } + default: + throw new ClassCastException("Unsupported data type"); + } + } + catch (ArrayIndexOutOfBoundsException aioobe) + { + String msg = "While writing data elements" + + ", x="+x+", y="+y+ + ", width="+width+", height="+height+ + ", scanlineStride="+scanlineStride+ + ", offset="+offset+ + ", data.getSize()="+data.getSize()+ + ", data.getOffset()="+data.getOffset()+ + ": " + + aioobe; + throw new ArrayIndexOutOfBoundsException(msg); + } + } + + public void setPixel(int x, int y, int[] iArray, DataBuffer data) + { + setSample(x, y, 0, iArray[0], data); + } + + public void setSample(int x, int y, int b, int s, DataBuffer data) + { + int bitpos = + ((dataBitOffset + x * numberOfBits) % elemBits) / numberOfBits; + int offset = getOffset(x, y); + + s = s << bitOffsets[bitpos]; + s = s & bitMasks[bitpos]; + + int sample = data.getElem(offset); + sample |= s; + data.setElem(offset, sample); + } + + /** + * Creates a String with some information about this SampleModel. + * @return A String describing this SampleModel. + * @see java.lang.Object#toString() + */ + public String toString() + { + StringBuffer result = new StringBuffer(); + result.append(getClass().getName()); + result.append("["); + result.append("scanlineStride=").append(scanlineStride); + for(int i=0; i < bitMasks.length; i+=1) + { + result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i])); + } + + result.append("]"); + return result.toString(); + } +} diff --git a/libjava/classpath/java/awt/image/PackedColorModel.java b/libjava/classpath/java/awt/image/PackedColorModel.java new file mode 100644 index 0000000..894e6e6 --- /dev/null +++ b/libjava/classpath/java/awt/image/PackedColorModel.java @@ -0,0 +1,192 @@ +/* Copyright (C) 2000, 2002, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import gnu.java.awt.BitMaskExtent; + +import java.awt.Point; +import java.awt.color.ColorSpace; + +/** + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public abstract class PackedColorModel extends ColorModel +{ + private int masks[]; + + /* Package accessibility, the DirectColorModel needs this array */ + int shifts[]; + + public PackedColorModel(ColorSpace cspace, int pixelBits, + int[] colorMaskArray, int alphaMask, + boolean isAlphaPremultiplied, + int transparency, + int transferType) + { + super(pixelBits, calcBitsPerComponent(colorMaskArray, alphaMask), + cspace, (alphaMask != 0), isAlphaPremultiplied, transparency, + transferType); + initMasks(colorMaskArray, alphaMask); + if ((pixelBits<1) || (pixelBits>32)) { + throw new IllegalArgumentException("pixels per bits must be " + + "in the range [1, 32]"); + } + } + + private static int[] calcBitsPerComponent(int[] colorMaskArray, + int alphaMask) + { + int numComponents = colorMaskArray.length; + if (alphaMask != 0) numComponents++; + + int[] bitsPerComponent = new int[numComponents]; + + BitMaskExtent extent = new BitMaskExtent(); + for (int b=0; b<colorMaskArray.length; b++) + { + extent.setMask(colorMaskArray[b]); + bitsPerComponent[b] = extent.bitWidth; + } + if (alphaMask != 0) + { + extent.setMask(alphaMask); + bitsPerComponent[numComponents-1] = extent.bitWidth; + } + return bitsPerComponent; + } + + /** Initializes the masks. + * + * @return an array containing the number of bits per color + * component. + */ + private void initMasks(int[] colorMaskArray, int alphaMask) + { + int numComponents = colorMaskArray.length; + if (alphaMask == 0) + { + masks = colorMaskArray; + } + else + { + masks = new int[numComponents+1]; + System.arraycopy(colorMaskArray, 0, + masks, 0, + numComponents); + masks[numComponents++] = alphaMask; + } + + shifts = new int[numComponents]; + + // Bit field handling have been moved to a utility class + BitMaskExtent extent = new BitMaskExtent(); + for (int b=0; b<numComponents; b++) + { + extent.setMask(masks[b]); + shifts[b] = extent.leastSignificantBit; + } + } + + public PackedColorModel(ColorSpace cspace, int pixelBits, + int rmask, int gmask, int bmask, + int amask, boolean isAlphaPremultiplied, + int transparency, + int transferType) + { + this(cspace, pixelBits, makeColorMaskArray(rmask, gmask, bmask), + amask, isAlphaPremultiplied, transparency, transferType); + } + + /* TODO: If there is a alpha mask, it is inefficient to create a + color mask array that will be discarded when the alpha mask is + appended. We should probably create a private constructor that + takes a complete array of masks (color+alpha) as an + argument. */ + + private static int[] makeColorMaskArray(int rmask, int gmask, int bmask) + { + int[] colorMaskArray = { rmask, gmask, bmask }; + return colorMaskArray; + } + + public final int getMask(int index) + { + return masks[index]; + } + + public final int[] getMasks() + { + return masks; + } + + public SampleModel createCompatibleSampleModel(int w, int h) + { + return new SinglePixelPackedSampleModel(transferType, w, h, masks); + } + + public boolean isCompatibleSampleModel(SampleModel sm) + { + if (!super.isCompatibleSampleModel(sm)) return false; + if (!(sm instanceof SinglePixelPackedSampleModel)) return false; + + SinglePixelPackedSampleModel sppsm = + (SinglePixelPackedSampleModel) sm; + return java.util.Arrays.equals(sppsm.getBitMasks(), masks); + } + + public WritableRaster getAlphaRaster(WritableRaster raster) { + if (!hasAlpha()) return null; + + SampleModel sm = raster.getSampleModel(); + int[] alphaBand = { sm.getNumBands() - 1 }; + SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand); + DataBuffer buffer = raster.getDataBuffer(); + Point origin = new Point(0, 0); + return Raster.createWritableRaster(alphaModel, buffer, origin); + } + + public boolean equals(Object obj) + { + if (!super.equals(obj)) return false; + if (!(obj instanceof PackedColorModel)) return false; + + PackedColorModel other = (PackedColorModel) obj; + + return java.util.Arrays.equals(masks, other.masks); + } +} diff --git a/libjava/classpath/java/awt/image/PixelGrabber.java b/libjava/classpath/java/awt/image/PixelGrabber.java new file mode 100644 index 0000000..b576dbf --- /dev/null +++ b/libjava/classpath/java/awt/image/PixelGrabber.java @@ -0,0 +1,618 @@ +/* PixelGrabber.java -- retrieve a subset of an image's data + Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.Image; +import java.util.Hashtable; + +/** + * PixelGrabber is an ImageConsumer that extracts a rectangular region + * of pixels from an Image. + */ +public class PixelGrabber implements ImageConsumer +{ + int x, y, offset; + int width = -1; + int height = -1; + int scansize = -1; + boolean forceRGB = true; + + ColorModel model = ColorModel.getRGBdefault(); + int hints; + Hashtable props; + + int int_pixel_buffer[]; + boolean ints_delivered = false; + byte byte_pixel_buffer[]; + boolean bytes_delivered = false; + + ImageProducer ip; + int observerStatus; + int consumerStatus; + + private Thread grabberThread; + boolean grabbing = false; + + /** + * Construct a PixelGrabber that will retrieve RGB data from a given + * Image. + * + * The RGB data will be retrieved from a rectangular region + * <code>(x, y, w, h)</code> within the image. The data will be + * stored in the provided <code>pix</code> array, which must have + * been initialized to a size of at least <code>w * h</code>. The + * data for a pixel (m, n) in the grab rectangle will be stored at + * <code>pix[(n - y) * scansize + (m - x) + off]</code>. + * + * @param img the Image from which to grab pixels + * @param x the x coordinate, relative to <code>img</code>'s + * top-left corner, of the grab rectangle's top-left pixel + * @param y the y coordinate, relative to <code>img</code>'s + * top-left corner, of the grab rectangle's top-left pixel + * @param w the width of the grab rectangle, in pixels + * @param h the height of the grab rectangle, in pixels + * @param pix the array in which to store grabbed RGB pixel data + * @param off the offset into the <code>pix</code> array at which to + * start storing RGB data + * @param scansize a set of <code>scansize</code> consecutive + * elements in the <code>pix</code> array represents one row of + * pixels in the grab rectangle + */ + public PixelGrabber(Image img, int x, int y, int w, int h, + int pix[], int off, int scansize) + { + this (img.getSource(), x, y, w, h, pix, off, scansize); + } + + /** + * Construct a PixelGrabber that will retrieve RGB data from a given + * ImageProducer. + * + * The RGB data will be retrieved from a rectangular region + * <code>(x, y, w, h)</code> within the image produced by + * <code>ip</code>. The data will be stored in the provided + * <code>pix</code> array, which must have been initialized to a + * size of at least <code>w * h</code>. The data for a pixel (m, n) + * in the grab rectangle will be stored at + * <code>pix[(n - y) * scansize + (m - x) + off]</code>. + * + * @param ip the ImageProducer from which to grab pixels + * @param x the x coordinate of the grab rectangle's top-left pixel, + * specified relative to the top-left corner of the image produced + * by <code>ip</code> + * @param y the y coordinate of the grab rectangle's top-left pixel, + * specified relative to the top-left corner of the image produced + * by <code>ip</code> + * @param w the width of the grab rectangle, in pixels + * @param h the height of the grab rectangle, in pixels + * @param pix the array in which to store grabbed RGB pixel data + * @param off the offset into the <code>pix</code> array at which to + * start storing RGB data + * @param scansize a set of <code>scansize</code> consecutive + * elements in the <code>pix</code> array represents one row of + * pixels in the grab rectangle + */ + public PixelGrabber(ImageProducer ip, int x, int y, int w, int h, + int pix[], int off, int scansize) + { + this.ip = ip; + this.x = x; + this.y = y; + this.width = w; + this.height = h; + this.offset = off; + this.scansize = scansize; + + int_pixel_buffer = pix; + // Initialize the byte array in case ip sends us byte-formatted + // pixel data. + byte_pixel_buffer = new byte[pix.length * 4]; + } + + /** + * Construct a PixelGrabber that will retrieve data from a given + * Image. + * + * The RGB data will be retrieved from a rectangular region + * <code>(x, y, w, h)</code> within the image. The data will be + * stored in an internal array which can be accessed by calling + * <code>getPixels</code>. The data for a pixel (m, n) in the grab + * rectangle will be stored in the returned array at index + * <code>(n - y) * scansize + (m - x) + off</code>. + * If forceRGB is false, then the returned data will be not be + * converted to RGB from its format in <code>img</code>. + * + * If <code>w</code> is negative, the width of the grab region will + * be from x to the right edge of the image. Likewise, if + * <code>h</code> is negative, the height of the grab region will be + * from y to the bottom edge of the image. + * + * @param img the Image from which to grab pixels + * @param x the x coordinate, relative to <code>img</code>'s + * top-left corner, of the grab rectangle's top-left pixel + * @param y the y coordinate, relative to <code>img</code>'s + * top-left corner, of the grab rectangle's top-left pixel + * @param w the width of the grab rectangle, in pixels + * @param h the height of the grab rectangle, in pixels + * @param forceRGB true to force conversion of the rectangular + * region's pixel data to RGB + */ + public PixelGrabber(Image img, + int x, int y, + int w, int h, + boolean forceRGB) + { + this.ip = img.getSource(); + this.x = x; + this.y = y; + width = w; + height = h; + // If width or height is negative, postpone pixel buffer + // initialization until setDimensions is called back by ip. + if (width >= 0 && height >= 0) + { + int_pixel_buffer = new int[width * height]; + byte_pixel_buffer = new byte[width * height]; + } + this.forceRGB = forceRGB; + } + + /** + * Start grabbing pixels. + * + * Spawns an image production thread that calls back to this + * PixelGrabber's ImageConsumer methods. + */ + public synchronized void startGrabbing() + { + // Make sure we're not already grabbing. + if (grabbing == false) + { + grabbing = true; + grabberThread = new Thread () + { + public void run () + { + ip.startProduction (PixelGrabber.this); + } + }; + grabberThread.start (); + } + } + + /** + * Abort pixel grabbing. + */ + public synchronized void abortGrabbing() + { + if (grabbing) + { + // Interrupt the grabbing thread. + Thread moribund = grabberThread; + grabberThread = null; + moribund.interrupt(); + + imageComplete (ImageConsumer.IMAGEABORTED); + } + } + + /** + * Have our Image or ImageProducer start sending us pixels via our + * ImageConsumer methods and wait for all pixels in the grab + * rectangle to be delivered. + * + * @return true if successful, false on abort or error + * + * @throws InterruptedException if interrupted by another thread. + */ + public synchronized boolean grabPixels() throws InterruptedException + { + return grabPixels(0); + } + + /** + * grabPixels's behavior depends on the value of <code>ms</code>. + * + * If ms < 0, return true if all pixels from the source image have + * been delivered, false otherwise. Do not wait. + * + * If ms >= 0 then we request that our Image or ImageProducer start + * delivering pixels to us via our ImageConsumer methods. + * + * If ms > 0, wait at most <code>ms</code> milliseconds for + * delivery of all pixels within the grab rectangle. + * + * If ms == 0, wait until all pixels have been delivered. + * + * @return true if all pixels from the source image have been + * delivered, false otherwise + * + * @throws InterruptedException if this thread is interrupted while + * we are waiting for pixels to be delivered + */ + public synchronized boolean grabPixels(long ms) throws InterruptedException + { + if (ms < 0) + return ((observerStatus & (ImageObserver.FRAMEBITS + | ImageObserver.ALLBITS)) != 0); + + // Spawn a new ImageProducer thread to send us the image data via + // our ImageConsumer methods. + startGrabbing(); + + if (ms > 0) + { + long stop_time = System.currentTimeMillis() + ms; + long time_remaining; + while (grabbing) + { + time_remaining = stop_time - System.currentTimeMillis(); + if (time_remaining <= 0) + break; + wait (time_remaining); + } + abortGrabbing (); + } + else + wait (); + + // If consumerStatus is non-zero then the image is done loading or + // an error has occurred. + if (consumerStatus != 0) + return setObserverStatus (); + + return ((observerStatus & (ImageObserver.FRAMEBITS + | ImageObserver.ALLBITS)) != 0); + } + + // Set observer status flags based on the current consumer status + // flags. Return true if the consumer flags indicate that the + // image was loaded successfully, or false otherwise. + private synchronized boolean setObserverStatus () + { + boolean retval = false; + + if ((consumerStatus & IMAGEERROR) != 0) + observerStatus |= ImageObserver.ERROR; + + if ((consumerStatus & IMAGEABORTED) != 0) + observerStatus |= ImageObserver.ABORT; + + if ((consumerStatus & STATICIMAGEDONE) != 0) + { + observerStatus |= ImageObserver.ALLBITS; + retval = true; + } + + if ((consumerStatus & SINGLEFRAMEDONE) != 0) + { + observerStatus |= ImageObserver.FRAMEBITS; + retval = true; + } + + return retval; + } + + /** + * @return the status of the pixel grabbing thread, represented by a + * bitwise OR of ImageObserver flags + */ + public synchronized int getStatus() + { + return observerStatus; + } + + /** + * @return the width of the grab rectangle in pixels, or a negative + * number if the ImageProducer has not yet called our setDimensions + * method + */ + public synchronized int getWidth() + { + return width; + } + + /** + * @return the height of the grab rectangle in pixels, or a negative + * number if the ImageProducer has not yet called our setDimensions + * method + */ + public synchronized int getHeight() + { + return height; + } + + /** + * @return a byte array of pixel data if ImageProducer delivered + * pixel data using the byte[] variant of setPixels, or an int array + * otherwise + */ + public synchronized Object getPixels() + { + if (ints_delivered) + return int_pixel_buffer; + else if (bytes_delivered) + return byte_pixel_buffer; + else + return null; + } + + /** + * @return the ColorModel currently being used for the majority of + * pixel data conversions + */ + public synchronized ColorModel getColorModel() + { + return model; + } + + /** + * Our <code>ImageProducer</code> calls this method to indicate the + * size of the image being produced. + * + * setDimensions is an ImageConsumer method. None of PixelGrabber's + * ImageConsumer methods should be called by code that instantiates + * a PixelGrabber. They are only made public so they can be called + * by the PixelGrabber's ImageProducer. + * + * @param width the width of the image + * @param height the height of the image + */ + public synchronized void setDimensions(int width, int height) + { + // Our width wasn't set when we were constructed. Set our width + // so that the grab region includes all pixels from x to the right + // edge of the source image. + if (this.width < 0) + this.width = width - x; + + // Our height wasn't set when we were constructed. Set our height + // so that the grab region includes all pixels from y to the + // bottom edge of the source image. + if (this.height < 0) + this.height = height - y; + + if (scansize < 0) + scansize = this.width; + + if (int_pixel_buffer == null) + int_pixel_buffer = new int[this.width * this.height]; + + if (byte_pixel_buffer == null) + byte_pixel_buffer = new byte[this.width * this.height]; + } + + /** + * Our <code>ImageProducer</code> may call this method to send us a + * list of its image's properties. + * + * setProperties is an ImageConsumer method. None of PixelGrabber's + * ImageConsumer methods should be called by code that instantiates + * a PixelGrabber. They are only made public so they can be called + * by the PixelGrabber's ImageProducer. + * + * @param props a list of properties associated with the image being + * produced + */ + public synchronized void setProperties(Hashtable props) + { + this.props = props; + } + + /** + * Our ImageProducer will call <code>setColorModel</code> to + * indicate the model used by the majority of calls to + * <code>setPixels</code>. Each call to <code>setPixels</code> + * could however indicate a different <code>ColorModel</code>. + * + * setColorModel is an ImageConsumer method. None of PixelGrabber's + * ImageConsumer methods should be called by code that instantiates + * a PixelGrabber. They are only made public so they can be called + * by the PixelGrabber's ImageProducer. + * + * @param model the color model to be used most often by setPixels + * + * @see ColorModel + */ + public synchronized void setColorModel(ColorModel model) + { + this.model = model; + } + + /** + * Our <code>ImageProducer</code> may call this method with a + * bit mask of hints from any of <code>RANDOMPIXELORDER</code>, + * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>, + * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code>. + * + * setHints is an ImageConsumer method. None of PixelGrabber's + * ImageConsumer methods should be called by code that instantiates + * a PixelGrabber. They are only made public so they can be called + * by the PixelGrabber's ImageProducer. + * + * @param flags a bit mask of hints + */ + public synchronized void setHints(int flags) + { + hints = flags; + } + + /** + * Our ImageProducer calls setPixels to deliver a subset of its + * pixels. + * + * Each element of the pixels array represents one pixel. The + * pixel data is formatted according to the color model model. + * The x and y parameters are the coordinates of the rectangular + * region of pixels being delivered to this ImageConsumer, + * specified relative to the top left corner of the image being + * produced. Likewise, w and h are the pixel region's dimensions. + * + * @param x x coordinate of pixel block + * @param y y coordinate of pixel block + * @param w width of pixel block + * @param h height of pixel block + * @param model color model used to interpret pixel data + * @param pixels pixel block data + * @param offset offset into pixels array + * @param scansize width of one row in the pixel block + */ + public synchronized void setPixels(int x, int y, int w, int h, + ColorModel model, byte[] pixels, + int offset, int scansize) + { + ColorModel currentModel; + if (model != null) + currentModel = model; + else + currentModel = this.model; + + for(int yp = y; yp < (y + h); yp++) + { + for(int xp = x; xp < (x + w); xp++) + { + // Check if the coordinates (xp, yp) are within the + // pixel block that we are grabbing. + if(xp >= this.x + && yp >= this.y + && xp < (this.x + this.width) + && yp < (this.y + this.height)) + { + int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset; + int p = (yp - y) * scansize + (xp - x) + offset; + if (forceRGB) + { + ints_delivered = true; + + int_pixel_buffer[i] = currentModel.getRGB (pixels[p] & 0xFF); + } + else + { + bytes_delivered = true; + + byte_pixel_buffer[i] = pixels[p]; + } + } + } + } + } + + /** + * Our ImageProducer calls setPixels to deliver a subset of its + * pixels. + * + * Each element of the pixels array represents one pixel. The + * pixel data is formatted according to the color model model. + * The x and y parameters are the coordinates of the rectangular + * region of pixels being delivered to this ImageConsumer, + * specified relative to the top left corner of the image being + * produced. Likewise, w and h are the pixel region's dimensions. + * + * @param x x coordinate of pixel block + * @param y y coordinate of pixel block + * @param w width of pixel block + * @param h height of pixel block + * @param model color model used to interpret pixel data + * @param pixels pixel block data + * @param offset offset into pixels array + * @param scansize width of one row in the pixel block + */ + public synchronized void setPixels(int x, int y, int w, int h, + ColorModel model, int[] pixels, + int offset, int scansize) + { + ColorModel currentModel; + if (model != null) + currentModel = model; + else + currentModel = this.model; + + ints_delivered = true; + + for(int yp = y; yp < (y + h); yp++) + { + for(int xp = x; xp < (x + w); xp++) + { + // Check if the coordinates (xp, yp) are within the + // pixel block that we are grabbing. + if(xp >= this.x + && yp >= this.y + && xp < (this.x + this.width) + && yp < (this.y + this.height)) + { + int i = (yp - this.y) * this.scansize + (xp - this.x) + this.offset; + int p = (yp - y) * scansize + (xp - x) + offset; + if (forceRGB) + int_pixel_buffer[i] = currentModel.getRGB (pixels[p]); + else + int_pixel_buffer[i] = pixels[p]; + } + } + } + } + + /** + * Our <code>ImageProducer</code> calls this method to inform us + * that a single frame or the entire image is complete. The method + * is also used to inform us of an error in loading or producing the + * image. + * + * @param status the status of image production, represented by a + * bitwise OR of ImageConsumer flags + */ + public synchronized void imageComplete(int status) + { + consumerStatus = status; + setObserverStatus (); + grabbing = false; + ip.removeConsumer (this); + + notifyAll (); + } + + /** + * @return the return value of getStatus + * + * @specnote The newer getStatus should be used in place of status. + */ + public synchronized int status() + { + return getStatus(); + } +} diff --git a/libjava/classpath/java/awt/image/PixelInterleavedSampleModel.java b/libjava/classpath/java/awt/image/PixelInterleavedSampleModel.java new file mode 100644 index 0000000..4c5c436 --- /dev/null +++ b/libjava/classpath/java/awt/image/PixelInterleavedSampleModel.java @@ -0,0 +1,98 @@ +/* PixelInterleavedSampleModel.java + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + + +/** + * A <code>SampleModel</code> that uses exactly one element of the + * raster’s {@link DataBuffer} per pixel, holds all bands in a + * single bank, and stores band data in pixel-interleaved manner. + * + * @since 1.2 + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class PixelInterleavedSampleModel + extends ComponentSampleModel +{ + public PixelInterleavedSampleModel(int dataType, int width, int height, + int pixelStride, int scanlineStride, + int[] bandOffsets) + { + super(dataType, width, height, pixelStride, scanlineStride, + bandOffsets); + } + + + /** + * Creates a new <code>SampleModel</code> that is like this one, but + * uses the specified width and height. + * + * @param width the number of pixels in the horizontal direction. + * + * @param height the number of pixels in the vertical direction. + */ + public SampleModel createCompatibleSampleModel(int width, int height) + { + return new PixelInterleavedSampleModel(dataType, width, height, + pixelStride, scanlineStride, + bandOffsets); + } + + + /** + * Creates a new <code>SampleModel</code> that is like this one, but + * uses only a subset of its bands. + * + * @param bands an array whose elements indicate which bands shall + * be part of the subset. For example, <code>[0, 2, 3]</code> would + * create a SampleModel containing bands #0, #2 and #3. + */ + public SampleModel createSubsetSampleModel(int[] bands) + { + int[] subOffsets; + + subOffsets = new int[bands.length]; + for (int i = 0; i < bands.length; i++) + subOffsets[i] = bandOffsets[bands[i]]; + + return new PixelInterleavedSampleModel(dataType, width, height, + pixelStride, scanlineStride, + subOffsets); + } +} diff --git a/libjava/classpath/java/awt/image/RGBImageFilter.java b/libjava/classpath/java/awt/image/RGBImageFilter.java new file mode 100644 index 0000000..f7b39b9 --- /dev/null +++ b/libjava/classpath/java/awt/image/RGBImageFilter.java @@ -0,0 +1,267 @@ +/* RGBImageFilter.java -- Java class for filtering Pixels by RGB values + Copyright (C) 1999, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +/** + * A filter designed to filter images in the default RGBColorModel regardless of + * the ImageProducer's ColorModel. + * + * @author Mark Benvenuto (mcb54@columbia.edu) + */ +public abstract class RGBImageFilter extends ImageFilter +{ + protected ColorModel origmodel; + + protected ColorModel newmodel; + + /** + Specifies whether to apply the filter to the index entries of the + IndexColorModel. Subclasses should set this to true if the filter + does not depend on the pixel's coordinate. + */ + protected boolean canFilterIndexColorModel = false; + + /** + Construct new RGBImageFilter. + */ + public RGBImageFilter() + { + } + + /** + * Sets the ColorModel used to filter with. If the specified ColorModel is IndexColorModel + * and canFilterIndexColorModel is true, we subsitute the ColorModel for a filtered one + * here and in setPixels whenever the original one appears. Otherwise overrides the default + * ColorModel of ImageProducer and specifies the default RGBColorModel + * + * @param model the color model to be used most often by setPixels + * @see ColorModel */ + public void setColorModel(ColorModel model) + { + origmodel = model; + newmodel = model; + + if( ( model instanceof IndexColorModel) && canFilterIndexColorModel ) { + newmodel = filterIndexColorModel( (IndexColorModel) model ); + consumer.setColorModel(newmodel); + } + else { + consumer.setColorModel(ColorModel.getRGBdefault()); + } + } + + /** + Registers a new ColorModel to subsitute for the old ColorModel when + setPixels encounters the a pixel with the old ColorModel. The pixel + remains unchanged except for a new ColorModel. + + @param oldcm the old ColorModel + @param newcm the new ColorModel + */ + public void substituteColorModel(ColorModel oldcm, + ColorModel newcm) + { + origmodel = oldcm; + newmodel = newcm; + } + + /** + Filters an IndexColorModel through the filterRGB function. Uses + coordinates of -1 to indicate its filtering an index and not a pixel. + + @param icm an IndexColorModel to filter + */ + public IndexColorModel filterIndexColorModel(IndexColorModel icm) + { + int len = icm.getMapSize(), rgb; + byte reds[] = new byte[len], greens[] = new byte[len], blues[] = new byte[len], alphas[] = new byte[len]; + + icm.getAlphas( alphas ); + icm.getReds( reds ); + icm.getGreens( greens ); + icm.getBlues( blues ); + + for( int i = 0; i < len; i++ ) + { + rgb = filterRGB( -1, -1, makeColor ( alphas[i], reds[i], greens[i], blues[i] ) ); + alphas[i] = (byte)(( 0xff000000 & rgb ) >> 24); + reds[i] = (byte)(( 0xff0000 & rgb ) >> 16); + greens[i] = (byte)(( 0xff00 & rgb ) >> 8); + blues[i] = (byte)(0xff & rgb); + } + return new IndexColorModel( icm.getPixelSize(), len, reds, greens, blues, alphas ); + } + + private int makeColor( byte a, byte r, byte g, byte b ) + { + return ( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b ); + } + + /** + This functions filters a set of RGB pixels through filterRGB. + + @param x the x coordinate of the rectangle + @param y the y coordinate of the rectangle + @param w the width of the rectangle + @param h the height of the rectangle + @param pixels the array of pixel values + @param offset the index of the first pixels in the <code>pixels</code> array + @param scansize the width to use in extracting pixels from the <code>pixels</code> array + */ + public void filterRGBPixels(int x, int y, int w, int h, int[] pixels, + int offset, int scansize) + { + for (int yp = 0; yp < h; yp++) + { + for (int xp = 0; xp < w; xp++) + { + pixels[offset + xp] = filterRGB(xp + x, yp + y, pixels[offset + xp]); + } + offset += scansize; + } + } + + + /** + * If the ColorModel is the same ColorModel which as already converted + * then it converts it the converted ColorModel. Otherwise it passes the + * array of pixels through filterRGBpixels. + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param model the <code>ColorModel</code> used to translate the pixels + * @param pixels the array of pixel values + * @param offset the index of the first pixels in the <code>pixels</code> array + * @param scansize the width to use in extracting pixels from the <code>pixels</code> array + */ + public void setPixels(int x, int y, int w, int h, + ColorModel model, byte[] pixels, + int offset, int scansize) + { + if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel) + { + consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize); + } + else + { + int intPixels[] = + convertColorModelToDefault( x, y, w, h, model, pixels, offset, scansize ); + filterRGBPixels( x, y, w, h, intPixels, offset, scansize ); + consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), intPixels, offset, scansize); + } + } + + /** + * This function delivers a rectangle of pixels where any + * pixel(m,n) is stored in the array as an <code>int</code> at + * index (n * scansize + m + offset). + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param model the <code>ColorModel</code> used to translate the pixels + * @param pixels the array of pixel values + * @param offset the index of the first pixels in the <code>pixels</code> array + * @param scansize the width to use in extracting pixels from the <code>pixels</code> array + */ + public void setPixels(int x, int y, int w, int h, + ColorModel model, int[] pixels, + int offset, int scansize) + { + if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel) + { + consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize); + } + else + { + //FIXME: Store the filtered pixels in a separate temporary buffer? + convertColorModelToDefault( x, y, w, h, model, pixels, offset, scansize ); + filterRGBPixels( x, y, w, h, pixels, offset, scansize ); + consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), pixels, offset, scansize); + } + } + + private int[] convertColorModelToDefault(int x, int y, int w, int h, + ColorModel model, byte pixels[], + int offset, int scansize) + { + int intPixels[] = new int[pixels.length]; + for (int i = 0; i < pixels.length; i++) + intPixels[i] = makeColorbyDefaultCM(model, pixels[i]); + return intPixels; + } + + private void convertColorModelToDefault(int x, int y, int w, int h, + ColorModel model, int pixels[], + int offset, int scansize) + { + for (int i = 0; i < pixels.length; i++) + pixels[i] = makeColorbyDefaultCM(model, pixels[i]); + } + + private int makeColorbyDefaultCM(ColorModel model, byte rgb) + { + return makeColor( model.getAlpha( rgb ) * 4, model.getRed( rgb ) * 4, model.getGreen( rgb ) * 4, model.getBlue( rgb ) * 4 ); + } + + private int makeColorbyDefaultCM(ColorModel model, int rgb) + { + return makeColor( model.getAlpha( rgb ), model.getRed( rgb ), model.getGreen( rgb ), model.getBlue( rgb ) ); + } + + private int makeColor( int a, int r, int g, int b ) + { + return (int)( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b ); + } + + + /** + Filters a single pixel from the default ColorModel. + + @param x x-coordinate + @param y y-coordinate + @param rgb color + */ + public abstract int filterRGB(int x, + int y, + int rgb); +} diff --git a/libjava/classpath/java/awt/image/Raster.java b/libjava/classpath/java/awt/image/Raster.java new file mode 100644 index 0000000..4af958a --- /dev/null +++ b/libjava/classpath/java/awt/image/Raster.java @@ -0,0 +1,546 @@ +/* Copyright (C) 2000, 2002, 2003 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.Point; +import java.awt.Rectangle; + +/** + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public class Raster +{ + protected SampleModel sampleModel; + protected DataBuffer dataBuffer; + protected int minX; + protected int minY; + protected int width; + protected int height; + protected int sampleModelTranslateX; + protected int sampleModelTranslateY; + protected int numBands; + protected int numDataElements; + protected Raster parent; + + protected Raster(SampleModel sampleModel, Point origin) + { + this(sampleModel, sampleModel.createDataBuffer(), origin); + } + + protected Raster(SampleModel sampleModel, DataBuffer dataBuffer, + Point origin) + { + this(sampleModel, dataBuffer, + new Rectangle(origin.x, origin.y, + sampleModel.getWidth(), sampleModel.getHeight()), + origin, null); + } + + protected Raster(SampleModel sampleModel, DataBuffer dataBuffer, + Rectangle aRegion, + Point sampleModelTranslate, Raster parent) + { + this.sampleModel = sampleModel; + this.dataBuffer = dataBuffer; + this.minX = aRegion.x; + this.minY = aRegion.y; + this.width = aRegion.width; + this.height = aRegion.height; + + // If sampleModelTranslate is null, use (0,0). Methods such as + // Raster.createRaster are specified to allow for a null argument. + if (sampleModelTranslate != null) + { + this.sampleModelTranslateX = sampleModelTranslate.x; + this.sampleModelTranslateY = sampleModelTranslate.y; + } + + this.numBands = sampleModel.getNumBands(); + this.numDataElements = sampleModel.getNumDataElements(); + this.parent = parent; + } + + public static WritableRaster createInterleavedRaster(int dataType, + int w, int h, + int bands, + Point location) + { + int[] bandOffsets = new int[bands]; + // TODO: Maybe not generate this every time. + for (int b=0; b<bands; b++) bandOffsets[b] = b; + + int scanlineStride = bands*w; + return createInterleavedRaster(dataType, w, h, scanlineStride, bands, + bandOffsets, location); + } + + public static WritableRaster createInterleavedRaster(int dataType, + int w, int h, + int scanlineStride, + int pixelStride, + int[] bandOffsets, + Point location) + { + SampleModel sm = new ComponentSampleModel(dataType, + w, h, + pixelStride, + scanlineStride, + bandOffsets); + return createWritableRaster(sm, location); + } + + public static WritableRaster createBandedRaster(int dataType, + int w, int h, int bands, + Point location) + { + SampleModel sm = new BandedSampleModel(dataType, w, h, bands); + return createWritableRaster(sm, location); + } + + public static WritableRaster createBandedRaster(int dataType, + int w, int h, + int scanlineStride, + int[] bankIndices, + int[] bandOffsets, + Point location) + { + SampleModel sm = new BandedSampleModel(dataType, w, h, scanlineStride, + bankIndices, bandOffsets); + return createWritableRaster(sm, location); + } + + public static WritableRaster createPackedRaster(int dataType, + int w, int h, + int[] bandMasks, + Point location) + { + SampleModel sm = new SinglePixelPackedSampleModel(dataType, + w, h, + bandMasks); + return createWritableRaster(sm, location); + } + + public static WritableRaster createPackedRaster(int dataType, + int w, int h, + int bands, int bitsPerBand, + Point location) + { + if (bands <= 0 || (bands * bitsPerBand > getTypeBits(dataType))) + throw new IllegalArgumentException(); + + SampleModel sm; + + if (bands == 1) + sm = new MultiPixelPackedSampleModel(dataType, w, h, bitsPerBand); + else + { + int[] bandMasks = new int[bands]; + int mask = 0x1; + for (int bits = bitsPerBand; --bits != 0;) + mask = (mask << 1) | 0x1; + for (int i = 0; i < bands; i++) + { + bandMasks[i] = mask; + mask <<= bitsPerBand; + } + + sm = new SinglePixelPackedSampleModel(dataType, w, h, bandMasks); + } + return createWritableRaster(sm, location); + } + + public static WritableRaster + createInterleavedRaster(DataBuffer dataBuffer, int w, int h, + int scanlineStride, int pixelStride, + int[] bandOffsets, Point location) + { + SampleModel sm = new ComponentSampleModel(dataBuffer.getDataType(), + w, h, + scanlineStride, + pixelStride, + bandOffsets); + return createWritableRaster(sm, dataBuffer, location); + } + + public static + WritableRaster createBandedRaster(DataBuffer dataBuffer, + int w, int h, + int scanlineStride, + int[] bankIndices, + int[] bandOffsets, + Point location) + { + SampleModel sm = new BandedSampleModel(dataBuffer.getDataType(), + w, h, scanlineStride, + bankIndices, bandOffsets); + return createWritableRaster(sm, dataBuffer, location); + } + + public static WritableRaster + createPackedRaster(DataBuffer dataBuffer, + int w, int h, + int scanlineStride, + int[] bandMasks, + Point location) + { + SampleModel sm = + new SinglePixelPackedSampleModel(dataBuffer.getDataType(), + w, h, + scanlineStride, + bandMasks); + return createWritableRaster(sm, dataBuffer, location); + } + + public static WritableRaster + createPackedRaster(DataBuffer dataBuffer, + int w, int h, + int bitsPerPixel, + Point location) + { + SampleModel sm = + new MultiPixelPackedSampleModel(dataBuffer.getDataType(), + w, h, + bitsPerPixel); + return createWritableRaster(sm, dataBuffer, location); + } + + public static Raster createRaster(SampleModel sm, DataBuffer db, + Point location) + { + return new Raster(sm, db, location); + } + + public static WritableRaster createWritableRaster(SampleModel sm, + Point location) + { + return new WritableRaster(sm, location); + } + + public static WritableRaster createWritableRaster(SampleModel sm, + DataBuffer db, + Point location) + { + return new WritableRaster(sm, db, location); + } + + public Raster getParent() + { + return parent; + } + + public final int getSampleModelTranslateX() + { + return sampleModelTranslateX; + } + + public final int getSampleModelTranslateY() + { + return sampleModelTranslateY; + } + + public WritableRaster createCompatibleWritableRaster() + { + return new WritableRaster(getSampleModel(), new Point(minX, minY)); + } + + public WritableRaster createCompatibleWritableRaster(int w, int h) + { + return createCompatibleWritableRaster(minX, minY, w, h); + } + + public WritableRaster createCompatibleWritableRaster(Rectangle rect) + { + return createCompatibleWritableRaster(rect.x, rect.y, + rect.width, rect.height); + } + + public WritableRaster createCompatibleWritableRaster(int x, int y, + int w, int h) + { + SampleModel sm = getSampleModel().createCompatibleSampleModel(w, h); + return new WritableRaster(sm, sm.createDataBuffer(), + new Point(x, y)); + } + + public Raster createTranslatedChild(int childMinX, int childMinY) { + int tcx = sampleModelTranslateX - minX + childMinX; + int tcy = sampleModelTranslateY - minY + childMinY; + + return new Raster(sampleModel, dataBuffer, + new Rectangle(childMinX, childMinY, + width, height), + new Point(tcx, tcy), + this); + } + + public Raster createChild(int parentX, int parentY, int width, + int height, int childMinX, int childMinY, + int[] bandList) + { + /* FIXME: Throw RasterFormatException if child bounds extends + beyond the bounds of this raster. */ + + SampleModel sm = (bandList == null) ? + sampleModel : + sampleModel.createSubsetSampleModel(bandList); + + /* + data origin + / + +------------------------- + |\. __ parent trans + | \`. + | \ `. parent origin + | \ `. / + | /\ +-------- - - + |trans\ /<\-- deltaTrans + |child +-+-\---- - - + | /|`| \__ parent [x, y] + |child | |`. \ + |origin| : `.\ + | | / `\ + | : / + + | child [x, y] + + parent_xy - parent_trans = child_xy - child_trans + + child_trans = parent_trans + child_xy - parent_xy + */ + + return new Raster(sm, dataBuffer, + new Rectangle(childMinX, childMinY, + width, height), + new Point(sampleModelTranslateX+childMinX-parentX, + sampleModelTranslateY+childMinY-parentY), + this); + } + + public Rectangle getBounds() + { + return new Rectangle(minX, minY, width, height); + } + + public final int getMinX() + { + return minX; + } + + public final int getMinY() + { + return minY; + } + + public final int getWidth() + { + return width; + } + + public final int getHeight() + { + return height; + } + + public final int getNumBands() + { + return numBands; + } + + public final int getNumDataElements() + { + return numDataElements; + } + + public final int getTransferType() + { + return sampleModel.getTransferType(); + } + + public DataBuffer getDataBuffer() + { + return dataBuffer; + } + + public SampleModel getSampleModel() + { + return sampleModel; + } + + public Object getDataElements(int x, int y, Object outData) + { + return sampleModel.getDataElements(x-sampleModelTranslateX, + y-sampleModelTranslateY, + outData, dataBuffer); + } + + public Object getDataElements(int x, int y, int w, int h, + Object outData) + { + return sampleModel.getDataElements(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, outData, dataBuffer); + } + + public int[] getPixel(int x, int y, int[] iArray) + { + return sampleModel.getPixel(x-sampleModelTranslateX, + y-sampleModelTranslateY, + iArray, dataBuffer); + } + + public float[] getPixel(int x, int y, float[] fArray) + { + return sampleModel.getPixel(x-sampleModelTranslateX, + y-sampleModelTranslateY, + fArray, dataBuffer); + } + + public double[] getPixel(int x, int y, double[] dArray) + { + return sampleModel.getPixel(x-sampleModelTranslateX, + y-sampleModelTranslateY, + dArray, dataBuffer); + } + + public int[] getPixels(int x, int y, int w, int h, int[] iArray) + { + return sampleModel.getPixels(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, iArray, dataBuffer); + } + + public float[] getPixels(int x, int y, int w, int h, + float[] fArray) + { + return sampleModel.getPixels(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, fArray, dataBuffer); + } + + public double[] getPixels(int x, int y, int w, int h, + double[] dArray) + { + return sampleModel.getPixels(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, dArray, dataBuffer); + } + + public int getSample(int x, int y, int b) + { + return sampleModel.getSample(x-sampleModelTranslateX, + y-sampleModelTranslateY, + b, dataBuffer); + } + + public float getSampleFloat(int x, int y, int b) + { + return sampleModel.getSampleFloat(x-sampleModelTranslateX, + y-sampleModelTranslateY, + b, dataBuffer); + } + + public double getSampleDouble(int x, int y, int b) + { + return sampleModel.getSampleDouble(x-sampleModelTranslateX, + y-sampleModelTranslateY, + b, dataBuffer); + } + + public int[] getSamples(int x, int y, int w, int h, int b, + int[] iArray) + { + return sampleModel.getSamples(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, b, iArray, dataBuffer); + } + + public float[] getSamples(int x, int y, int w, int h, int b, + float[] fArray) + { + return sampleModel.getSamples(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, b, fArray, dataBuffer); + } + + public double[] getSamples(int x, int y, int w, int h, int b, + double[] dArray) + { + return sampleModel.getSamples(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, b, dArray, dataBuffer); + } + + /** + * Create a String representing the stat of this Raster. + * @return A String representing the stat of this Raster. + * @see java.lang.Object#toString() + */ + public String toString() + { + StringBuffer result = new StringBuffer(); + + result.append(getClass().getName()); + result.append("[("); + result.append(minX).append(",").append(minY).append("), "); + result.append(width).append(" x ").append(height).append(","); + result.append(sampleModel).append(","); + result.append(dataBuffer); + result.append("]"); + + return result.toString(); + } + + // Map from datatype to bits + private static int getTypeBits(int dataType) + { + switch (dataType) + { + case DataBuffer.TYPE_BYTE: + return 8; + case DataBuffer.TYPE_USHORT: + case DataBuffer.TYPE_SHORT: + return 16; + case DataBuffer.TYPE_INT: + case DataBuffer.TYPE_FLOAT: + return 32; + case DataBuffer.TYPE_DOUBLE: + return 64; + default: + return 0; + } + } +} diff --git a/libjava/classpath/java/awt/image/RasterFormatException.java b/libjava/classpath/java/awt/image/RasterFormatException.java new file mode 100644 index 0000000..582c2ae --- /dev/null +++ b/libjava/classpath/java/awt/image/RasterFormatException.java @@ -0,0 +1,65 @@ +/* RasterFormatException.java -- indicates invalid layout in Raster + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +/** + * This exception is thrown when there is invalid layout information in + * <code>Raster</code> + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see Raster + * @status updated to 1.4 + */ +public class RasterFormatException extends RuntimeException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 96598996116164315L; + + /** + * Create a new instance with a descriptive error message. + * + * @param message the descriptive error message + */ + public RasterFormatException(String message) + { + super(message); + } +} // class RasterFormatException diff --git a/libjava/classpath/java/awt/image/RasterOp.java b/libjava/classpath/java/awt/image/RasterOp.java new file mode 100644 index 0000000..e081ca3 --- /dev/null +++ b/libjava/classpath/java/awt/image/RasterOp.java @@ -0,0 +1,57 @@ +/* RasterOp.java -- + Copyright (C) 2000, 2002, 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +public interface RasterOp +{ + WritableRaster filter(Raster src, WritableRaster dest); + + Rectangle2D getBounds2D(Raster src); + + WritableRaster createCompatibleDestRaster(Raster src); + + Point2D getPoint2D(Point2D srcPoint, Point2D destPoint); + + RenderingHints getRenderingHints(); +} + diff --git a/libjava/classpath/java/awt/image/RenderedImage.java b/libjava/classpath/java/awt/image/RenderedImage.java new file mode 100644 index 0000000..b35f860 --- /dev/null +++ b/libjava/classpath/java/awt/image/RenderedImage.java @@ -0,0 +1,70 @@ +/* RenderedImage.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.Rectangle; +import java.util.Vector; + +/** + * NEEDS DOCUMENTATION + */ +public interface RenderedImage +{ + Vector getSources(); + Object getProperty(String name); + String[] getPropertyNames(); + ColorModel getColorModel(); + SampleModel getSampleModel(); + int getWidth(); + int getHeight(); + int getMinX(); + int getMinY(); + int getNumXTiles(); + int getNumYTiles(); + int getMinTileX(); + int getMinTileY(); + int getTileWidth(); + int getTileHeight(); + int getTileGridXOffset(); + int getTileGridYOffset(); + Raster getTile(int x, int y); + Raster getData(); + Raster getData(Rectangle r); + WritableRaster copyData(WritableRaster raster); +} // interface RenderedImage diff --git a/libjava/classpath/java/awt/image/ReplicateScaleFilter.java b/libjava/classpath/java/awt/image/ReplicateScaleFilter.java new file mode 100644 index 0000000..3841e49 --- /dev/null +++ b/libjava/classpath/java/awt/image/ReplicateScaleFilter.java @@ -0,0 +1,244 @@ +/* ReplicateScaleFilter.java -- Java class for filtering images + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.util.Hashtable; + +/** + * This filter should be used for fast scaling of images where the result + * does not need to ensure straight lines are still straight, etc. The + * exact method is not defined by Sun but some sort of fast Box filter should + * probably be correct. + * <br> + * Currently this filter does nothing and needs to be implemented. + * + * @author C. Brian Jones (cbj@gnu.org) + */ +public class ReplicateScaleFilter extends ImageFilter +{ + public ReplicateScaleFilter(int width, int height) { + destHeight = height; + destWidth = width; + } + + /** + * The height of the destination image. + */ + protected int destHeight; + + /** + * The width of the destination image. + */ + protected int destWidth; + + /** + * The height of the source image. + */ + protected int srcHeight; + + /** + * The width of the source image. + */ + protected int srcWidth; + + /** + * + */ + protected int srcrows[]; + + /** + * + */ + protected int srccols[]; + + /** + * + */ + protected Object outpixbuf; + + /** + * An <code>ImageProducer</code> indicates the size of the image + * being produced using this method. A filter can override this + * method to intercept these calls from the producer in order to + * change either the width or the height before in turn calling + * the consumer's <code>setDimensions</code> method. + * + * @param width the width of the image + * @param height the height of the image + */ + public void setDimensions(int width, int height) + { + srcWidth = width; + srcHeight = height; + + /* If either destHeight or destWidth is < 0, the image should + maintain its original aspect ratio. When both are < 0, + just maintain the original width and height. */ + if (destWidth < 0 && destHeight < 0) + { + destWidth = width; + destHeight = height; + } + else if (destWidth < 0) + { + destWidth = (int) (width * ((double) destHeight / srcHeight)); + } + else if (destHeight < 0) + { + destHeight = (int) (height * ((double) destWidth / srcWidth)); + } + + consumer.setDimensions(destWidth, destHeight); + } + + /** + * An <code>ImageProducer</code> can set a list of properties + * associated with this image by using this method. + * + * @param props the list of properties associated with this image + */ + public void setProperties(Hashtable props) + { + props.put("filters", "ReplicateScaleFilter"); + consumer.setProperties(props); + } + + /** + * This function delivers a rectangle of pixels where any + * pixel(m,n) is stored in the array as a <code>byte</code> at + * index (n * scansize + m + offset). + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param model the <code>ColorModel</code> used to translate the pixels + * @param pixels the array of pixel values + * @param offset the index of the first pixels in the <code>pixels</code> array + * @param scansize the width to use in extracting pixels from the <code>pixels</code> array + */ + public void setPixels(int x, int y, int w, int h, + ColorModel model, byte[] pixels, int offset, int scansize) + { + double rx = ((double) srcWidth) / destWidth; + double ry = ((double) srcHeight) / destHeight; + + int destScansize = (int) Math.round(scansize / rx); + + byte[] destPixels = replicatePixels(x, y, w, h, + model, pixels, offset, scansize, + rx, ry, destScansize); + + consumer.setPixels((int) Math.floor(x/rx), (int) Math.floor(y/ry), + (int) Math.ceil(w/rx), (int) Math.ceil(h/ry), + model, destPixels, 0, destScansize); + } + + /** + * This function delivers a rectangle of pixels where any + * pixel(m,n) is stored in the array as an <code>int</code> at + * index (n * scansize + m + offset). + * + * @param x the x coordinate of the rectangle + * @param y the y coordinate of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param model the <code>ColorModel</code> used to translate the pixels + * @param pixels the array of pixel values + * @param offset the index of the first pixels in the <code>pixels</code> array + * @param scansize the width to use in extracting pixels from the <code>pixels</code> array + */ + public void setPixels(int x, int y, int w, int h, + ColorModel model, int[] pixels, int offset, int scansize) + { + double rx = ((double) srcWidth) / destWidth; + double ry = ((double) srcHeight) / destHeight; + + int destScansize = (int) Math.round(scansize / rx); + + int[] destPixels = replicatePixels(x, y, w, h, + model, pixels, offset, scansize, + rx, ry, destScansize); + + consumer.setPixels((int) Math.floor(x/rx), (int) Math.floor(y/ry), + (int) Math.ceil(w/rx), (int) Math.ceil(h/ry), + model, destPixels, 0, destScansize); + } + + private byte[] replicatePixels(int srcx, int srcy, int srcw, int srch, + ColorModel model, byte[] srcPixels, + int srcOffset, int srcScansize, + double rx, double ry, int destScansize) + { + byte[] destPixels = + new byte[(int) Math.ceil(srcw/rx) * (int) Math.ceil(srch/ry)]; + + int a, b; + for (int i = 0; i < destPixels.length; i++) + { + a = (int) ((int) ( ((double) i) / destScansize) * ry) * srcScansize; + b = (int) ((i % destScansize) * rx); + if ((a + b + srcOffset) < srcPixels.length) + destPixels[i] = srcPixels[a + b + srcOffset]; + } + + return destPixels; + } + + private int[] replicatePixels(int srcx, int srcy, int srcw, int srch, + ColorModel model, int[] srcPixels, + int srcOffset, int srcScansize, + double rx, double ry, int destScansize) + { + int[] destPixels = + new int[(int) Math.ceil(srcw/rx) * (int) Math.ceil(srch/ry)]; + + int a, b; + for (int i = 0; i < destPixels.length; i++) + { + a = (int) ((int) ( ((double) i) / destScansize) * ry) * srcScansize; + b = (int) ((i % destScansize) * rx); + if ((a + b + srcOffset) < srcPixels.length) + destPixels[i] = srcPixels[a + b + srcOffset]; + } + + return destPixels; + } +} + diff --git a/libjava/classpath/java/awt/image/RescaleOp.java b/libjava/classpath/java/awt/image/RescaleOp.java new file mode 100644 index 0000000..35b42f7 --- /dev/null +++ b/libjava/classpath/java/awt/image/RescaleOp.java @@ -0,0 +1,218 @@ +/* Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Arrays; + +/** + * @author Jerry Quinn (jlquinn@optonline.net) + */ +public class RescaleOp implements BufferedImageOp, RasterOp +{ + private float[] scale; + private float[] offsets; + private RenderingHints hints = null; + + public RescaleOp(float[] scaleFactors, + float[] offsets, + RenderingHints hints) + { + this.scale = scaleFactors; + this.offsets = offsets; + this.hints = hints; + } + + public RescaleOp(float scaleFactor, + float offset, + RenderingHints hints) + { + scale = new float[]{ scaleFactor }; + offsets = new float[]{offset}; + this.hints = hints; + } + + public final float[] getScaleFactors(float[] scaleFactors) + { + if (scaleFactors == null) + scaleFactors = new float[scale.length]; + System.arraycopy(scale, 0, scaleFactors, 0, scale.length); + return scaleFactors; + } + + public final float[] getOffsets(float[] offsets) + { + if (offsets == null) + offsets = new float[this.offsets.length]; + System.arraycopy(this.offsets, 0, offsets, 0, this.offsets.length); + return offsets; + } + + public final int getNumFactors() + { + return scale.length; + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#getRenderingHints() + */ + public RenderingHints getRenderingHints() + { + return hints; + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, java.awt.image.BufferedImage) + */ + public final BufferedImage filter(BufferedImage src, BufferedImage dst) + { + // TODO Make sure premultiplied alpha is handled correctly. + // TODO See that color conversion is handled. + // TODO figure out how to use rendering hints. + if (scale.length != offsets.length) + throw new IllegalArgumentException(); + + ColorModel scm = src.getColorModel(); + if (dst == null) dst = createCompatibleDestImage(src, null); + + WritableRaster wsrc = src.getRaster(); + WritableRaster wdst = dst.getRaster(); + + // Share constant across colors except alpha + if (scale.length == 1 || scale.length == scm.getNumColorComponents()) + { + // Construct a raster that doesn't include an alpha band. + int[] subbands = new int[scm.getNumColorComponents()]; + for (int i=0; i < subbands.length; i++) subbands[i] = i; + wsrc = + wsrc.createWritableChild(wsrc.minX, wsrc.minY, wsrc.width, wsrc.height, + wsrc.minX, wsrc.minY, subbands); + } + // else all color bands + + filter(wsrc, wdst); + return dst; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster) + */ + public final WritableRaster filter(Raster src, WritableRaster dest) + { + if (dest == null) dest = src.createCompatibleWritableRaster(); + + // Required sanity checks + if (src.numBands != dest.numBands || scale.length != offsets.length) + throw new IllegalArgumentException(); + if (scale.length != 1 && scale.length != src.numBands) + throw new IllegalArgumentException(); + + // Create scaling arrays if needed + float[] lscale = scale; + float[] loff = offsets; + if (scale.length == 1) + { + lscale = new float[src.numBands]; + Arrays.fill(lscale, scale[0]); + loff = new float[src.numBands]; + Arrays.fill(loff, offsets[0]); + } + + // TODO The efficiency here can be improved for various data storage + // patterns, aka SampleModels. + float[] pixel = new float[src.numBands]; + for (int y = src.minY; y < src.height + src.minY; y++) + for (int x = src.minX; x < src.width + src.minX; x++) + { + src.getPixel(x, y, pixel); + for (int b = 0; b < src.numBands; b++) + pixel[b] = pixel[b] * lscale[b] + loff[b]; + dest.setPixel(x, y, pixel); + } + return dest; + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel) + */ + public BufferedImage createCompatibleDestImage(BufferedImage src, + ColorModel dstCM) + { + if (dstCM == null) dstCM = src.getColorModel(); + WritableRaster wr = src.getRaster().createCompatibleWritableRaster(); + BufferedImage image + = new BufferedImage(dstCM, wr, src.isPremultiplied, null); + return image; + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster) + */ + public WritableRaster createCompatibleDestRaster(Raster src) + { + return src.createCompatibleWritableRaster(); + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage) + */ + public final Rectangle2D getBounds2D(BufferedImage src) + { + return src.getRaster().getBounds(); + } + + /* (non-Javadoc) + * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster) + */ + public final Rectangle2D getBounds2D(Raster src) + { + return src.getBounds(); + } + + /* (non-Javadoc) + * @see java.awt.image.BufferedImageOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D) + */ + public final Point2D getPoint2D(Point2D src, Point2D dst) { + if (dst == null) dst = (Point2D) src.clone(); + else dst.setLocation(src); + return dst; + } + +} diff --git a/libjava/classpath/java/awt/image/SampleModel.java b/libjava/classpath/java/awt/image/SampleModel.java new file mode 100644 index 0000000..257e30a --- /dev/null +++ b/libjava/classpath/java/awt/image/SampleModel.java @@ -0,0 +1,477 @@ +/* Copyright (C) 2000, 2001, 2002, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +/** + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public abstract class SampleModel +{ + /** Width of image described. */ + protected int width; + + /** Height of image described. */ + protected int height; + + /** Number of bands in the image described. */ + protected int numBands; + + /** + * The DataBuffer type that is used to store the data of the image + * described. + */ + protected int dataType; + + public SampleModel(int dataType, int w, int h, int numBands) + { + if ((w <= 0) || (h <= 0)) + throw new IllegalArgumentException((w <= 0 ? " width<=0" : " width is ok") + +(h <= 0 ? " height<=0" : " height is ok")); + + // FIXME: How can an int be greater than Integer.MAX_VALUE? + // FIXME: How do we identify an unsupported data type? + + this.dataType = dataType; + this.width = w; + this.height = h; + this.numBands = numBands; + } + + public final int getWidth() + { + return width; + } + + public final int getHeight() + { + return height; + } + + public final int getNumBands() + { + return numBands; + } + + public abstract int getNumDataElements(); + + public final int getDataType() + { + return dataType; + } + + public int getTransferType() + { + // FIXME: Is this a reasonable default implementation? + return dataType; + } + + public int[] getPixel(int x, int y, int[] iArray, DataBuffer data) + { + if (iArray == null) iArray = new int[numBands]; + for (int b=0; b<numBands; b++) iArray[b] = getSample(x, y, b, data); + return iArray; + } + + /** + * + * This method is provided as a faster alternative to getPixel(), + * that can be used when there is no need to decode the pixel into + * separate sample values. + * + * @param obj An array to return the pixel data in. If null, an + * array of the right type and size will be created. + * + * @return A single pixel as an array object of a primitive type, + * based on the transfer type. Eg. if transfer type is + * DataBuffer.TYPE_USHORT, then a short[] object is returned. + */ + public abstract Object getDataElements(int x, int y, Object obj, + DataBuffer data); + + + public Object getDataElements(int x, int y, int w, int h, Object obj, + DataBuffer data) + { + int size = w*h; + int numDataElements = getNumDataElements(); + int dataSize = numDataElements*size; + + if (obj == null) + { + switch (getTransferType()) + { + case DataBuffer.TYPE_BYTE: + obj = new byte[dataSize]; + break; + case DataBuffer.TYPE_USHORT: + obj = new short[dataSize]; + break; + case DataBuffer.TYPE_INT: + obj = new int[dataSize]; + break; + default: + // Seems like the only sensible thing to do. + throw new ClassCastException(); + } + } + Object pixelData = null; + int outOffset = 0; + for (int yy = y; yy<(y+h); yy++) + { + for (int xx = x; xx<(x+w); xx++) + { + pixelData = getDataElements(xx, yy, pixelData, data); + System.arraycopy(pixelData, 0, obj, outOffset, + numDataElements); + outOffset += numDataElements; + } + } + return obj; + } + + public abstract void setDataElements(int x, int y, Object obj, + DataBuffer data); + + public void setDataElements(int x, int y, int w, int h, + Object obj, DataBuffer data) + { + int size = w*h; + int numDataElements = getNumDataElements(); + int dataSize = numDataElements*size; + + Object pixelData; + switch (getTransferType()) + { + case DataBuffer.TYPE_BYTE: + pixelData = new byte[numDataElements]; + break; + case DataBuffer.TYPE_USHORT: + pixelData = new short[numDataElements]; + break; + case DataBuffer.TYPE_INT: + pixelData = new int[numDataElements]; + break; + default: + // Seems like the only sensible thing to do. + throw new ClassCastException(); + } + int inOffset = 0; + + for (int yy=y; yy<(y+h); yy++) + { + for (int xx=x; xx<(x+w); xx++) + { + System.arraycopy(obj, inOffset, pixelData, 0, + numDataElements); + setDataElements(xx, yy, pixelData, data); + inOffset += numDataElements; + } + } + } + + public float[] getPixel(int x, int y, float[] fArray, DataBuffer data) + { + if (fArray == null) fArray = new float[numBands]; + + for (int b=0; b<numBands; b++) + { + fArray[b] = getSampleFloat(x, y, b, data); + } + return fArray; + } + + public double[] getPixel(int x, int y, double[] dArray, DataBuffer data) { + if (dArray == null) dArray = new double[numBands]; + for (int b=0; b<numBands; b++) + { + dArray[b] = getSampleDouble(x, y, b, data); + } + return dArray; + } + + /* FIXME: Should it return a banded or pixel interleaved array of + samples? (Assume interleaved.) */ + public int[] getPixels(int x, int y, int w, int h, int[] iArray, + DataBuffer data) + { + int size = w*h; + int outOffset = 0; + int[] pixel = null; + if (iArray == null) iArray = new int[w*h*numBands]; + for (int yy=y; yy<(y+h); yy++) + { + for (int xx=x; xx<(x+w); xx++) + { + pixel = getPixel(xx, yy, pixel, data); + System.arraycopy(pixel, 0, iArray, outOffset, numBands); + outOffset += numBands; + } + } + return iArray; + } + + /* FIXME: Should it return a banded or pixel interleaved array of + samples? (Assume interleaved.) */ + public float[] getPixels(int x, int y, int w, int h, float[] fArray, + DataBuffer data) + { + int size = w*h; + int outOffset = 0; + float[] pixel = null; + if (fArray == null) fArray = new float[w*h*numBands]; + for (int yy=y; yy<(y+h); yy++) + { + for (int xx=x; xx<(x+w); xx++) + { + pixel = getPixel(xx, yy, pixel, data); + System.arraycopy(pixel, 0, fArray, outOffset, numBands); + outOffset += numBands; + } + } + return fArray; + } + + /* FIXME: Should it return a banded or pixel interleaved array of + samples? (Assume interleaved.) */ + public double[] getPixels(int x, int y, int w, int h, double[] dArray, + DataBuffer data) + { + int size = w*h; + int outOffset = 0; + double[] pixel = null; + if (dArray == null) dArray = new double[w*h*numBands]; + for (int yy=y; yy<(y+h); yy++) + { + for (int xx=x; xx<(x+w); xx++) + { + pixel = getPixel(xx, yy, pixel, data); + System.arraycopy(pixel, 0, dArray, outOffset, numBands); + outOffset += numBands; + } + } + return dArray; + } + + public abstract int getSample(int x, int y, int b, DataBuffer data); + + public float getSampleFloat(int x, int y, int b, DataBuffer data) + { + return getSample(x, y, b, data); + } + + public double getSampleDouble(int x, int y, int b, DataBuffer data) + { + return getSampleFloat(x, y, b, data); + } + + public int[] getSamples(int x, int y, int w, int h, int b, + int[] iArray, DataBuffer data) + { + int size = w*h; + int outOffset = 0; + if (iArray == null) iArray = new int[size]; + for (int yy=y; yy<(y+h); yy++) + { + for (int xx=x; xx<(x+w); xx++) + { + iArray[outOffset++] = getSample(xx, yy, b, data); + } + } + return iArray; + } + + public float[] getSamples(int x, int y, int w, int h, int b, + float[] fArray, DataBuffer data) + { + int size = w*h; + int outOffset = 0; + if (fArray == null) fArray = new float[size]; + for (int yy=y; yy<(y+h); yy++) + { + for (int xx=x; xx<(x+w); xx++) + { + fArray[outOffset++] = getSampleFloat(xx, yy, b, data); + } + } + return fArray; + } + + public double[] getSamples(int x, int y, int w, int h, int b, + double[] dArray, DataBuffer data) + { + int size = w*h; + int outOffset = 0; + if (dArray == null) dArray = new double[size]; + for (int yy=y; yy<(y+h); yy++) + { + for (int xx=x; xx<(x+w); xx++) + { + dArray[outOffset++] = getSampleDouble(xx, yy, b, data); + } + } + return dArray; + } + + public void setPixel(int x, int y, int[] iArray, DataBuffer data) + { + for (int b=0; b<numBands; b++) setSample(x, y, b, iArray[b], data); + } + + public void setPixel(int x, int y, float[] fArray, DataBuffer data) + { + for (int b=0; b<numBands; b++) setSample(x, y, b, fArray[b], data); + } + + public void setPixel(int x, int y, double[] dArray, DataBuffer data) + { + for (int b=0; b<numBands; b++) setSample(x, y, b, dArray[b], data); + } + + public void setPixels(int x, int y, int w, int h, int[] iArray, + DataBuffer data) + { + int inOffset = 0; + int[] pixel = new int[numBands]; + for (int yy=y; yy<(y+h); yy++) + { + for (int xx=x; xx<(x+w); xx++) + { + System.arraycopy(iArray, inOffset, pixel, 0, numBands); + setPixel(xx, yy, pixel, data); + inOffset += numBands; + } + } + } + + public void setPixels(int x, int y, int w, int h, float[] fArray, + DataBuffer data) + { + int inOffset = 0; + float[] pixel = new float[numBands]; + for (int yy=y; yy<(y+h); yy++) + { + for (int xx=x; xx<(x+w); xx++) + { + System.arraycopy(fArray, inOffset, pixel, 0, numBands); + setPixel(xx, yy, pixel, data); + inOffset += numBands; + } + } + } + + public void setPixels(int x, int y, int w, int h, double[] dArray, + DataBuffer data) + { + int inOffset = 0; + double[] pixel = new double[numBands]; + for (int yy=y; yy<(y+h); yy++) + { + for (int xx=x; xx<(x+w); xx++) + { + System.arraycopy(dArray, inOffset, pixel, 0, numBands); + setPixel(xx, yy, pixel, data); + inOffset += numBands; + } + } + } + + public abstract void setSample(int x, int y, int b, int s, + DataBuffer data); + + public void setSample(int x, int y, int b, float s, + DataBuffer data) + { + setSample(x, y, b, (int) s, data); + } + + public void setSample(int x, int y, int b, double s, + DataBuffer data) + { + setSample(x, y, b, (float) s, data); + } + + public void setSamples(int x, int y, int w, int h, int b, + int[] iArray, DataBuffer data) + { + int size = w*h; + int inOffset = 0; + for (int yy=y; yy<(y+h); yy++) + for (int xx=x; xx<(x+w); xx++) + setSample(xx, yy, b, iArray[inOffset++], data); + } + + public void setSamples(int x, int y, int w, int h, int b, + float[] fArray, DataBuffer data) + { + int size = w*h; + int inOffset = 0; + for (int yy=y; yy<(y+h); yy++) + for (int xx=x; xx<(x+w); xx++) + setSample(xx, yy, b, fArray[inOffset++], data); + + } + + public void setSamples(int x, int y, int w, int h, int b, + double[] dArray, DataBuffer data) { + int size = w*h; + int inOffset = 0; + for (int yy=y; yy<(y+h); yy++) + for (int xx=x; xx<(x+w); xx++) + setSample(xx, yy, b, dArray[inOffset++], data); + } + + public abstract SampleModel createCompatibleSampleModel(int w, int h); + + /** + * Return a SampleModel with a subset of the bands in this model. + * + * Selects bands.length bands from this sample model. The bands chosen + * are specified in the indices of bands[]. This also permits permuting + * the bands as well as taking a subset. Thus, giving an array with + * 1, 2, 3, ..., numbands, will give an identical sample model. + * + * @param bands Array with band indices to include. + * @return A new sample model + */ + public abstract SampleModel createSubsetSampleModel(int[] bands); + + public abstract DataBuffer createDataBuffer(); + + public abstract int[] getSampleSize(); + + public abstract int getSampleSize(int band); +} diff --git a/libjava/classpath/java/awt/image/ShortLookupTable.java b/libjava/classpath/java/awt/image/ShortLookupTable.java new file mode 100644 index 0000000..5915a79 --- /dev/null +++ b/libjava/classpath/java/awt/image/ShortLookupTable.java @@ -0,0 +1,162 @@ +/* ShortLookupTable.java -- Java class for a pixel translation table. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +/** + * ShortLookupTable represents translation arrays for pixel values. It wraps + * one or more data arrays for each layer (or component) in an image, such as + * Alpha, R, G, and B. When doing translation, the offset is subtracted from + * the pixel values to allow a subset of an array to be used. + * + * @author Jerry Quinn (jlquinn@optonline.net) + * @version 1.0 + */ +public class ShortLookupTable extends LookupTable +{ + // Array of translation tables. + private short data[][]; + + /** + * Creates a new <code>ShortLookupTable</code> instance. + * + * Offset is subtracted from pixel values when looking up in the translation + * tables. If data.length is one, the same table is applied to all pixel + * components. + * + * @param offset Offset to be subtracted. + * @param data Array of lookup tables. + * @exception IllegalArgumentException if offset < 0 or data.length < 1. + */ + public ShortLookupTable(int offset, short[][] data) + throws IllegalArgumentException + { + super(offset, data.length); + this.data = data; + } + + /** + * Creates a new <code>ShortLookupTable</code> instance. + * + * Offset is subtracted from pixel values when looking up in the translation + * table. The same table is applied to all pixel components. + * + * @param offset Offset to be subtracted. + * @param data Lookup table for all components. + * @exception IllegalArgumentException if offset < 0. + */ + public ShortLookupTable(int offset, short[] data) + throws IllegalArgumentException + { + super(offset, 1); + this.data = new short[][] {data}; + } + + /** Return the lookup tables. */ + public final short[][] getTable() + { + return data; + } + + /** + * Return translated values for a pixel. + * + * For each value in the pixel src, use the value minus offset as an index + * in the component array and copy the value there to the output for the + * component. If dest is null, the output is a new array, otherwise the + * translated values are written to dest. Dest can be the same array as + * src. + * + * For example, if the pixel src is [2, 4, 3], and offset is 1, the output + * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the + * translation arrays. + * + * @param src Component values of a pixel. + * @param dst Destination array for values, or null. + * @return Translated values for the pixel. + */ + public int[] lookupPixel(int[] src, int[] dst) + throws ArrayIndexOutOfBoundsException + { + if (dst == null) + dst = new int[src.length]; + + if (data.length == 1) + for (int i=0; i < src.length; i++) + dst[i] = data[0][src[i] - offset]; + else + for (int i=0; i < src.length; i++) + dst[i] = data[i][src[i] - offset]; + + return dst; + } + + /** + * Return translated values for a pixel. + * + * For each value in the pixel src, use the value minus offset as an index + * in the component array and copy the value there to the output for the + * component. If dest is null, the output is a new array, otherwise the + * translated values are written to dest. Dest can be the same array as + * src. + * + * For example, if the pixel src is [2, 4, 3], and offset is 1, the output + * is [comp1[1], comp2[3], comp3[2]], where comp1, comp2, and comp3 are the + * translation arrays. + * + * @param src Component values of a pixel. + * @param dst Destination array for values, or null. + * @return Translated values for the pixel. + */ + public short[] lookupPixel(short[] src, short[] dst) + throws ArrayIndexOutOfBoundsException + { + if (dst == null) + dst = new short[src.length]; + + if (data.length == 1) + for (int i=0; i < src.length; i++) + dst[i] = data[0][((int)src[i]) - offset]; + else + for (int i=0; i < src.length; i++) + dst[i] = data[i][((int)src[i]) - offset]; + + return dst; + + } +} diff --git a/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java b/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java new file mode 100644 index 0000000..6ccce75 --- /dev/null +++ b/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java @@ -0,0 +1,449 @@ +/* Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.image; + +import gnu.java.awt.BitMaskExtent; +import gnu.java.awt.Buffers; + +/** + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public class SinglePixelPackedSampleModel extends SampleModel +{ + private int scanlineStride; + private int[] bitMasks; + private int[] bitOffsets; + private int[] sampleSize; + + public SinglePixelPackedSampleModel(int dataType, int w, int h, + int[] bitMasks) + { + this(dataType, w, h, w, bitMasks); + } + + public SinglePixelPackedSampleModel(int dataType, int w, int h, + int scanlineStride, int[] bitMasks) + { + super(dataType, w, h, bitMasks.length); + + switch (dataType) + { + case DataBuffer.TYPE_BYTE: + case DataBuffer.TYPE_USHORT: + case DataBuffer.TYPE_INT: + break; + default: + throw new IllegalArgumentException("SinglePixelPackedSampleModel unsupported dataType"); + } + + this.scanlineStride = scanlineStride; + this.bitMasks = bitMasks; + + bitOffsets = new int[numBands]; + sampleSize = new int[numBands]; + + BitMaskExtent extent = new BitMaskExtent(); + for (int b=0; b<numBands; b++) + { + extent.setMask(bitMasks[b]); + sampleSize[b] = extent.bitWidth; + bitOffsets[b] = extent.leastSignificantBit; + } + } + + public int getNumDataElements() + { + return 1; + } + + public SampleModel createCompatibleSampleModel(int w, int h) + { + /* FIXME: We can avoid recalculation of bit offsets and sample + sizes here by passing these from the current instance to a + special private constructor. */ + return new SinglePixelPackedSampleModel(dataType, w, h, bitMasks); + } + + + /** + * Creates a DataBuffer for holding pixel data in the format and + * layout described by this SampleModel. The returned buffer will + * consist of one single bank. + */ + public DataBuffer createDataBuffer() + { + int size; + + // We can save (scanlineStride - width) pixels at the very end of + // the buffer. The Sun reference implementation (J2SE 1.3.1 and + // 1.4.1_01) seems to do this; tested with Mauve test code. + size = scanlineStride * (height - 1) + width; + + return Buffers.createBuffer(getDataType(), size); + } + + + public int[] getSampleSize() + { + return sampleSize; + } + + public int getSampleSize(int band) + { + return sampleSize[band]; + } + + public int getOffset(int x, int y) + { + return scanlineStride*y + x; + } + + public int[] getBitOffsets() + { + return bitOffsets; + } + + public int[] getBitMasks() + { + return bitMasks; + } + + public int getScanlineStride() + { + return scanlineStride; + } + + public SampleModel createSubsetSampleModel(int[] bands) + { + // FIXME: Is this the right way to interpret bands? + + int numBands = bands.length; + + int[] bitMasks = new int[numBands]; + + for (int b=0; b<numBands; b++) + bitMasks[b] = this.bitMasks[bands[b]]; + + return new SinglePixelPackedSampleModel(dataType, width, height, + scanlineStride, bitMasks); + } + + public Object getDataElements(int x, int y, Object obj, + DataBuffer data) + { + int offset = scanlineStride*y + x + data.getOffset(); + + return Buffers.getData(data, offset, obj, + 0, // destination offset, + 1 // length + ); + } + + /** + * This is a more efficient implementation of the default implementation in the super + * class. + * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>. + * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>. + * @param w The width of the pixel rectangle to store in <code>obj</code>. + * @param h The height of the pixel rectangle to store in <code>obj</code>. + * @param obj The primitive array to store the pixels into or null to force creation. + * @param data The DataBuffer that is the source of the pixel data. + * @return The primitive array containing the pixel data. + * @see java.awt.image.SampleModel#getDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer) + */ + public Object getDataElements(int x, int y, int w, int h, Object obj, + DataBuffer data) + { + int size = w*h; + int dataSize = size; + Object pixelData = null; + switch (getTransferType()) + { + case DataBuffer.TYPE_BYTE: + pixelData = ((DataBufferByte) data).getData(); + if (obj == null) obj = new byte[dataSize]; + break; + case DataBuffer.TYPE_USHORT: + pixelData = ((DataBufferUShort) data).getData(); + if (obj == null) obj = new short[dataSize]; + break; + case DataBuffer.TYPE_INT: + pixelData = ((DataBufferInt) data).getData(); + if (obj == null) obj = new int[dataSize]; + break; + default: + // Seems like the only sensible thing to do. + throw new ClassCastException(); + } + if(x==0 && scanlineStride == w) + { + // The full width need to be copied therefore we can copy in one shot. + System.arraycopy(pixelData, scanlineStride*y + data.getOffset(), obj, 0, size); + } + else + { + // Since we do not need the full width we need to copy line by line. + int outOffset = 0; + int dataOffset = scanlineStride*y + x + data.getOffset(); + for (int yy = y; yy<(y+h); yy++) + { + System.arraycopy(pixelData, dataOffset, obj, outOffset, w); + dataOffset += scanlineStride; + outOffset += w; + } + } + return obj; + } + + + public int[] getPixel(int x, int y, int[] iArray, DataBuffer data) + { + int offset = scanlineStride*y + x; + if (iArray == null) iArray = new int[numBands]; + int samples = data.getElem(offset); + + for (int b=0; b<numBands; b++) + iArray[b] = (samples & bitMasks[b]) >>> bitOffsets[b]; + + return iArray; + } + + public int[] getPixels(int x, int y, int w, int h, int[] iArray, + DataBuffer data) + { + int offset = scanlineStride*y + x; + if (iArray == null) iArray = new int[numBands*w*h]; + int outOffset = 0; + for (y=0; y<h; y++) + { + int lineOffset = offset; + for (x=0; x<w; x++) + { + int samples = data.getElem(lineOffset++); + for (int b=0; b<numBands; b++) + iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b]; + } + offset += scanlineStride; + } + return iArray; + } + + public int getSample(int x, int y, int b, DataBuffer data) + { + int offset = scanlineStride*y + x; + int samples = data.getElem(offset); + return (samples & bitMasks[b]) >>> bitOffsets[b]; + } + + /** + * This method implements a more efficient way to set data elements than the default + * implementation of the super class. It sets the data elements line by line instead + * of pixel by pixel. + * @param x The x-coordinate of the data elements in <code>obj</code>. + * @param y The y-coordinate of the data elements in <code>obj</code>. + * @param w The width of the data elements in <code>obj</code>. + * @param h The height of the data elements in <code>obj</code>. + * @param obj The primitive array containing the data elements to set. + * @param data The DataBuffer to store the data elements into. + * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer) + */ + public void setDataElements(int x, int y, int w, int h, + Object obj, DataBuffer data) + { + + Object pixelData; + switch (getTransferType()) + { + case DataBuffer.TYPE_BYTE: + pixelData = ((DataBufferByte) data).getData(); + break; + case DataBuffer.TYPE_USHORT: + pixelData = ((DataBufferUShort) data).getData(); + break; + case DataBuffer.TYPE_INT: + pixelData = ((DataBufferInt) data).getData(); + break; + default: + // Seems like the only sensible thing to do. + throw new ClassCastException(); + } + + int inOffset = 0; + int dataOffset = scanlineStride*y + x + data.getOffset(); + for (int yy=y; yy<(y+h); yy++) + { + System.arraycopy(obj,inOffset,pixelData,dataOffset,w); + dataOffset += scanlineStride; + inOffset += w; + } + } + + + public void setDataElements(int x, int y, Object obj, DataBuffer data) + { + int offset = scanlineStride*y + x + data.getOffset(); + + int transferType = getTransferType(); + if (getTransferType() != data.getDataType()) + { + throw new IllegalArgumentException("transfer type ("+ + getTransferType()+"), "+ + "does not match data "+ + "buffer type (" + + data.getDataType() + + ")."); + } + + try + { + switch (transferType) + { + case DataBuffer.TYPE_BYTE: + { + DataBufferByte out = (DataBufferByte) data; + byte[] in = (byte[]) obj; + out.getData()[offset] = in[0]; + return; + } + case DataBuffer.TYPE_USHORT: + { + DataBufferUShort out = (DataBufferUShort) data; + short[] in = (short[]) obj; + out.getData()[offset] = in[0]; + return; + } + case DataBuffer.TYPE_INT: + { + DataBufferInt out = (DataBufferInt) data; + int[] in = (int[]) obj; + out.getData()[offset] = in[0]; + return; + } + // FIXME: Fill in the other possible types. + default: + throw new InternalError(); + } + } + catch (ArrayIndexOutOfBoundsException aioobe) + { + String msg = "While writing data elements" + + ", x="+x+", y="+y+ + ", width="+width+", height="+height+ + ", scanlineStride="+scanlineStride+ + ", offset="+offset+ + ", data.getSize()="+data.getSize()+ + ", data.getOffset()="+data.getOffset()+ + ": " + + aioobe; + throw new ArrayIndexOutOfBoundsException(msg); + } + } + + public void setPixel(int x, int y, int[] iArray, DataBuffer data) + { + int offset = scanlineStride*y + x; + + int samples = 0; + for (int b=0; b<numBands; b++) + samples |= (iArray[b] << bitOffsets[b]) & bitMasks[b]; + + data.setElem(offset, samples); + } + + /** + * This method implements a more efficient way to set pixels than the default + * implementation of the super class. It copies the pixel components directly + * from the input array instead of creating a intermediate buffer. + * @param x The x-coordinate of the pixel rectangle in <code>obj</code>. + * @param y The y-coordinate of the pixel rectangle in <code>obj</code>. + * @param w The width of the pixel rectangle in <code>obj</code>. + * @param h The height of the pixel rectangle in <code>obj</code>. + * @param iArray The primitive array containing the pixels to set. + * @param data The DataBuffer to store the pixels into. + * @see java.awt.image.SampleModel#setPixels(int, int, int, int, int[], java.awt.image.DataBuffer) + */ + public void setPixels(int x, int y, int w, int h, int[] iArray, + DataBuffer data) + { + int inOffset = 0; + int[] pixel = new int[numBands]; + for (int yy=y; yy<(y+h); yy++) + { + int offset = scanlineStride*yy + x; + for (int xx=x; xx<(x+w); xx++) + { + int samples = 0; + for (int b=0; b<numBands; b++) + samples |= (iArray[inOffset+b] << bitOffsets[b]) & bitMasks[b]; + data.setElem(0, offset, samples); + inOffset += numBands; + offset += 1; + } + } + } + + + public void setSample(int x, int y, int b, int s, DataBuffer data) + { + int offset = scanlineStride*y + x; + int samples = data.getElem(offset); + int bitMask = bitMasks[b]; + samples &= ~bitMask; + samples |= (s << bitOffsets[b]) & bitMask; + data.setElem(offset, samples); + } + + /** + * Creates a String with some information about this SampleModel. + * @return A String describing this SampleModel. + * @see java.lang.Object#toString() + */ + public String toString() + { + StringBuffer result = new StringBuffer(); + result.append(getClass().getName()); + result.append("["); + result.append("scanlineStride=").append(scanlineStride); + for(int i=0; i < bitMasks.length; i+=1) + { + result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i])); + } + + result.append("]"); + return result.toString(); + } +} diff --git a/libjava/classpath/java/awt/image/TileObserver.java b/libjava/classpath/java/awt/image/TileObserver.java new file mode 100644 index 0000000..99aafbc --- /dev/null +++ b/libjava/classpath/java/awt/image/TileObserver.java @@ -0,0 +1,47 @@ +/* TileObserver.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +/** + * NEEDS DOCUMENTATION + */ +public interface TileObserver +{ + void tileUpdate(WritableRenderedImage src, int x, int y, boolean writable); +} // interface TileObserver diff --git a/libjava/classpath/java/awt/image/VolatileImage.java b/libjava/classpath/java/awt/image/VolatileImage.java new file mode 100644 index 0000000..3086541 --- /dev/null +++ b/libjava/classpath/java/awt/image/VolatileImage.java @@ -0,0 +1,253 @@ +/* VolatileImage.java -- a hardware-accelerated image buffer + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Transparency; +import java.awt.ImageCapabilities; + +/** + * VolatileImage represents a hardware-accelerated graphics buffer. + * The native graphics system may free or damage the resources + * occupied by a VolatileImage at any time. As such, one must + * frequently check the "validity" of the image buffer's resources. + * + * A volatile image's "validity" depends on multiple factors. Its + * resources may have become unavailble in which case you must + * reallocate them. If you move the image from one output device to + * another, you may need to recreate the image's resources if the new + * output device's capabilities don't match the old one's. Finally, + * if the contents of the image's buffer have been damaged you must + * re-render the image. + * + * VolatileImages should always be created using either + * Component.createVolatileImage or + * GraphicsConfiguration.createCompatibleVolatileImage. + */ +public abstract class VolatileImage extends Image + implements Transparency +{ + /** + * One of validate's possible return values. Indicates that the + * image buffer matches its graphics configuration's capabilities + * and that its resources are initialized and ready to be drawn + * into. Also implies that any existing image rendered to the + * buffer is intact and need not be re-rendered. + */ + public static final int IMAGE_OK = 0; + + /** + * One of validate's possible return values. Indicates that the + * image buffer has been restored, meaning that it is valid and + * ready-to-use but that its previous contents have been lost. This + * return value implies that the image needs to be re-rendered. + */ + public static final int IMAGE_RESTORED = 1; + + /** + * One of validate's possible return values. Indicates that the + * image buffer type is unsupported by the current graphics + * configuration. The graphics configuration may have changed, for + * example if the image moved from one output device to another. + * This return value implies that the image buffer's resources + * should be re-acquired. + */ + public static final int IMAGE_INCOMPATIBLE = 2; + + /** + * This image's transparency type. One of Transparency.BITMASK, + * Transparency.OPAQUE or Transparency.TRANSLUCENT. + * + * @since 1.5 + */ + protected int transparency; + + /** + * Default constructor. VolatileImages should not be created + * directly. Rather, you should use Component.createVolatileImage + * or GraphicsConfiguration.createCompatibleVolatileImage. + */ + public VolatileImage() + { + } + + /** + * Returns an image representing the current state of the volatile + * image buffer. The returned image is static meaning that it is + * not updated after being created. It is a snapshot of the + * volatile image buffer at the time getSnapshot is called. + * + * This method, which reads pixels from the volatile image buffer, + * may be less-performant than methods that write pixels since + * VolatileImages are typically optimized for writing. + * + * @return a BufferedImage representing this VolatileImage + */ + public abstract BufferedImage getSnapshot(); + + /** + * Returns the width of this image buffer. + * + * @return the width of this VolatileImage + */ + public abstract int getWidth(); + + /** + * Returns the height of this image buffer. + * + * @return the height of this VolatileImage + */ + public abstract int getHeight(); + + /** + * Calling this method is equivalent to calling + * getSnapshot().getSource(). The ImageProducer produces pixels + * from the BufferedImage snapshot and not from the VolatileImage + * itself. Thus, changes to the VolatileImage that occur after this + * ImageProducer has been retrieved will not be reflected in the + * produced pixels. + * + * This method, which reads pixels from the volatile image buffer, + * may be less-performant than methods that write pixels since + * VolatileImages are typically optimized for writing. + * + * @return an ImageProducer for a static BufferedImage snapshot of + * this image buffer + */ + public ImageProducer getSource() + { + return getSnapshot().getSource(); + } + + /** + * Releases the system resources taken by this image. + */ + public void flush() + { + } + + /** + * Returns a Graphics2D object that can be used to draw onto this + * image. This method is present for backwards-compatibility. It + * simply returns the result of createGraphics. + * + * @return a Graphics2D object that can be used to draw onto this + * image + */ + public Graphics getGraphics() + { + return createGraphics(); + } + + /** + * Returns a Graphics2D object that can be used to draw onto this + * image. + * + * @return a Graphics2D object that can be used to draw onto this + * image + */ + public abstract Graphics2D createGraphics(); + + /** + * Validates and restores this image. If the image buffer has + * become unavailable for further use since the last call to + * validate, validate will allocate a new image buffer. The image + * is also "validated" against the GraphicsConfiguration parameter. + * + * "Validating" the image means checking that the capabilities it + * requires of the output device are indeed supported by the given + * output device. If the image's characteristics, which can be + * highly output device-specific, are not supported by the graphics + * configuration, then IMAGE_INCOMPATIBLE will be returned. This + * can happen, for example, if this image was created on one output + * device, then validated against a different output device with + * different capabilities. Calling validate with a NULL gc argument + * causes validate to skip the validation test. + * + * @param gc graphics configuration against which to validate or + * NULL + * + * @return a code indicating the result of validation. One of: + * <ul> + * <li><code>IMAGE_OK</code> if the image did not need to be + * validated and didn't need to be restored</li> + * <li><code>IMAGE_RESTORED</code> if the image may need to be + * re-rendered.</li> + * <li><code>IMAGE_INCOMPATIBLE</code> if this image's + * requirements are not fulfilled by the graphics configuration + * parameter. This implies that you need to create a new + * VolatileImage for the different GraphicsConfiguration or + * Component. This return value implies nothing about whether the + * image is valid or needs to be re-rendered.</li> + * </ul> + */ + public abstract int validate(GraphicsConfiguration gc); + + /** + * Returns true if the contents of the image buffer have been + * damaged or if the image buffer's resources have been reclaimed by + * the graphics system. You should call this method after a series + * of rendering operations to or from the image, to see if the image + * buffer needs to be revalidated or the image re-rendered. + * + * @return true if the validate should be called, false otherwise + */ + public abstract boolean contentsLost(); + + /** + * Returns the capabilities of this image buffer. + * + * @return the capabilities of this image buffer + */ + public abstract ImageCapabilities getCapabilities(); + + /** + * Returns the transparency type of this image. + * + * @return Transparency.OPAQUE, Transparency.BITMASK or + * Transparency.TRANSLUCENT + */ + public int getTransparency() + { + return transparency; + } +} diff --git a/libjava/classpath/java/awt/image/WritableRaster.java b/libjava/classpath/java/awt/image/WritableRaster.java new file mode 100644 index 0000000..2e5462f --- /dev/null +++ b/libjava/classpath/java/awt/image/WritableRaster.java @@ -0,0 +1,265 @@ +/* Copyright (C) 2000, 2002, 2003 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.Point; +import java.awt.Rectangle; + +/** + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public class WritableRaster extends Raster +{ + protected WritableRaster(SampleModel sampleModel, Point origin) + { + this(sampleModel, sampleModel.createDataBuffer(), origin); + } + + protected WritableRaster(SampleModel sampleModel, + DataBuffer dataBuffer, Point origin) + { + this(sampleModel, dataBuffer, + new Rectangle(origin != null ? origin.x : 0, + origin != null ? origin.y : 0, + sampleModel.getWidth(), sampleModel.getHeight()), + origin, + null); + } + + protected WritableRaster(SampleModel sampleModel, + DataBuffer dataBuffer, + Rectangle aRegion, + Point sampleModelTranslate, + WritableRaster parent) + { + super(sampleModel, dataBuffer, aRegion, sampleModelTranslate, + parent); + } + + public WritableRaster getWritableParent() + { + return (WritableRaster) getParent(); + } + + public WritableRaster createWritableTranslatedChild(int childMinX, + int childMinY) + { + // This mirrors the code from the super class + int tcx = sampleModelTranslateX - minX + childMinX; + int tcy = sampleModelTranslateY - minY + childMinY; + + return new WritableRaster(sampleModel, dataBuffer, + new Rectangle(childMinX, childMinY, + width, height), + new Point(tcx, tcy), + this); + } + + public WritableRaster createWritableChild(int parentX, + int parentY, + int w, int h, + int childMinX, + int childMinY, + int[] bandList) + { + // This mirrors the code from the super class + + // FIXME: Throw RasterFormatException if child bounds extends + // beyond the bounds of this raster. + + SampleModel sm = (bandList == null) ? + sampleModel : + sampleModel.createSubsetSampleModel(bandList); + + return new + WritableRaster(sm, dataBuffer, + new Rectangle(childMinX, childMinY, + w, h), + new Point(sampleModelTranslateX+childMinX-parentX, + sampleModelTranslateY+childMinY-parentY), + this); + } + + public void setDataElements(int x, int y, Object inData) + { + sampleModel.setDataElements(x-sampleModelTranslateX, + y-sampleModelTranslateY, + inData, dataBuffer); + } + + public void setDataElements(int x, int y, Raster inRaster) + { + Object dataElements = getDataElements(0, 0, + inRaster.getWidth(), + inRaster.getHeight(), + null); + setDataElements(x, y, dataElements); + } + + public void setDataElements(int x, int y, int w, int h, + Object inData) + { + sampleModel.setDataElements(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, inData, dataBuffer); + } + + public void setRect(Raster srcRaster) + { + setRect(0, 0, srcRaster); + } + + public void setRect(int dx, int dy, Raster srcRaster) + { + Rectangle targetUnclipped = new Rectangle(srcRaster.getMinX()+dx, + srcRaster.getMinY()+dy, + srcRaster.getWidth(), + srcRaster.getHeight()); + + Rectangle target = getBounds().intersection(targetUnclipped); + + if (target.isEmpty()) return; + + int sx = target.x - dx; + int sy = target.y - dy; + + // FIXME: Do tests on rasters and use get/set data instead. + + /* The JDK documentation seems to imply this implementation. + (the trucation of higher bits), but an implementation using + get/setDataElements would be more efficient. None of the + implementations would do anything sensible when the sample + models don't match. + + But this is probably not the place to consider such + optimizations.*/ + + int[] pixels = srcRaster.getPixels(sx, sy, + target.width, target.height, + (int[]) null); + + setPixels(target.x, target.y, target.width, target.height, pixels); + } + + public void setPixel(int x, int y, int[] iArray) + { + sampleModel.setPixel(x-sampleModelTranslateX, + y-sampleModelTranslateY, + iArray, dataBuffer); + } + + public void setPixel(int x, int y, float[] fArray) + { + sampleModel.setPixel(x-sampleModelTranslateX, + y-sampleModelTranslateY, + fArray, dataBuffer); + } + + public void setPixel(int x, int y, double[] dArray) + { + sampleModel.setPixel(x-sampleModelTranslateX, + y-sampleModelTranslateY, + dArray, dataBuffer); + } + + public void setPixels(int x, int y, int w, int h, int[] iArray) + { + sampleModel.setPixels(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, iArray, dataBuffer); + } + + public void setPixels(int x, int y, int w, int h, float[] fArray) + { + sampleModel.setPixels(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, fArray, dataBuffer); + } + + public void setPixels(int x, int y, int w, int h, double[] dArray) + { + sampleModel.setPixels(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, dArray, dataBuffer); + } + + public void setSample(int x, int y, int b, int s) + { + sampleModel.setSample(x-sampleModelTranslateX, + y-sampleModelTranslateY, + b, s, dataBuffer); + } + + public void setSample(int x, int y, int b, float s) + { + sampleModel.setSample(x-sampleModelTranslateX, + y-sampleModelTranslateY, + b, s, dataBuffer); + } + + public void setSample(int x, int y, int b, double s) + { + sampleModel.setSample(x-sampleModelTranslateX, + y-sampleModelTranslateY, + b, s, dataBuffer); + } + + public void setSamples(int x, int y, int w, int h, int b, + int[] iArray) + { + sampleModel.setSamples(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, b, iArray, dataBuffer); + } + + public void setSamples(int x, int y, int w, int h, int b, + float[] fArray) + { + sampleModel.setSamples(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, b, fArray, dataBuffer); + } + + public void setSamples(int x, int y, int w, int h, int b, + double[] dArray) + { + sampleModel.setSamples(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w, h, b, dArray, dataBuffer); + } +} diff --git a/libjava/classpath/java/awt/image/WritableRenderedImage.java b/libjava/classpath/java/awt/image/WritableRenderedImage.java new file mode 100644 index 0000000..4ed9f10 --- /dev/null +++ b/libjava/classpath/java/awt/image/WritableRenderedImage.java @@ -0,0 +1,56 @@ +/* WritableRenderedImage.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image; + +import java.awt.Point; + +/** + * NEEDS DOCUMENTATION + */ +public interface WritableRenderedImage extends RenderedImage +{ + void addTileObserver(TileObserver to); + void removeTileObserver(TileObserver to); + WritableRaster getWritableTile(int x, int y); + void releaseWritableTile(int x, int y); + boolean isTileWritable(int x, int y); + Point[] getWritableTileIndices(); + boolean hasTileWriters(); + void setData(Raster r); +} // interface WritableRenderedImage diff --git a/libjava/classpath/java/awt/image/package.html b/libjava/classpath/java/awt/image/package.html new file mode 100644 index 0000000..50fa99d --- /dev/null +++ b/libjava/classpath/java/awt/image/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.image package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.image</title></head> + +<body> +<p>Image consumers, producers and filters.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/image/renderable/ContextualRenderedImageFactory.java b/libjava/classpath/java/awt/image/renderable/ContextualRenderedImageFactory.java new file mode 100644 index 0000000..729d857 --- /dev/null +++ b/libjava/classpath/java/awt/image/renderable/ContextualRenderedImageFactory.java @@ -0,0 +1,56 @@ +/* ContextualRenderedImageFactory.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image.renderable; + +import java.awt.geom.Rectangle2D; +import java.awt.image.RenderedImage; + +/** + * STUBBED + */ +public interface ContextualRenderedImageFactory extends RenderedImageFactory +{ + RenderContext mapRenderContext(int i, RenderContext context, + ParameterBlock block, RenderableImage image); + RenderedImage create(RenderContext context, ParameterBlock block); + Rectangle2D getBounds2D(ParameterBlock block); + Object getProperty(ParameterBlock block, String name); + String[] getPropertyNames(); + boolean isDynamic(); +} // interface ContextualRenderedImageFactory diff --git a/libjava/classpath/java/awt/image/renderable/ParameterBlock.java b/libjava/classpath/java/awt/image/renderable/ParameterBlock.java new file mode 100644 index 0000000..879d3c4 --- /dev/null +++ b/libjava/classpath/java/awt/image/renderable/ParameterBlock.java @@ -0,0 +1,308 @@ +/* ParameterBlock.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image.renderable; + +import java.awt.image.RenderedImage; +import java.io.Serializable; +import java.util.Vector; + +public class ParameterBlock implements Cloneable, Serializable +{ + private static final long serialVersionUID = -7577115551785240750L; + protected Vector sources; + protected Vector parameters; + + public ParameterBlock() + { + this(new Vector(), new Vector()); + } + + public ParameterBlock(Vector sources) + { + this(sources, new Vector()); + } + + public ParameterBlock(Vector sources, Vector parameters) + { + this.sources = sources; + this.parameters = parameters; + } + + public Object shallowClone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // impossible + } + } + + public Object clone() + { + ParameterBlock pb = (ParameterBlock) shallowClone(); + if (sources != null) + pb.sources = (Vector) sources.clone(); + if (parameters != null) + pb.parameters = (Vector) parameters.clone(); + return pb; + } + + public ParameterBlock addSource(Object source) + { + sources.add(source); + return this; + } + + public Object getSource(int index) + { + return sources.get(index); + } + + public ParameterBlock setSource(Object source, int index) + { + sources.ensureCapacity(index); + sources.set(index, source); + return this; + } + + public RenderedImage getRenderedSource(int index) + { + return (RenderedImage) sources.get(index); + } + + public RenderableImage getRenderableSource(int index) + { + return (RenderableImage) sources.get(index); + } + + public int getNumSources() + { + return sources.size(); + } + + public Vector getSources() + { + return sources; + } + + public void setSources(Vector sources) + { + this.sources = sources; + } + + public void removeSources() + { + if (sources != null) + sources.clear(); + } + + public int getNumParameters() + { + return parameters.size(); + } + + public Vector getParameters() + { + return parameters; + } + + public void setParameters(Vector parameters) + { + this.parameters = parameters; + } + + public void removeParameters() + { + if (parameters != null) + parameters.clear(); + } + + public ParameterBlock add(Object o) + { + parameters.add(o); + return this; + } + + public ParameterBlock add(byte b) + { + return add(new Byte(b)); + } + + public ParameterBlock add(char c) + { + return add(new Character(c)); + } + + public ParameterBlock add(short s) + { + return add(new Short(s)); + } + + public ParameterBlock add(int i) + { + return add(new Integer(i)); + } + + public ParameterBlock add(long l) + { + return add(new Long(l)); + } + + public ParameterBlock add(float f) + { + return add(new Float(f)); + } + + public ParameterBlock add(double d) + { + return add(new Double(d)); + } + + public ParameterBlock set(Object o, int index) + { + parameters.ensureCapacity(index); + parameters.set(index, o); + return this; + } + + public ParameterBlock set(byte b, int index) + { + return set(new Byte(b), index); + } + + public ParameterBlock set(char c, int index) + { + return set(new Character(c), index); + } + + public ParameterBlock set(short s, int index) + { + return set(new Short(s), index); + } + + public ParameterBlock set(int i, int index) + { + return set(new Integer(i), index); + } + + public ParameterBlock set(long l, int index) + { + return set(new Long(l), index); + } + + public ParameterBlock set(float f, int index) + { + return set(new Float(f), index); + } + + public ParameterBlock set(double d, int index) + { + return set(new Double(d), index); + } + + public Object getObjectParameter(int index) + { + return parameters.get(index); + } + + public byte getByteParameter(int index) + { + return ((Byte) parameters.get(index)).byteValue(); + } + + public char getCharParameter(int index) + { + return ((Character) parameters.get(index)).charValue(); + } + + public short getShortParameter(int index) + { + return ((Short) parameters.get(index)).shortValue(); + } + + public int getIntParameter(int index) + { + return ((Integer) parameters.get(index)).intValue(); + } + + public long getLongParameter(int index) + { + return ((Long) parameters.get(index)).longValue(); + } + + public float getFloatParameter(int index) + { + return ((Float) parameters.get(index)).floatValue(); + } + + public double getDoubleParameter(int index) + { + return ((Double) parameters.get(index)).doubleValue(); + } + + public Class[] getParamClasses() + { + int i = parameters.size(); + Class[] result = new Class[i]; + while (--i >= 0) + { + Class c = parameters.get(i).getClass(); + if (c == Byte.class) + result[i] = byte.class; + else if (c == Character.class) + result[i] = char.class; + else if (c == Short.class) + result[i] = short.class; + else if (c == Integer.class) + result[i] = int.class; + else if (c == Long.class) + result[i] = long.class; + else if (c == Float.class) + result[i] = float.class; + else if (c == Double.class) + result[i] = double.class; + else + result[i] = c; + } + return result; + } +} // class ParameterBlock diff --git a/libjava/classpath/java/awt/image/renderable/RenderContext.java b/libjava/classpath/java/awt/image/renderable/RenderContext.java new file mode 100644 index 0000000..67f0b8a --- /dev/null +++ b/libjava/classpath/java/awt/image/renderable/RenderContext.java @@ -0,0 +1,141 @@ +/* RenderContext.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image.renderable; + +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.geom.AffineTransform; + +public class RenderContext implements Cloneable +{ + private AffineTransform xform; + private Shape aoi; + private RenderingHints hints; + + public RenderContext(AffineTransform xform, Shape aoi, RenderingHints hints) + { + this.xform = xform; + this.aoi = aoi; + this.hints = hints; + } + + public RenderContext(AffineTransform xform) + { + this(xform, null, null); + } + + public RenderContext(AffineTransform xform, RenderingHints hints) + { + this(xform, null, hints); + } + + public RenderContext(AffineTransform xform, Shape aoi) + { + this(xform, aoi, null); + } + + public RenderingHints getRenderingHints() + { + return hints; + } + + public void setRenderingHints(RenderingHints hints) + { + this.hints = hints; + } + + public void setTransform(AffineTransform xform) + { + this.xform = xform; + } + + public void preConcatenateTransform(AffineTransform pre) + { + preConcetenateTransform (pre); + } + + /** @deprecated */ + public void preConcetenateTransform(AffineTransform pre) + { + xform.preConcatenate (pre); + } + + public void concatenateTransform(AffineTransform post) + { + concetenateTransform (post); + } + + /** @deprecated */ + public void concetenateTransform(AffineTransform post) + { + xform.concatenate (post); + } + + public AffineTransform getTransform() + { + return xform; + } + + public void setAreaOfInterest(Shape aoi) + { + this.aoi = aoi; + } + + public Shape getAreaOfInterest() + { + return aoi; + } + + public Object clone() + { + try + { + RenderContext copy = (RenderContext) super.clone(); + if (xform != null) + copy.xform = (AffineTransform) xform.clone(); + if (hints != null) + copy.hints = (RenderingHints) hints.clone(); + return copy; + } + catch (CloneNotSupportedException e) + { + throw (Error) new InternalError().initCause(e); // impossible + } + } +} // class RenderContext diff --git a/libjava/classpath/java/awt/image/renderable/RenderableImage.java b/libjava/classpath/java/awt/image/renderable/RenderableImage.java new file mode 100644 index 0000000..45d2eb7 --- /dev/null +++ b/libjava/classpath/java/awt/image/renderable/RenderableImage.java @@ -0,0 +1,62 @@ +/* RenderableImage.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image.renderable; + +import java.awt.RenderingHints; +import java.awt.image.RenderedImage; +import java.util.Vector; + +public interface RenderableImage +{ + String HINTS_OBSERVED = "HINTS_OBSERVED"; + + Vector getSources(); + Object getProperty(String name); + String[] getPropertyNames(); + boolean isDynamic(); + float getWidth(); + float getHeight(); + float getMinX(); + float getMinY(); + RenderedImage createScaledRendering(int w, int h, RenderingHints hints); + RenderedImage createDefaultRendering(); + RenderedImage createRendering(RenderContext context); + +} // interface RenderableImage + diff --git a/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java b/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java new file mode 100644 index 0000000..5385a82 --- /dev/null +++ b/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java @@ -0,0 +1,157 @@ +/* RenderableImageOp.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image.renderable; + +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.image.RenderedImage; +import java.util.Vector; + +public class RenderableImageOp implements RenderableImage +{ + private final ContextualRenderedImageFactory crif; + private ParameterBlock block; + + public RenderableImageOp(ContextualRenderedImageFactory crif, + ParameterBlock block) + { + this.crif = crif; + this.block = (ParameterBlock) block.clone(); + } + + public Vector getSources() + { + if (block.sources == null) + return null; + int size = block.sources.size(); + Vector v = new Vector(); + for (int i = 0; i < size; i++) + { + Object o = block.sources.get(i); + if (o instanceof RenderableImage) + v.add(o); + } + return v; + } + + public Object getProperty(String name) + { + return crif.getProperty(block, name); + } + + public String[] getPropertyNames() + { + return crif.getPropertyNames(); + } + + public boolean isDynamic() + { + return crif.isDynamic(); + } + + public float getWidth() + { + return (float) crif.getBounds2D(block).getWidth(); + } + + public float getHeight() + { + return (float) crif.getBounds2D(block).getHeight(); + } + + public float getMinX() + { + return (float) crif.getBounds2D(block).getX(); + } + + public float getMinY() + { + return (float) crif.getBounds2D(block).getY(); + } + + public ParameterBlock setParameterBlock(ParameterBlock block) + { + ParameterBlock result = this.block; + this.block = (ParameterBlock) block.clone(); + return result; + } + + public ParameterBlock getParameterBlock() + { + return block; + } + + public RenderedImage createScaledRendering(int w, int h, + RenderingHints hints) + { + if (w == 0) + if (h == 0) + throw new IllegalArgumentException(); + else + w = Math.round(h * getWidth() / getHeight()); + if (h == 0) + h = Math.round(w * getHeight() / getWidth()); + AffineTransform xform = AffineTransform.getScaleInstance(w * getWidth(), + h * getHeight()); + return createRendering(new RenderContext(xform, hints)); + } + + public RenderedImage createDefaultRendering() + { + return createRendering(new RenderContext(new AffineTransform())); + } + + public RenderedImage createRendering(RenderContext context) + { + ParameterBlock copy = (ParameterBlock) block.clone(); + int i = block.sources.size(); + while (--i >= 0) + { + Object o = block.sources.get(i); + if (o instanceof RenderableImage) + { + RenderableImage ri = (RenderableImage) o; + RenderContext rc = crif.mapRenderContext(i, context, block, ri); + copy.sources.set(i, ri.createRendering(rc)); + } + } + // Now copy.sources should be only RenderedImages. + return crif.create(context, copy); + } +} // class RenderableImageOp diff --git a/libjava/classpath/java/awt/image/renderable/RenderableImageProducer.java b/libjava/classpath/java/awt/image/renderable/RenderableImageProducer.java new file mode 100644 index 0000000..78f3051 --- /dev/null +++ b/libjava/classpath/java/awt/image/renderable/RenderableImageProducer.java @@ -0,0 +1,79 @@ +/* RenderableImageProducer.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image.renderable; + +import java.awt.image.ImageConsumer; +import java.awt.image.ImageProducer; + +public class RenderableImageProducer implements ImageProducer, Runnable +{ + public RenderableImageProducer(RenderableImage image, RenderContext context) + { + throw new Error("not implemented"); + } + + public void setRenderContext(RenderContext context) + { + } + + public void addConsumer(ImageConsumer consumer) + { + } + + public boolean isConsumer(ImageConsumer consumer) + { + return false; + } + + public void removeConsumer(ImageConsumer consumer) + { + } + + public void startProduction(ImageConsumer consumer) + { + } + + public void requestTopDownLeftRightResend(ImageConsumer consumer) + { + } + + public void run() + { + } +} // class RenderableImageProducer diff --git a/libjava/classpath/java/awt/image/renderable/RenderedImageFactory.java b/libjava/classpath/java/awt/image/renderable/RenderedImageFactory.java new file mode 100644 index 0000000..6ff4cb0 --- /dev/null +++ b/libjava/classpath/java/awt/image/renderable/RenderedImageFactory.java @@ -0,0 +1,47 @@ +/* RenderedImageFactory.java -- + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.image.renderable; + +import java.awt.RenderingHints; +import java.awt.image.RenderedImage; + +public interface RenderedImageFactory +{ + RenderedImage create(ParameterBlock block, RenderingHints hints); +} // interface RenderedImageFactory diff --git a/libjava/classpath/java/awt/image/renderable/package.html b/libjava/classpath/java/awt/image/renderable/package.html new file mode 100644 index 0000000..a24237e --- /dev/null +++ b/libjava/classpath/java/awt/image/renderable/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.image.renderable package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.image.renderable</title></head> + +<body> +<p></p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/package.html b/libjava/classpath/java/awt/package.html new file mode 100644 index 0000000..c5ff988 --- /dev/null +++ b/libjava/classpath/java/awt/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt</title></head> + +<body> +<p>Abstract Window Toolkit classes.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/peer/ButtonPeer.java b/libjava/classpath/java/awt/peer/ButtonPeer.java new file mode 100644 index 0000000..a55fc22 --- /dev/null +++ b/libjava/classpath/java/awt/peer/ButtonPeer.java @@ -0,0 +1,46 @@ +/* ButtonPeer.java -- Peer interface for buttons + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface ButtonPeer extends ComponentPeer +{ + void setLabel (String label); + +} // interface ButtonPeer + diff --git a/libjava/classpath/java/awt/peer/CanvasPeer.java b/libjava/classpath/java/awt/peer/CanvasPeer.java new file mode 100644 index 0000000..4b33835 --- /dev/null +++ b/libjava/classpath/java/awt/peer/CanvasPeer.java @@ -0,0 +1,45 @@ +/* CanvasPeer.java -- Peer interface for a canvas + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface CanvasPeer extends ComponentPeer +{ + +} // interface CanvasPeer + diff --git a/libjava/classpath/java/awt/peer/CheckboxMenuItemPeer.java b/libjava/classpath/java/awt/peer/CheckboxMenuItemPeer.java new file mode 100644 index 0000000..5213dc9 --- /dev/null +++ b/libjava/classpath/java/awt/peer/CheckboxMenuItemPeer.java @@ -0,0 +1,46 @@ +/* CheckboxMenuItemPeer.java -- Peer interface for checkbox menu items + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface CheckboxMenuItemPeer extends MenuItemPeer +{ + void setState (boolean state); + +} // interface CheckboxMenuItemPeer + diff --git a/libjava/classpath/java/awt/peer/CheckboxPeer.java b/libjava/classpath/java/awt/peer/CheckboxPeer.java new file mode 100644 index 0000000..8b23b3f --- /dev/null +++ b/libjava/classpath/java/awt/peer/CheckboxPeer.java @@ -0,0 +1,52 @@ +/* CheckboxPeer.java -- Interface for checkbox peer + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.CheckboxGroup; + +public interface CheckboxPeer extends ComponentPeer +{ + void setCheckboxGroup (CheckboxGroup group); + + void setLabel (String label); + + void setState (boolean state); + +} // interface CheckboxPeer + diff --git a/libjava/classpath/java/awt/peer/ChoicePeer.java b/libjava/classpath/java/awt/peer/ChoicePeer.java new file mode 100644 index 0000000..8ed1107 --- /dev/null +++ b/libjava/classpath/java/awt/peer/ChoicePeer.java @@ -0,0 +1,54 @@ +/* ChoicePeer.java -- Peer for choice box + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface ChoicePeer extends ComponentPeer +{ + void add (String item, int index); + + void addItem (String item, int index); + + void remove (int index); + + void removeAll(); + + void select (int index); + +} // interface ChoicePeer + diff --git a/libjava/classpath/java/awt/peer/ComponentPeer.java b/libjava/classpath/java/awt/peer/ComponentPeer.java new file mode 100644 index 0000000..7ed8f60 --- /dev/null +++ b/libjava/classpath/java/awt/peer/ComponentPeer.java @@ -0,0 +1,187 @@ +/* ComponentPeer.java -- Toplevel component peer + Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.AWTEvent; +import java.awt.AWTException; +import java.awt.BufferCapabilities; +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.event.PaintEvent; +import java.awt.image.ColorModel; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.awt.image.VolatileImage; + +public interface ComponentPeer +{ + int checkImage(Image img, int width, int height, + ImageObserver ob); + Image createImage(ImageProducer prod); + Image createImage(int width, int height); + void disable(); + void dispose(); + void enable(); + ColorModel getColorModel(); + FontMetrics getFontMetrics(Font f); + Graphics getGraphics(); + Point getLocationOnScreen(); + Dimension getMinimumSize(); + Dimension getPreferredSize(); + Toolkit getToolkit(); + void handleEvent(AWTEvent e); + void hide(); + + /** + * Part of the earlier 1.1 API, replaced by isFocusable(). + */ + boolean isFocusTraversable(); + boolean isFocusable(); + Dimension minimumSize(); + Dimension preferredSize(); + void paint(Graphics graphics); + boolean prepareImage(Image img, int width, int height, + ImageObserver ob); + void print(Graphics graphics); + void repaint(long tm, int x, int y, int width, int height); + + /** + * Part of the earlier 1.1 API, apparently replaced by argument + * form of the same method. + */ + void requestFocus(); + boolean requestFocus (Component source, boolean bool1, boolean bool2, long x); + + void reshape(int x, int y, int width, int height); + void setBackground(Color color); + void setBounds(int x, int y, int width, int height); + + /** + * Part of the earlier 1.1 API, apparently no longer needed. + */ + void setCursor(Cursor cursor); + + void setEnabled(boolean enabled); + void setFont(Font font); + void setForeground(Color color); + void setVisible(boolean visible); + void show(); + + /** + * Get the graphics configuration of the component. The color model + * of the component can be derived from the configuration. + */ + GraphicsConfiguration getGraphicsConfiguration(); + + /** + * Part of an older API, no longer needed. + */ + void setEventMask (long mask); + + // Methods below are introduced since 1.1 + boolean isObscured(); + boolean canDetermineObscurity(); + void coalescePaintEvent(PaintEvent e); + void updateCursorImmediately(); + boolean handlesWheelScrolling(); + + /** + * A convenience method that creates a volatile image. The volatile + * image is created on the screen device on which this component is + * displayed, in the device's current graphics configuration. + * + * @param width width of the image + * @param height height of the image + * + * @see VolatileImage + * + * @since 1.2 + */ + VolatileImage createVolatileImage(int width, int height); + + /** + * Create a number of image buffers that implement a buffering + * strategy according to the given capabilities. + * + * @param numBuffers the number of buffers + * @param caps the buffering capabilities + * + * @throws AWTException if the specified buffering strategy is not + * implemented + * + * @since 1.2 + */ + void createBuffers(int numBuffers, BufferCapabilities caps) + throws AWTException; + + /** + * Return the back buffer of this component. + * + * @return the back buffer of this component. + * + * @since 1.2 + */ + Image getBackBuffer(); + + /** + * Perform a page flip, leaving the contents of the back buffer in + * the specified state. + * + * @param contents the state in which to leave the back buffer + * + * @since 1.2 + */ + void flip(BufferCapabilities.FlipContents contents); + + /** + * Destroy the resources created by createBuffers. + * + * @since 1.2 + */ + void destroyBuffers(); +} diff --git a/libjava/classpath/java/awt/peer/ContainerPeer.java b/libjava/classpath/java/awt/peer/ContainerPeer.java new file mode 100644 index 0000000..f1373a1 --- /dev/null +++ b/libjava/classpath/java/awt/peer/ContainerPeer.java @@ -0,0 +1,59 @@ +/* ContainerPeer.java -- Interface for container peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.peer; + +import java.awt.Insets; + +public interface ContainerPeer extends ComponentPeer +{ + Insets insets(); + + Insets getInsets(); + + void beginValidate(); + + void endValidate(); + + void beginLayout(); + + void endLayout(); + + boolean isPaintPending(); + +} // interface ContainerPeer + diff --git a/libjava/classpath/java/awt/peer/DialogPeer.java b/libjava/classpath/java/awt/peer/DialogPeer.java new file mode 100644 index 0000000..e26d64f --- /dev/null +++ b/libjava/classpath/java/awt/peer/DialogPeer.java @@ -0,0 +1,48 @@ +/* DialogPeer.java -- Interface for dialog box peer + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface DialogPeer extends WindowPeer +{ + void setResizable (boolean resizeable); + + void setTitle (String title); + +} // interface DialogPeer + diff --git a/libjava/classpath/java/awt/peer/FileDialogPeer.java b/libjava/classpath/java/awt/peer/FileDialogPeer.java new file mode 100644 index 0000000..7db1798 --- /dev/null +++ b/libjava/classpath/java/awt/peer/FileDialogPeer.java @@ -0,0 +1,52 @@ +/* FileDialogPeer.java -- Interface for file selection dialog box peer + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.io.FilenameFilter; + +public interface FileDialogPeer extends DialogPeer +{ + void setFile (String file); + + void setDirectory (String dir); + + void setFilenameFilter (FilenameFilter ff); + +} // interface FileDialogPeer + diff --git a/libjava/classpath/java/awt/peer/FontPeer.java b/libjava/classpath/java/awt/peer/FontPeer.java new file mode 100644 index 0000000..f0ba6d8 --- /dev/null +++ b/libjava/classpath/java/awt/peer/FontPeer.java @@ -0,0 +1,45 @@ +/* FontPeer.java -- Interface for font peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface FontPeer +{ + +} // interface FontPeer + diff --git a/libjava/classpath/java/awt/peer/FramePeer.java b/libjava/classpath/java/awt/peer/FramePeer.java new file mode 100644 index 0000000..13498ff --- /dev/null +++ b/libjava/classpath/java/awt/peer/FramePeer.java @@ -0,0 +1,55 @@ +/* FramePeer.java -- Interface for frame peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.Image; +import java.awt.MenuBar; +import java.awt.Rectangle; + +public interface FramePeer extends WindowPeer +{ + void setIconImage(Image image); + void setMenuBar(MenuBar mb); + void setResizable(boolean resizable); + void setTitle(String title); + int getState(); + void setState(int state); + void setMaximizedBounds(Rectangle r); +} // interface FramePeer + diff --git a/libjava/classpath/java/awt/peer/LabelPeer.java b/libjava/classpath/java/awt/peer/LabelPeer.java new file mode 100644 index 0000000..d0fca46 --- /dev/null +++ b/libjava/classpath/java/awt/peer/LabelPeer.java @@ -0,0 +1,46 @@ +/* LabelPeer.java -- Interface for simple text lable peer + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface LabelPeer extends ComponentPeer +{ + void setAlignment(int alignment); + void setText(String text); +} // interface LabelPeer + diff --git a/libjava/classpath/java/awt/peer/LightweightPeer.java b/libjava/classpath/java/awt/peer/LightweightPeer.java new file mode 100644 index 0000000..93cad7a --- /dev/null +++ b/libjava/classpath/java/awt/peer/LightweightPeer.java @@ -0,0 +1,45 @@ +/* LightweightPeer.java -- Interface for lightweight peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface LightweightPeer extends ComponentPeer +{ + +} // interface LightweightPeer + diff --git a/libjava/classpath/java/awt/peer/ListPeer.java b/libjava/classpath/java/awt/peer/ListPeer.java new file mode 100644 index 0000000..c0f765d --- /dev/null +++ b/libjava/classpath/java/awt/peer/ListPeer.java @@ -0,0 +1,61 @@ +/* ListPeer.java -- Interface for list box peer + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.Dimension; + +public interface ListPeer extends ComponentPeer +{ + void add(String item, int index); + void addItem(String item, int index); + void clear(); + void delItems(int start_index, int end_index); + void deselect(int index); + int[] getSelectedIndexes(); + void makeVisible(int index); + Dimension minimumSize(int s); + Dimension preferredSize(int s); + void removeAll(); + void select(int index); + void setMultipleMode(boolean multi); + void setMultipleSelections(boolean multi); + Dimension getPreferredSize(int s); + Dimension getMinimumSize(int s); +} // interface ListPeer + diff --git a/libjava/classpath/java/awt/peer/MenuBarPeer.java b/libjava/classpath/java/awt/peer/MenuBarPeer.java new file mode 100644 index 0000000..c5f7c58 --- /dev/null +++ b/libjava/classpath/java/awt/peer/MenuBarPeer.java @@ -0,0 +1,48 @@ +/* MenuBarPeer.java -- Interface for menu bar peer + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.Menu; + +public interface MenuBarPeer extends MenuComponentPeer +{ + void addHelpMenu(Menu menu); + void delMenu(int index); +} // interface MenuBarPeer + diff --git a/libjava/classpath/java/awt/peer/MenuComponentPeer.java b/libjava/classpath/java/awt/peer/MenuComponentPeer.java new file mode 100644 index 0000000..1b10ca1 --- /dev/null +++ b/libjava/classpath/java/awt/peer/MenuComponentPeer.java @@ -0,0 +1,45 @@ +/* MenuComponentPeer.java -- + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface MenuComponentPeer +{ + void dispose(); +} // interface MenuComponentPeer + diff --git a/libjava/classpath/java/awt/peer/MenuItemPeer.java b/libjava/classpath/java/awt/peer/MenuItemPeer.java new file mode 100644 index 0000000..3ba1027 --- /dev/null +++ b/libjava/classpath/java/awt/peer/MenuItemPeer.java @@ -0,0 +1,48 @@ +/* MenuItemPeer.java -- Interface for menu item peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface MenuItemPeer extends MenuComponentPeer +{ + void disable(); + void enable(); + void setEnabled(boolean enabled); + void setLabel(String text); +} // interface MenuItemPeer + diff --git a/libjava/classpath/java/awt/peer/MenuPeer.java b/libjava/classpath/java/awt/peer/MenuPeer.java new file mode 100644 index 0000000..c51ea73 --- /dev/null +++ b/libjava/classpath/java/awt/peer/MenuPeer.java @@ -0,0 +1,48 @@ +/* MenuPeer.java -- Interface for menu peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.MenuItem; + +public interface MenuPeer extends MenuItemPeer +{ + void addItem (MenuItem item); + void delItem (int index); +} + diff --git a/libjava/classpath/java/awt/peer/PanelPeer.java b/libjava/classpath/java/awt/peer/PanelPeer.java new file mode 100644 index 0000000..192632e --- /dev/null +++ b/libjava/classpath/java/awt/peer/PanelPeer.java @@ -0,0 +1,45 @@ +/* PanelPeer.java -- Interface for panel peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface PanelPeer extends ContainerPeer +{ + +} // interface PanelPeer + diff --git a/libjava/classpath/java/awt/peer/PopupMenuPeer.java b/libjava/classpath/java/awt/peer/PopupMenuPeer.java new file mode 100644 index 0000000..2e8f4bb --- /dev/null +++ b/libjava/classpath/java/awt/peer/PopupMenuPeer.java @@ -0,0 +1,53 @@ +/* PopupMenuPeer.java -- Interface for popup menu peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.Component; +import java.awt.Event; + +public interface PopupMenuPeer extends MenuPeer +{ + /** + * Part of the older API, replaced by event version instead. + */ + void show (Component origin, int x, int y); + + void show (Event e); +} // interface PopupMenuPeer + diff --git a/libjava/classpath/java/awt/peer/RobotPeer.java b/libjava/classpath/java/awt/peer/RobotPeer.java new file mode 100644 index 0000000..db81c80 --- /dev/null +++ b/libjava/classpath/java/awt/peer/RobotPeer.java @@ -0,0 +1,54 @@ +/* RobotPeer.java -- Interface for programatically driving GUI + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.Rectangle; + +public interface RobotPeer +{ + void mouseMove (int x, int y); + void mousePress (int buttons); + void mouseRelease (int buttons); + void mouseWheel (int wheelAmt); + void keyPress (int keycode); + void keyRelease (int keycode); + int getRGBPixel (int x, int y); + int[] getRGBPixels (Rectangle screen); +} // interface RobotPeer + diff --git a/libjava/classpath/java/awt/peer/ScrollPanePeer.java b/libjava/classpath/java/awt/peer/ScrollPanePeer.java new file mode 100644 index 0000000..de4331e --- /dev/null +++ b/libjava/classpath/java/awt/peer/ScrollPanePeer.java @@ -0,0 +1,52 @@ +/* ScrollPanePeer.java -- Interface for scrollable panes + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.Adjustable; + +public interface ScrollPanePeer extends ContainerPeer +{ + int getHScrollbarHeight(); + int getVScrollbarWidth(); + void setScrollPosition(int h, int v); + void childResized(int width, int height); + void setUnitIncrement(Adjustable item, int inc); + void setValue(Adjustable item, int value); +} // interface ScollPanePeer + diff --git a/libjava/classpath/java/awt/peer/ScrollbarPeer.java b/libjava/classpath/java/awt/peer/ScrollbarPeer.java new file mode 100644 index 0000000..fe4f24d --- /dev/null +++ b/libjava/classpath/java/awt/peer/ScrollbarPeer.java @@ -0,0 +1,47 @@ +/* ScrollbarPeer.java -- Interface for scrollbar peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface ScrollbarPeer extends ComponentPeer +{ + void setLineIncrement(int inc); + void setPageIncrement(int inc); + void setValues(int value, int visible, int min, int max); +} // interface ScrollbarPeer + diff --git a/libjava/classpath/java/awt/peer/TextAreaPeer.java b/libjava/classpath/java/awt/peer/TextAreaPeer.java new file mode 100644 index 0000000..354e46d --- /dev/null +++ b/libjava/classpath/java/awt/peer/TextAreaPeer.java @@ -0,0 +1,53 @@ +/* TextAreaPeer.java -- Interface for text area peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.Dimension; + +public interface TextAreaPeer extends TextComponentPeer +{ + void insert(String text, int pos); + void insertText(String text, int pos); + Dimension minimumSize(int rows, int cols); + Dimension getMinimumSize(int rows, int cols); + Dimension preferredSize(int rows, int cols); + Dimension getPreferredSize(int rows, int cols); + void replaceRange(String text, int start_pos, int end_pos); + void replaceText(String text, int start_pos, int end_pos); +} // interface TextAreaPeer diff --git a/libjava/classpath/java/awt/peer/TextComponentPeer.java b/libjava/classpath/java/awt/peer/TextComponentPeer.java new file mode 100644 index 0000000..cacc7d8 --- /dev/null +++ b/libjava/classpath/java/awt/peer/TextComponentPeer.java @@ -0,0 +1,57 @@ +/* TextComponentPeer.java -- Superclass interface for text components + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.Rectangle; + +public interface TextComponentPeer extends ComponentPeer +{ + int getSelectionEnd(); + int getSelectionStart(); + String getText(); + void setText(String text); + void select(int start_pos, int end_pos); + void setEditable(boolean editable); + int getCaretPosition(); + void setCaretPosition(int pos); + int getIndexAtPoint(int x, int y); + Rectangle getCharacterBounds(int pos); + long filterEvents(long filter); +} // interface TextComponentPeer + diff --git a/libjava/classpath/java/awt/peer/TextFieldPeer.java b/libjava/classpath/java/awt/peer/TextFieldPeer.java new file mode 100644 index 0000000..e68d666 --- /dev/null +++ b/libjava/classpath/java/awt/peer/TextFieldPeer.java @@ -0,0 +1,52 @@ +/* TextFieldPeer.java -- Interface for text field peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +import java.awt.Dimension; + +public interface TextFieldPeer extends TextComponentPeer +{ + Dimension minimumSize(int len); + Dimension preferredSize(int len); + Dimension getMinimumSize(int len); + Dimension getPreferredSize(int len); + void setEchoChar(char echo_char); + void setEchoCharacter(char echo_char); +} // interface TextFieldPeer + diff --git a/libjava/classpath/java/awt/peer/WindowPeer.java b/libjava/classpath/java/awt/peer/WindowPeer.java new file mode 100644 index 0000000..8f136dd --- /dev/null +++ b/libjava/classpath/java/awt/peer/WindowPeer.java @@ -0,0 +1,46 @@ +/* WindowPeer.java -- Interface for window peers + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.peer; + +public interface WindowPeer extends ContainerPeer +{ + void toBack(); + void toFront(); +} // interface WindowPeer + diff --git a/libjava/classpath/java/awt/peer/package.html b/libjava/classpath/java/awt/peer/package.html new file mode 100644 index 0000000..7a7458c --- /dev/null +++ b/libjava/classpath/java/awt/peer/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.peer package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.peer</title></head> + +<body> +<p>Interfaces for using native interface components.</p> + +</body> +</html> diff --git a/libjava/classpath/java/awt/print/Book.java b/libjava/classpath/java/awt/print/Book.java new file mode 100644 index 0000000..b084a17 --- /dev/null +++ b/libjava/classpath/java/awt/print/Book.java @@ -0,0 +1,159 @@ +/* Book.java -- A mixed group of pages to print. + Copyright (C) 1999, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.print; + +import java.util.Vector; + +/** + * This class allows documents to be created with different paper types, + * page formatters, and painters. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class Book implements Pageable +{ + /** + * Painter objects for the book. + */ + Vector printables = new Vector(); + + /** + * Page formats for the book. + */ + Vector page_formats = new Vector(); + + /** + * Initializes a new instance of <code>Book</code> that is empty. + */ + public Book() + { + } + + /** + * Returns the number of pages in this book. + * + * @return The number of pages in this book. + */ + public int getNumberOfPages() + { + return printables.size(); + } + + /** + * This method returns the <code>PageFormat</code> object for the + * specified page. + * + * @param page_number The number of the page to get information for, where + * page numbers start at 0. + * + * @return The <code>PageFormat</code> object for the specified page. + * + * @exception IndexOutOfBoundsException If the page number is not valid. + */ + public PageFormat getPageFormat(int page_number) + { + return (PageFormat) page_formats.elementAt(page_number); + } + + /** + * This method returns the <code>Printable</code> object for the + * specified page. + * + * @param page_number The number of the page to get information for, where + * page numbers start at 0. + * + * @return The <code>Printable</code> object for the specified page. + * + * @exception IndexOutOfBoundsException If the page number is not valid. + */ + public Printable getPrintable(int page_number) + { + return (Printable) printables.elementAt(page_number); + } + + /** + * This method appends a page to the end of the book. + * + * @param printable The <code>Printable</code> for this page. + * @param page_format The <code>PageFormat</code> for this page. + * + * @exception NullPointerException If either argument is <code>null</code>. + */ + public void append(Printable printable, PageFormat page_format) + { + append(printable, page_format, 1); + } + + /** + * This method appends the specified number of pages to the end of the book. + * Each one will be associated with the specified <code>Printable</code> + * and <code>PageFormat</code>. + * + * @param printable The <code>Printable</code> for this page. + * @param page_format The <code>PageFormat</code> for this page. + * @param num_pages The number of pages to append. + * + * @exception NullPointerException If any argument is <code>null</code>. + */ + public void append(Printable printable, PageFormat page_format, int num_pages) + { + for (int i = 0; i < num_pages; i++) + { + printables.addElement(printable); + page_formats.addElement(page_format); + } + } + + /** + * This method changes the <code>Printable</code> and <code>PageFormat</code> + * for the specified page. The page must already exist or an exception + * will be thrown. + * + * @param page_num The page number to alter. + * @param printable The new <code>Printable</code> for the page. + * @param page_format The new <code>PageFormat</code> for the page. + * + * @throws IndexOutOfBoundsException If the specified page does not exist. + */ + public void setPage(int page_num, Printable printable, PageFormat page_format) + { + printables.setElementAt(printable, page_num); + page_formats.setElementAt(page_format, page_num); + } +} diff --git a/libjava/classpath/java/awt/print/PageFormat.java b/libjava/classpath/java/awt/print/PageFormat.java new file mode 100644 index 0000000..6399552 --- /dev/null +++ b/libjava/classpath/java/awt/print/PageFormat.java @@ -0,0 +1,292 @@ +/* PageFormat.java -- Information about the page format + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.print; + +/** + * This class contains information about the desired page format to + * use for printing a particular set of pages. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class PageFormat implements Cloneable +{ + +/* + * Static Variables + */ + +/** + * A constant for a landscaped page orientation. Used by + * <code>getOrientation</code> and <code>setOrientation</code>. + */ +public static final int LANDSCAPE = 0; + +/** + * A constant for a portrait page orientation. Used by + * <code>getOrientation</code> and <code>setOrientation</code>. + */ +public static final int PORTRAIT = 1; + +/** + * A constant for a reversed landscaped page orientation. This is + * the orientation used by Macintosh's for landscape. The origin is + * in the upper right hand corner instead of the upper left. The + * X and Y axes are reversed. Used by <code>getOrientation</code> and + * <code>setOrientation</code>. + */ +public static final int REVERSE_LANDSCAPE = 2; + +/*************************************************************************/ + +/* + * Instance Variables + */ + +// The page orientation +private int orientation; + +// The paper type +private Paper paper; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * This method creates a default page layout, which will be in portrait + * format. + */ +public +PageFormat() +{ + this.paper = new Paper(); + this.orientation = PORTRAIT; +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * This method returns the width of the page, in 1/72nd's of an inch. The + * "width" measured depends on orientation. + * + * @return The width of the page. + */ +public double +getWidth() +{ + return(paper.getWidth()); +} + +/*************************************************************************/ + +/** + * This method returns the height of the page, in 1/72nd's of an inch. + * The "height" measured depends on the orientation. + * + * @return The height of the page. + */ +public double +getHeight() +{ + return(paper.getHeight()); +} + +/*************************************************************************/ + +/** + * This method returns the X coordinate value of the upper leftmost + * drawable area of the paper. + * + * @return The upper leftmost imageable X coordinate. + */ +public double +getImageableX() +{ + return(paper.getImageableX()); +} + +/*************************************************************************/ + +/** + * This method returns the Y coordinate value of the upper leftmost + * drawable area of the paper. + * + * @return The upper leftmost imageable Y coordinate. + */ +public double +getImageableY() +{ + return(paper.getImageableY()); +} + +/*************************************************************************/ + +/** + * This method returns the imageable width of the paper, in 1/72nd's of + * an inch. + * + * @return The imageable width of the paper. + */ +public double +getImageableWidth() +{ + return(paper.getImageableWidth()); +} + +/*************************************************************************/ + +/** + * This method returns the imageable height of the paper, in 1/72nd's of + * an inch. + * + * @return The imageable height of the paper. + */ +public double getImageableHeight() +{ + return(paper.getImageableHeight()); +} + +/*************************************************************************/ + +/** + * Returns a copy of the <code>paper</code> object being used for this + * page format. + * + * @return A copy of the <code>Paper</code> object for this format. + */ +public Paper +getPaper() +{ + return((Paper)paper.clone()); +} + +/*************************************************************************/ + +/** + * Sets the <code>Paper</code> object to be used by this page format. + * + * @param paper The new <code>Paper</code> object for this page format. + */ +public void +setPaper(Paper paper) +{ + this.paper = paper; +} + +/*************************************************************************/ + +/** + * This method returns the current page orientation. The value returned + * will be one of the page orientation constants from this class. + * + * @return The current page orientation. + */ +public int +getOrientation() +{ + return(orientation); +} + +/*************************************************************************/ + +/** + * This method sets the page orientation for this format to the + * specified value. It must be one of the page orientation constants + * from this class or an exception will be thrown. + * + * @param orientation The new page orientation. + * + * @exception IllegalArgumentException If the specified page orientation + * value is not one of the constants from this class. + */ +public void +setOrientation(int orientation) throws IllegalArgumentException +{ + if ((orientation != PORTRAIT) && + (orientation != LANDSCAPE) && + (orientation != REVERSE_LANDSCAPE)) + throw new IllegalArgumentException("Bad page orientation value: " + + orientation); + + this.orientation = orientation; +} + +/*************************************************************************/ + +/** + * This method returns a matrix used for transforming user space + * coordinates to page coordinates. The value returned will be six + * doubles as described in <code>java.awt.geom.AffineTransform</code>. + * + * @return The transformation matrix for this page format. + */ +public double[] +getMatrix() +{ + throw new RuntimeException("Not implemented since I don't know what to do"); +} + +/*************************************************************************/ + +/** + * This method returns a copy of this object. + * + * @return A copy of this object. + */ +public Object +clone() +{ + try + { + return(super.clone()); + } + catch(CloneNotSupportedException e) + { + return(null); + } +} + +} // class PageFormat + diff --git a/libjava/classpath/java/awt/print/Pageable.java b/libjava/classpath/java/awt/print/Pageable.java new file mode 100644 index 0000000..12fa542 --- /dev/null +++ b/libjava/classpath/java/awt/print/Pageable.java @@ -0,0 +1,113 @@ +/* Pageable.java -- Pages to be printed + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.print; + +/** + * This interface represents pages that are to be printed. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public interface Pageable +{ + +/* + * Static Variables + */ + +/** + * This constant is returned when <code>getNumberOfPages()</code> + * cannot determine the number of pages available for printing. + */ +int UNKNOWN_NUMBER_OF_PAGES = -1; + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * This method returns the number of pages this object contains, or + * <code>UNKNOWN_NUMBER_OF_PAGES</code> if it cannot determine the number + * of pages to be printed. + * + * @return The number of pages to be printed, or + * <code>UNKNOWN_NUMBER_OF_PAGES</code> if this is unknown. + */ +int +getNumberOfPages(); + +/*************************************************************************/ + +/** + * This method returns the <code>PageFormat</code> instance for the + * specified page. Page numbers start at zero. An exception is thrown if + * the requested page does not exist. + * + * @param pageIndex The index of the page to return the + * <code>PageFormat</code> for. + * + * @return The <code>PageFormat</code> for the requested page. + * + * @exception IndexOutOfBoundsException If the requested page number does + * not exist. + */ +PageFormat +getPageFormat(int pageIndex) throws IndexOutOfBoundsException; + +/*************************************************************************/ + +/** + * This method returns the <code>Printable</code> instance for the + * specified page. Page numbers start at zero. An exception is thrown if + * the requested page does not exist. + * + * @param pageIndex The index of the page to return the + * <code>Printable</code> for. + * + * @return The <code>Printable</code> for the requested page. + * + * @exception IndexOutOfBoundsException If the requested page number does + * not exist. + */ +Printable +getPrintable(int pageIndex) throws IndexOutOfBoundsException; + +} // interface Pageable + diff --git a/libjava/classpath/java/awt/print/Paper.java b/libjava/classpath/java/awt/print/Paper.java new file mode 100644 index 0000000..4579da3 --- /dev/null +++ b/libjava/classpath/java/awt/print/Paper.java @@ -0,0 +1,236 @@ +/* Paper.java -- Information about a paper type. + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.print; + +/** + * This class describes a particular type of paper. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class Paper implements Cloneable +{ + +/* + * Instance Variables + */ + +// Height of the paper +private double height; + +// Width of the paper +private double width; + +// Upper left imageable X coordinate +private double imageableX; + +// Upper left imageable Y coordinate +private double imageableY; + +// Imageable width of the page +private double imageableWidth; + +// Imageable height of the page +private double imageableHeight; + +/*************************************************************************/ + +/* + * Constructor + */ + +/** + * This method creates a letter sized paper with one inch margins + */ +public +Paper() +{ + width = 8.5 * 72; + height = 11 * 72; + imageableX = 72; + imageableY = 72; + imageableWidth = width - (2 * 72); + imageableHeight = height - (2 * 72); +} + +/*************************************************************************/ + +/** + * This method returns the height of the paper in 1/72nds of an inch. + * + * @return The height of the paper in 1/72nds of an inch. + */ +public double +getHeight() +{ + return(height); +} + +/*************************************************************************/ + +/** + * Returns the width of the paper in 1/72nds of an inch. + * + * @return The width of the paper in 1/72nds of an inch. + */ +public double +getWidth() +{ + return(width); +} + +/*************************************************************************/ + +/** + * This method returns the X coordinate of the upper left hand corner + * of the imageable area of the paper. + * + * @return The X coordinate of the upper left hand corner of the imageable + * area of the paper. + */ +public double +getImageableX() +{ + return(imageableX); +} + +/*************************************************************************/ + +/** + * This method returns the Y coordinate of the upper left hand corner + * of the imageable area of the paper. + * + * @return The Y coordinate of the upper left hand corner of the imageable + * area of the paper. + */ +public double +getImageableY() +{ + return(imageableY); +} + +/*************************************************************************/ + +/** + * Returns the width of the imageable area of the paper. + * + * @return The width of the imageable area of the paper. + */ +public double +getImageableWidth() +{ + return(imageableWidth); +} + +/*************************************************************************/ + +/** + * Returns the height of the imageable area of the paper. + * + * @return The height of the imageable area of the paper. + */ +public double +getImageableHeight() +{ + return(imageableHeight); +} + +/*************************************************************************/ + +/** + * This method sets the size of the paper to the specified width and + * height, which are specified in 1/72nds of an inch. + * + * @param width The width of the paper in 1/72nds of an inch. + * @param height The height of the paper in 1/72nds of an inch. + */ +public void +setSize(double width, double height) +{ + this.width = width; + this.height = height; +} + +/*************************************************************************/ + +/** + * This method sets the imageable area of the paper by specifying the + * coordinates of the upper left hand corner of that area, and its + * length and height. All values are in 1/72nds of an inch. + * + * @param imageableX The X coordinate of the upper left hand corner of + * the imageable area, in 1/72nds of an inch. + * @param imageableY The Y coordinate of the upper left hand corner of + * the imageable area, in 1/72nds of an inch. + * @param imageableWidth The width of the imageable area of the paper, + * in 1/72nds of an inch. + * @param imageableHeight The heigth of the imageable area of the paper, + * in 1/72nds of an inch. + */ +public void +setImageableArea(double imageableX, double imageableY, + double imageableWidth, double imageableHeight) +{ + this.imageableX = imageableX; + this.imageableY = imageableY; + this.imageableWidth = imageableWidth; + this.imageableHeight = imageableHeight; +} + +/*************************************************************************/ + +/** + * This method creates a copy of this object. + * + * @return A copy of this object. + */ +public Object +clone() +{ + try + { + return(super.clone()); + } + catch(CloneNotSupportedException e) + { + return(null); + } +} + +} // class Paper + diff --git a/libjava/classpath/java/awt/print/Printable.java b/libjava/classpath/java/awt/print/Printable.java new file mode 100644 index 0000000..775167e --- /dev/null +++ b/libjava/classpath/java/awt/print/Printable.java @@ -0,0 +1,80 @@ +/* Printable.java -- Renders a page to the print device + Copyright (C) 1999, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.awt.print; + +import java.awt.Graphics; + + +/** + * This interface provides a mechanism for the actual printing of pages to the + * printer. The object implementing this interface performs the page + * rendering. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public interface Printable +{ + /** + * This value is returned by the <code>print()</code> method to indicate + * that the requested page exists and has been printed. + */ + int PAGE_EXISTS = 0; + + /** + * This value is returned by the <code>print()</code> method to indicate + * that the requested page number does not exist. + */ + int NO_SUCH_PAGE = 1; + + /** + * This method prints the specified page to the specified graphics + * context in the specified format. The pages are numbered starting + * from zero. + * + * @param graphics The graphics context to render the pages on. + * @param format The format in which to print the page. + * @param page_number The page number to print, where numbers start at zero. + * + * @return <code>PAGE_EXISTS</code> if the requested page exists and was + * successfully printed, <code>NO_SUCH_PAGE</code> otherwise. + * + * @exception PrinterException If an error occurs during printing. + */ + int print(Graphics graphics, PageFormat format, int page_number) + throws PrinterException; +} diff --git a/libjava/classpath/java/awt/print/PrinterAbortException.java b/libjava/classpath/java/awt/print/PrinterAbortException.java new file mode 100644 index 0000000..4580630 --- /dev/null +++ b/libjava/classpath/java/awt/print/PrinterAbortException.java @@ -0,0 +1,71 @@ +/* PrinterAbortException.java -- Indicates the print job was aborted + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.print; + +/** + * This exception is thrown when the print job is aborted, either by the + * user or by the application. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @status updated to 1.4 + */ +public class PrinterAbortException extends PrinterException +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 4725169026278854136L; + + /** + * Create a new instance with no detailed error message. + */ + public PrinterAbortException() + { + } + + /** + * Create a new instance with a descriptive error message. + * + * @param message the descriptive error message + */ + public PrinterAbortException(String message) + { + super(message); + } +} // class PrinterAbortException diff --git a/libjava/classpath/java/awt/print/PrinterException.java b/libjava/classpath/java/awt/print/PrinterException.java new file mode 100644 index 0000000..c105f54 --- /dev/null +++ b/libjava/classpath/java/awt/print/PrinterException.java @@ -0,0 +1,71 @@ +/* PrinterException.java -- generic problem in the printing subsystem + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.print; + +/** + * This is the generic toplevel exception for printing errors. Subclasses + * provide more detailed descriptions of the problem. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @status updated to 1.4 + */ +public class PrinterException extends Exception +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = -3757589981158265819L; + + /** + * Create a new instance with no detailed error message. + */ + public PrinterException() + { + } + + /** + * Create a new instance with a descriptive error message. + * + * @param message the descriptive error message + */ + public PrinterException(String message) + { + super(message); + } +} // class PrinterException diff --git a/libjava/classpath/java/awt/print/PrinterGraphics.java b/libjava/classpath/java/awt/print/PrinterGraphics.java new file mode 100644 index 0000000..5ca6419 --- /dev/null +++ b/libjava/classpath/java/awt/print/PrinterGraphics.java @@ -0,0 +1,61 @@ +/* PrinterGraphics.java -- Hook to return print job controller. + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.print; + +/** + * This interface is implemented by the <code>Graphics</code> instance + * that is used for rendering pages. It provides a hook to return the + * object that is controlling the print job. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public interface PrinterGraphics +{ + +/** + * This method returns the instance of <code>PrinterJob</code> that is + * controlling this print job. + * + * @return The <code>PrinterJob</code> that is controlling this print job. + */ +PrinterJob +getPrinterJob(); + +} // interface PrinterGraphics + diff --git a/libjava/classpath/java/awt/print/PrinterIOException.java b/libjava/classpath/java/awt/print/PrinterIOException.java new file mode 100644 index 0000000..c646acd --- /dev/null +++ b/libjava/classpath/java/awt/print/PrinterIOException.java @@ -0,0 +1,98 @@ +/* PrinterIOException.java -- The print job encountered an I/O error + Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.print; + +import java.io.IOException; + +/** + * This exception is thrown when the print job encounters an I/O problem + * of some kind. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @status updated to 1.4 + */ +public class PrinterIOException extends PrinterException +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 5850870712125932846L; + + /** + * The exception that caused this (duplicates Throwable). + * + * @serial the I/O exception that terminated the job + */ + private final IOException mException; + + /** + * Initializes a new instance with the given cause. + * + * @param mException the cause + */ + public PrinterIOException(IOException mException) + { + super(mException == null ? null : mException.toString()); + initCause(mException); + this.mException = mException; + } + + /** + * Gets the underlying <code>IOException</code> that caused this exception. + * This legacy method has been replaced by {@link #getCause()}. + * + * @return the cause + */ + public IOException getIOException() + { + return mException; + } + + /** + * Gets the cause. + * + * @return the cause + */ + public Throwable getCause() + { + return mException; + } +} // class PrinterIOException + diff --git a/libjava/classpath/java/awt/print/PrinterJob.java b/libjava/classpath/java/awt/print/PrinterJob.java new file mode 100644 index 0000000..e61ab61 --- /dev/null +++ b/libjava/classpath/java/awt/print/PrinterJob.java @@ -0,0 +1,299 @@ +/* PrinterJob.java -- This job is the printer control class + Copyright (C) 1999, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.print; + +import java.awt.HeadlessException; + +import javax.print.PrintService; +import javax.print.attribute.PrintRequestAttributeSet; + +/** + * This class controls printing. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public abstract class PrinterJob +{ + // The print service associated with this job + private PrintService printer = null; + + /** + * Creates a new print job. + * + * @return A <code>PrinterJob</code> object for the newly created print job. + */ + public static PrinterJob getPrinterJob() + { + // FIXME: Need to fix this to load a default implementation instance. + return null; + } + + /** + * Initializes a new instance of <code>PrinterJob</code>. + */ + public PrinterJob() + { + } + + /** + * Returns the number of copies to be printed. + * + * @return The number of copies to be printed. + */ + public abstract int getCopies(); + + /** + * Sets the number of copies to be printed. + * + * @param copies The number of copies to be printed. + */ + public abstract void setCopies(int copies); + + /** + * Returns the name of the print job. + * + * @return The name of the print job. + */ + public abstract String getJobName(); + + /** + * Sets the name of the print job. + * + * @param job_name The name of the print job. + */ + public abstract void setJobName(String job_name); + + /** + * Returns the printing user name. + * + * @return The printing username. + */ + public abstract String getUserName(); + + /** + * Cancels an in progress print job. + */ + public abstract void cancel(); + + /** + * Tests whether or not this job has been cancelled. + * + * @return <code>true</code> if this job has been cancelled, <code>false</code> + * otherwise. + */ + public abstract boolean isCancelled(); + + /** + * Returns an instance of the default page which will have the default + * paper and orientation. + * + * @return A default instance of <code>PageFormat</code>. + */ + public PageFormat defaultPage() + { + return new PageFormat(); + } + + /** + * Clones the specified <code>PageFormat</code> object then alters the + * clone so that it represents the default page format. + * + * @param page_format The <code>PageFormat</code> to clone. + * + * @return A new default page format. + */ + public abstract PageFormat defaultPage(PageFormat page_format); + + /** + * Displays a dialog box to the user which allows the page format + * attributes to be modified. + * + * @param page_format The <code>PageFormat</code> object to modify. + * + * @return The modified <code>PageFormat</code>. + */ + public abstract PageFormat pageDialog(PageFormat page_format) + throws HeadlessException; + + /** + * @since 1.4 + */ + public PageFormat pageDialog(PrintRequestAttributeSet attributes) + throws HeadlessException + { + // FIXME: Implement this for real. + return pageDialog((PageFormat) null); + } + + /** + * Prints the pages. + */ + public abstract void print () throws PrinterException; + + /** + * Prints the page with given attributes. + */ + public abstract void print (PrintRequestAttributeSet attributes) + throws PrinterException; + + /** + * Displays a dialog box to the user which allows the print job + * attributes to be modified. + * + * @return <code>false</code> if the user cancels the dialog box, + * <code>true</code> otherwise. + */ + public abstract boolean printDialog() + throws HeadlessException; + + /** + * Displays a dialog box to the user which allows the print job + * attributes to be modified. + * + * @return <code>false</code> if the user cancels the dialog box, + * <code>true</code> otherwise. + */ + public boolean printDialog(PrintRequestAttributeSet attributes) + throws HeadlessException + { + // FIXME: Implement this for real. + return printDialog(); + } + + /** + * This sets the pages that are to be printed. + * + * @param pageable The pages to be printed, which may not be <code>null</code>. + */ + public abstract void setPageable(Pageable pageable); + + /** + * Sets this specified <code>Printable</code> as the one to use for + * rendering the pages on the print device. + * + * @param printable The <code>Printable</code> for the print job. + */ + public abstract void setPrintable(Printable printable); + + /** + * Sets the <code>Printable</code> and the page format for the pages + * to be printed. + * + * @param printable The <code>Printable</code> for the print job. + * @param page_format The <code>PageFormat</code> for the print job. + */ + public abstract void setPrintable(Printable printable, PageFormat page_format); + + /** + * Makes any alterations to the specified <code>PageFormat</code> + * necessary to make it work with the current printer. The alterations + * are made to a clone of the input object, which is then returned. + * + * @param page_format The <code>PageFormat</code> to validate. + * + * @return The validated <code>PageFormat</code>. + */ + public abstract PageFormat validatePage(PageFormat page_format); + + /** + * Find and return 2D image print services. + * + * This is the same as calling PrintServiceLookup.lookupPrintServices() + * with Pageable service-specified DocFlavor. + * @return Array of PrintService objects, could be empty. + * @since 1.4 + */ + public static PrintService[] lookupPrintServices() + { + return new PrintService[0]; + // FIXME: + // Enable this when javax.print has this implemented. +// return PrintServiceLookup.lookupPrintServices( +// new DocFlavor("application/x-java-jvm-local-objectref", +// "java.awt.print.Pageable"), +// null); + } + + /** + * Find and return 2D image stream print services. + * + * This is the same as calling + * StreamPrintServiceFactory.lookupStreamPrintServices() + * with Pageable service-specified DocFlavor. + * @param mimeType The output format mime type, or null for any type. + * @return Array of stream print services, could be empty. + * @since 1.4 + */ + // FIXME: + // Enable when javax.print has StreamPrintServiceFactory +// public static StreamPrintServiceFactory[] lookupStreamPrintServices(String mimeType) +// { +// return StreamPrintServiceFactory.lookupStreamServiceFactories( +// new DocFlavor("application/x-java-jvm-local-objectref", +// "java.awt.print.Pageable"), +// mimeType); +// } + + /** + * Return the printer for this job. If print services aren't supported by + * the subclass, returns null. + * + * @return The associated PrintService. + * @since 1.4 + */ + public PrintService getPrintService() + { + return null; + } + + /** + * Change the printer for this print job to service. Subclasses that + * support setting the print service override this method. Throws + * PrinterException when the class doesn't support setting the printer, + * the service doesn't support Pageable or Printable interfaces for 2D + * print output. + * @param service The new printer to use. + * @throws PrinterException if service is not valid. + */ + public void setPrintService(PrintService service) + throws PrinterException + { + throw new PrinterException(); + } +} diff --git a/libjava/classpath/java/awt/print/package.html b/libjava/classpath/java/awt/print/package.html new file mode 100644 index 0000000..50abcbf --- /dev/null +++ b/libjava/classpath/java/awt/print/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.awt.print package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.awt.print</title></head> + +<body> +<p>Classes for printer jobs, pages, paper sizes, graphics and formats.</p> + +</body> +</html> |