aboutsummaryrefslogtreecommitdiff
path: root/libjava/java
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@gcc.gnu.org>2004-05-27 06:17:44 +0000
committerGraydon Hoare <graydon@gcc.gnu.org>2004-05-27 06:17:44 +0000
commitc5d2de6b4c976dc152c8618ab3e8e1319018dc30 (patch)
tree2ffcb4d3889f27364cadf6d34acb5b88d5881e8a /libjava/java
parente314a036a8942fe4ce5d9fd586f0a8bac90f6df3 (diff)
downloadgcc-c5d2de6b4c976dc152c8618ab3e8e1319018dc30.zip
gcc-c5d2de6b4c976dc152c8618ab3e8e1319018dc30.tar.gz
gcc-c5d2de6b4c976dc152c8618ab3e8e1319018dc30.tar.bz2
[multiple changes]
2004-05-25 David Jee <djee@redhat.com> * java/awt/Container.java (remove): Set component's parent to null only after we removed the component from its parent's layout manager. 2004-05-25 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkComponentPeer.java (GtkComponentPeer): Set bounds regardless of whether awtComponent is valid. * gnu/java/awt/peer/gtk/GtkListPeer.java (getSize): Change native method declaration. (minimumSize): Pass visible row count into getSize(). (preferredSize): Likewise. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c (Java_gnu_java_awt_peer_gtk_GtkListPeer_getSize): Use scroll window's natural size. Use visible row count to determine the final height value to return. 2004-05-21 Graydon Hoare <graydon@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics2D.java (setClip): Minor correction to order of operations. * javax/swing/JScrollPane.java: Extend sketchy implementation. * javax/swing/ScrollPaneLayout.java: Likewise. * javax/swing/JViewPort.java: Likewise. * javax/swing/ViewportLayout.java: Likewise. * javax/swing/JComponent.java: Rewrite. * javax/swing/RepaintManager.java: Likewise. * javax/swing/JLayeredPane.java: Change validate() to revalidate(). * javax/swing/JList.java (setSelectedIndices): (getSelectedIndices): (getSelectedValues): New functions. (getPreferredScrollableViewportSize): Return preferred size. (getScrollableUnitIncrement): (getScrollableBlockIncrement): Initial implementations. * javax/swing/JRootPane.java: Clean up slightly. (getUI): (setUI): (updateUI): (getUIClassID): (isValidateRoot): Add overrides from JComponent. * javax/swing/JScrollBar.java: Set default orientation to VERTICAL. * javax/swing/UIManager.java (getDimension): Return the dimension. * javax/swing/plaf/basic/BasicButtonUI.java: Set component opaque. * javax/swing/plaf/basic/BasicLabelUI.java: Likewise. * javax/swing/plaf/basic/BasicMenuItemUI.java: Likewise. * javax/swing/plaf/basic/BasicProgressBarUI.java: Likewise. * javax/swing/plaf/basic/BasicSeparatorUI.java: Likewise. * javax/swing/plaf/basic/BasicSliderUI.java: Likewise. * javax/swing/plaf/basic/BasicTabbedPaneUI.java: Likewise. * javax/swing/plaf/basic/BasicRootPaneUI.java: Likewise, and set background. * javax/swing/plaf/basic/BasicListUI.java: Likewise, and improve a bit. * javax/swing/plaf/basic/BasicScrollBarUI.java: Likewise, and adjust calculations. * javax/swing/plaf/basic/BasicViewportUI.java: Likewise, and improve a bit. * javax/swing/plaf/basic/BasicLookAndFeel.java (Button.margin): Shrink. * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c: Hack to set horizontal always, workaround pango. * jni/gtk-peer/gtkcairopeer.h: Change to match pattern API. * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c: Synchronize more often, check cairo status after ops, handle changes to cairo pattern API, check for disposal. 2004-05-21 Olga Rodimina <rodimina@redhat.com> * javax/swing/plaf/basic/BasicMenuItemUI.java: (BasicMenuItemUI): Create propertyChangeListener. (getPath):Implemented. (installListeners): Add propertyChangeListener to menuItem. (uninstallListeners): Remove propertyChangeListener from menuItem. (update): Implemented. * javax/swing/plaf/basic/BasicMenuUI.MouseInputHandler: (mouseEntered): Take insets of popup menu into account when calculating position of popup menu. 2004-05-18 Olga Rodimina <rodimina@redhat.com> * Makefile.am: Added new file. * Makefile.in: Regenerate. * javax/swing/JMenuBar.java: Started implementation. * javax/swing/JPopupMenu.java: (setVisible): Fixed location of lightweight/mediumweight popup menu. (show): Fixed location of PopupMenu. * javax/swing/plaf/basic/BasicMenuBarUI.java: New file. UI Delegate for JMenuBar. * javax/swing/plaf/basic/BasicMenuUI.MouseInputHandler: (mouseEntered): Corrected position of the submenu. 2004-05-18 Thomas Fitzsimmons <fitzsim@redhat.com> * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c: Remove calls to _gtk_accel_group_attach. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkPopupMenuPeer.c: Likewise. * gnu/java/awt/peer/gtk/GtkButtonPeer.java: Give gtkSetFont package access. Don't override setFont. * gnu/java/awt/peer/gtk/GtkCheckboxPeer.java: Likewise. * gnu/java/awt/peer/gtk/GtkComponentPeer.java: Give gtkWidgetRequestFocus package access. * gnu/java/awt/peer/gtk/GtkLabelPeer.java: Don't override setFont. * gnu/java/awt/peer/gtk/GtkListPeer.java: Override gtkSetFont. Give gtkWidgetRequestFocus package access. * gnu/java/awt/peer/gtk/GtkTextAreaPeer.java: Give gtkWidgetRequestFocus package access. Don't override setFont. * gnu/java/awt/peer/gtk/GtkTextFieldPeer.java: Don't override setFont. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c (gtkSetLabel): Move call to gtk_bin_get_child into GDK critical region. (gtkSetFont): Likewise. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c (gtkSetFont): Implement. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c (gtkSetFont): Whitespace fix. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c (gtkWidgetSetUsize): Remove method. 2004-05-18 David Jee <djee@redhat.com> * java/awt/image/MemoryImageSource.java (newPixels(int,int,int,int,boolean)): Set only the specified rectangle of pixels. (newPixels(byte[],ColorModel,int,int)): Implement. (newPixels(int[],ColorModel,int,int)): Implement. 2004-05-18 Olga Rodimina <rodimina@redhat.com> * Makefile.am: Added new file. * Makefile.in: Regenerate. * javax/swing/JMenu.java: Started implementation. * javax/swing/JPopupMenu.java: (insert): If specified index is -1, then add component at the end. (isPopupTrigger): Reimplemented. (JPopupMenu.LightWeightPopup): setBounds of the lightWeightPopup before adding it to the layeredPane. (javax/swing/plaf/basic/BasicIconFactory.java): (getMenuArrowIcon): Implemented. * javax/swing/plaf/basic/BasicMenuItemUI.java: (getPreferredSize): Add size of the arrow icon if this menu item is instance of JMenu. (paintMenuItem): Paint arrow icon if this menu item is a submenu. * javax/swing/plaf/basic/BasicMenuUI.java: New File. UI Delegate for JMenu. 2004-05-17 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GtkComponentPeer.java (postKeyEvent): Post KEY_TYPED events. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c (generates_key_typed_event): Remove function. 2004-05-17 Olga Rodimina <rodimina@redhat.com> * javax/swing/JRootPane.java (JRootPane.RootLayout): Reimplemented to set bounds of contentPane and menuBar. (setJMenuBar): Add menu bar to the layered pane. (createLayeredPane): Set layout of layeredPane to null. * javax/swing/JLayeredPane.java: (addImpl): Calculate index of the component in the layeredPane according to the specified position within the layer. 2004-05-17 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkImagePainter.java (setPixels): Change color model to the default model after converting pixels. * java/awt/image/MemoryImageSource.java (newPixels): Set only the specified rectangle of pixels. 2004-05-13 Thomas Fitzsimmons <fitzsim@redhat.com> * libgcj.spec.in (lib): Add -l-java-awt -l-java-applet -l-java-beans -l-javax-accessibility -l-javax-swing. * java/awt/AWTEvent.java (toString): Print source's name rather than the source itself. 2004-05-12 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GtkToolkit.java (loadSystemColors): Make native. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c (gdk_color_to_java_color): New function. * jni/gtk-peer/gtkpeer.h: Add SystemColor defines. 2004-05-12 David Jee <djee@redhat.com> * java/awt/image/RGBImageFilter.java: Initialize origmodel as null. (makeColor): Fix pixel component order. (filterRGBPixels): Fix pixel iteration. (setPixels): Add extra checks for index color model. Convert pixels to default color model if necessary. (convertColorModelToDefault): New override method for byte pixels. (convertColorModelToDefault): For int pixels, fix pixel iteration. (makeColorbyDefaultCM): New override method for byte pixels. (makeColorbyDefaultCM): For int pixel, add color model as argument. (makeColor): Fix pixel component order. 2004-05-11 Kim Ho <kho@redhat.com> * javax/swing/Box.java: Comment out more parts of Box.Filler. 2004-05-11 Kim Ho <kho@redhat.com> * javax/swing/Box.java: Remove reference to AccessibleAWTComponent so it compiles again. 2004-05-10 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GtkListPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c: Update implementation of list peer to use GtkTreeView instead of deprecated GtkCList. 2004-05-07 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GtkComponentPeer.java (gtkWidgetDispatchKeyEvent): Remove keyChar parameter. (handleEvent): Remove keyChar argument to gtkWidgetDispatchKeyEvent calls. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c: Fix compiler warnings. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c: Likewise. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c: Likewise. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c: Likewise. 2004-05-06 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GtkComponentPeer.java (gtkWidgetRequestFocus): Mark protected. (GtkComponentPeer): Only set the peer's bounds if its component is valid. * java/awt/Component.java (static): Set the default keyboard focus manager. (requestFocus(), requestFocus(boolean), requestFocusInWindow(), requestFocusInWindow(temporary)): Don't request focus if the component is not showing. Get tree lock before traversing component hierarchy. * java/awt/DefaultKeyboardFocusManager.java (dispatchEvent): Only set the global focus owner if it is not a Window. (processKeyEvent): Consume keystrokes associated with the focus traversal keystroke. (focusPreviousComponent, focusNextComponent, upFocusCycle, downFocusCycle): Call requestFocusInWindow instead of requestFocus. * java/awt/EventDispatchThread.java (run): Move setting of default keyboard focus manager to Component.java. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c (awt_keycode_to_keysym): New function. (gtkWidgetDispatchKeyEvent): Finish implementation. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c (pre_event_handler): Add FIXME comment. * gnu/java/awt/peer/gtk/GtkTextAreaPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c (gtkWidgetRequestFocus): New method. * java/awt/TextArea.java (TextArea): Set focus traversal keys to disable Tab and Shift-Tab keystrokes. (addNotify, appendText, insertText, replaceText): Simplify peer retrieval code. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c (connectSignals): Remove connections to "commit" signals. Remove C++-style comments. * gnu/java/awt/peer/gtk/GtkButtonPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c (handleEvent): Activate GTK button when the space bar key is pressed. (gtkActivate): New method. 2004-05-06 David Jee <djee@redhat.com> * java/awt/image/CropImageFilter.java (setPixels): Implement for byte array pixels. * java/awt/image/ReplicateScaleFilter.java (setPixels): Implement for byte array pixels. (replicatePixels): Overload for byte array pixels. 2004-05-06 Kim Ho <kho@redhat.com> * javax/swing/Box.java: (getAccessibleContext): Return an instance of the correct class. 2004-05-05 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics.java (drawImage): When component is null, use SystemColor.window as the default bgcolor. * gnu/java/awt/peer/gtk/GtkImage.java (setPixels): We can avoid iterating through the pixel rows only when height is 1. * java/awt/Image.java (getScaledInstance): Partially implement. * java/awt/image/CropImageFilter.java (setProperties): Fix "filter" property. (setPixels): Implement. * java/awt/image/ReplicateScaleFilter.java (setDimensions): Use scaled dimensions. (setPixels): Implement. (replicatePixels): New method. 2004-05-05 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkImagePainter.java (convertPixels): If either pixels or model is null, return null. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImagePainter.c (Java_gnu_java_awt_peer_gtk_GtkImagePainter_drawPixels): If jpixels is null, do nothing and return. 2004-05-03 Kim Ho <kho@redhat.com> * gnu/java/awt/peer/gtk/GtkDialogPeer.java: (getGraphics): Like GtkFramePeer, the Graphics object needs to be translate to account for window decorations. (postMouseEvent): New method. Account for translation. (postExposeEvent): ditto. * javax/swing/Box.java: Stubbed. * javax/swing/JDialog.java: Ran through jalopy to fix indentation. (JDialog): Call SwingUtilities' getOwnerFrame for null owners. (setLayout): Check isRootPaneCheckingEnabled * javax/swing/JOptionPane.java: Re-implemented. * javax/swing/SwingUtilities.java: (getOwnerFrame): Static method to grab a default owner frame for Dialogs that don't specify owners. * javax/swing/event/SwingPropertyChangeSupport.java: (firePropertyChange): Fix early exit condition. * javax/swing/plaf/basic/BasicLabelUI.java: (paint): Avoid painting text if it is null or empty. * javax/swing/plaf/basic/BasicOptionPaneUI.java: Implement. 2004-05-03 Olga Rodimina <rodimina@redhat.com> * Makefile.am: Added new file. * Makefile.in: Regenerate. * javax/swing/JPopupMenu.java: Started implementation. * javax/swing/JWindow.java (JWindow): call super() if parent for window is not specified. * javax/swing/plaf/basic/BasicPopupMenuUI.java: New File. UI Delegate for JPopupMenu. 2004-04-30 Olga Rodimina <rodimina@redhat.com> * javax/swing/JApplet.java: Indicated that JApplet implements RootPaneContainer and made method of this interface public. * javax/swing/JFrame.java: Ditto. * javax/swing/JWindow.java: Ditto. 2004-04-29 Thomas Fitzsimmons <fitzsim@redhat.com> * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c (nativeSetBounds): Call gdk_window_move in addition to gtk_window_move. * java/applet/Applet.java (preferredSize): Call parent's preferredSize if the applet stub is null. (minimumSize): Likewise for parent's minimumSize. 2004-04-27 Olga Rodimina <rodimina@redhat.com> * javax/swing/JMenuItem.java (createActionPropertyChangeListener): Implemented. (processMouseEvent): Ditto. (fireMenuDragMouseEntered): Ditto. (fireMenuDragMouseExited): Ditto. (fireMenuDragMouseDragged): Ditto. (fireMenuDragMouseReleased): Ditto. (menuSelectionChanged): Ditto. (getSubElements): Ditto. (getComponent): Ditto. (addMenuDragMouseListener): Ditto. (removeMenuDragMouseListener):Ditto. (addMenuKeyListener): Ditto. (removeMenuKeyListener): Ditto. * javax/swing/plaf/basic/BasicMenuItemUI.java (doClick): Imlemented. * javax/swing/plaf/basic/BasicMenuItemUI.MouseInputHandler: Don't handle mouse events here. Pass them to MenuSelectionManager. 2004-04-26 Olga Rodimina <rodimina@redhat.com> Used correct version of jalopy configuration file to fix style in the files below. 2004-04-26 Olga Rodimina <rodimina@redhat.com> * javax/swing/JCheckBoxMenuItem.java: Fixed style and removed unnecessary comments. * javax/swing/JMenuItem.java: Ditto. * javax/swing/JRadioButtonMenuItem.java: Ditto. * javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java: Ditto. * javax/swing/plaf/basic/BasicMenuItemUI.java: Ditto. * javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java: Ditto. 2004-04-23 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu_java_awt_peer_gtk_GtkWindowPeer.c: Change FIXME comment to C-style. * gnu_java_awt_peer_gtk_GtkWindowPeer.c: Add FIXME comment. * java/awt/ContainerOrderFocusTraversalPolicy.java (getComponentAfter): Start from current component and work up the component hierarchy until an acceptable component is found. Synchronize on tree lock. (getComponentBefore): Likewise. 2004-04-22 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GtkComponentPeer.java: Remove focus-related debugging messages. * java/awt/DefaultKeyboardFocusManager.java: Likewise. * java/awt/EventDispatchThread.java: Likewise. * java/awt/KeyboardFocusManager.java: Likewise. * java/awt/Window.java: Likewise. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c: Likewise. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c: Likewise. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c: Change new C++-style comments to C-style comments. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c: Likewise. * gnu/java/awt/peer/gtk/GtkComponentPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c (handleEvent): Dispatch key press and key release events to backing widget. (requestFocus): Post a FOCUS_GAINED event to the event queue. (gtkWidgetRequestFocus): New method. (gtkWidgetDispatchKeyEvent): Likewise. * java/awt/Component.java (requestFocus, requestFocus(boolean), requestFocusInWindow, requestFocusInWindow(boolean), getFocusCycleRootAncestor, nextFocus, transferFocus, transferFocusBackward, transferFocusUpCycle, hasFocus, isFocusOwner): Implement and document focus-handling methods. (setFocusTraversalKeys): Inherit focus traversal keys when keystrokes argument is null. Fix focus-handling documentation throughout class. * java/awt/Container.java (setFocusTraversalKeys, getFocusTraversalKeys, areFocusTraversalKeysSet, isFocusCycleRoot, setFocusTraversalPolicy, getFocusTraversalPolicy, isFocusTraversalPolicySet, setFocusCycleRoot, isFocusCycleRoot, transferFocusDownCycle): Implement and document focus-handling methods. (transferFocusBackward): Remove method. (readObject, writeObject): Implement and document serialization methods. * java/awt/ContainerOrderFocusTraversalPolicy.java: Implement and document. * java/awt/DefaultFocusTraversalPolicy.java: Implement and document. * java/awt/DefaultKeyboardFocusManager.java: Implement and partially document. * java/awt/EventDispatchThread.java (run): Set default keyboard focus manager. Attempt to dispatch each event to the keyboard focus manager before normal dispatch. * java/awt/KeyboardFocusManager.java: Implement and partially document. * java/awt/Window.java (Window): Set focusCycleRoot to true. (show): Focus initial component when window is shown for the first time. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c (pre_event_handler): Replace complex key press and key release logic with simple callbacks into GtkComponentPeer. * jni/gtk-peer/gtkpeer.h: Fix FOCUS_GAINED/FOCUS_LOST reversal. 2004-04-21 Olga Rodimina <rodimina@redhat.com> * javax/swing/MenuSelectionManager.java (componentForPoint): Added new method. (defaultManager): New Method. Implemented. (getSelectedPath): Ditto. (isComponentPartOfCurrentMenu): Ditto. (processKeyEvent): Added new method. (processMouseEvent): New Method. Implemented. (setSelectedPath): Ditto. (getPath): Ditto. 2004-04-19 Kim Ho <kho@redhat.com> * java/awt/Container.java: (remove): Set the component's parent to null. (getComponentAt): Implement. * javax/swing/JComponent.java: (JComponent): Initialize defaultLocale (getDefaultLocale): Implement. (setDefaultLocale): ditto. * javax/swing/JSlider.java: (JSlider): Fix calculation of value. * javax/swing/JSplitPane.java: Implement. * javax/swing/plaf/basic/BasicLookAndFeel.java: Change SplitPane's default divider size. * javax/swing/plaf/basic/BasicScrollBarUI.java: (paint): Remove unused code. * javax/swing/plaf/basic/BasicSplitPaneDivider.java: Added comments and ran through jalopy. (setBasicSplitPaneUI): Get reference to hidden divider and set up one touch buttons if necessary. (setBorder): Fire propertyChangeEvent only if borders are different. (getPreferredSize): Defer to layout manager. (propertyChange): Implement. (oneTouchExpandableChanged): ditto. (createLeftOneTouchButton): Use BasicArrowButton. (createRightOneTouchButton): ditto. (moveDividerTo): New method. Moves the divider to a set location based on the last divider location. (BasicSplitPaneDivider::MouseHandler): Implement. (BasicSplitPaneDivider::OneTouchButton): Removed. (BasicSplitPaneDivider::DragController): Implement. (BasicSplitPaneDivider::VerticalDragController): ditto. (BasicSplitPaneDivider::DividerLayout): ditto. * javax/swing/plaf/basic/BasicSplitPaneUI.java: Reimplement. * javax/swing/plaf/basic/BasicTabbedPaneUI.java: (calculateLayoutInfo): Don't show component if it's null. (paintTab): Fix title paint logic. From-SVN: r82314
Diffstat (limited to 'libjava/java')
-rw-r--r--libjava/java/applet/Applet.java4
-rw-r--r--libjava/java/awt/AWTEvent.java12
-rw-r--r--libjava/java/awt/Component.java571
-rw-r--r--libjava/java/awt/Container.java333
-rw-r--r--libjava/java/awt/ContainerOrderFocusTraversalPolicy.java275
-rw-r--r--libjava/java/awt/DefaultFocusTraversalPolicy.java66
-rw-r--r--libjava/java/awt/DefaultKeyboardFocusManager.java418
-rw-r--r--libjava/java/awt/EventDispatchThread.java12
-rw-r--r--libjava/java/awt/Image.java16
-rw-r--r--libjava/java/awt/KeyboardFocusManager.java807
-rw-r--r--libjava/java/awt/TextArea.java40
-rw-r--r--libjava/java/awt/Window.java33
-rw-r--r--libjava/java/awt/image/CropImageFilter.java47
-rw-r--r--libjava/java/awt/image/MemoryImageSource.java34
-rw-r--r--libjava/java/awt/image/RGBImageFilter.java82
-rw-r--r--libjava/java/awt/image/ReplicateScaleFilter.java87
16 files changed, 2258 insertions, 579 deletions
diff --git a/libjava/java/applet/Applet.java b/libjava/java/applet/Applet.java
index 27c8aaf..009b18c 100644
--- a/libjava/java/applet/Applet.java
+++ b/libjava/java/applet/Applet.java
@@ -483,7 +483,7 @@ public class Applet extends Panel
*/
public Dimension preferredSize()
{
- return getDimensions ();
+ return stub == null ? super.preferredSize () : getDimensions ();
}
/**
@@ -494,7 +494,7 @@ public class Applet extends Panel
*/
public Dimension minimumSize()
{
- return getDimensions ();
+ return stub == null ? super.minimumSize () : getDimensions ();
}
/**
diff --git a/libjava/java/awt/AWTEvent.java b/libjava/java/awt/AWTEvent.java
index 41cdad5..a084dcf 100644
--- a/libjava/java/awt/AWTEvent.java
+++ b/libjava/java/awt/AWTEvent.java
@@ -231,15 +231,15 @@ public abstract class AWTEvent extends EventObject
}
/**
- * Returns a string representation of this event. This is in the format
- * <code>getClass().getName() + '[' + paramString() + "] on "
- * + source</code>.
+ * Create a string that represents this event in the format
+ * <code>classname[eventstring] on sourcecomponentname</code>.
*
- * @return a string representation of this event
+ * @return a string representing this event
*/
- public String toString()
+ public String toString ()
{
- return getClass().getName() + "[" + paramString() + "] on " + source;
+ return getClass ().getName () + "[" + paramString () + "] on "
+ + ((Component) source).getName ();
}
/**
diff --git a/libjava/java/awt/Component.java b/libjava/java/awt/Component.java
index d52818a..3ca2b4f 100644
--- a/libjava/java/awt/Component.java
+++ b/libjava/java/awt/Component.java
@@ -383,18 +383,18 @@ public abstract class Component
boolean focusable = true;
/**
- * Tracks whether this component uses default focus traversal, or has a
- * different policy.
+ * Tracks whether this component's {@link #isFocusTraversable}
+ * method has been overridden.
*
- * @see #isFocusTraversableOverridden()
* @since 1.4
*/
int isFocusTraversableOverridden;
/**
- * 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.
+ * 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)
@@ -557,6 +557,12 @@ public abstract class Component
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;
@@ -566,6 +572,8 @@ public abstract class Component
{
incrementalDraw = Boolean.getBoolean ("awt.image.incrementalDraw");
redrawRate = Long.getLong ("awt.image.redrawrate");
+ // Set the default KeyboardFocusManager.
+ KeyboardFocusManager.setCurrentKeyboardFocusManager (null);
}
// Public and protected API.
@@ -2963,6 +2971,7 @@ public abstract class Component
{
if (focusListener == null)
return;
+
switch (e.id)
{
case FocusEvent.FOCUS_GAINED:
@@ -3411,13 +3420,18 @@ public abstract class Component
}
/**
- * Sets the focus traversal keys for a given type of focus events. 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.
+ * 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 defauts are:
+ * <p>The defaults are:
* <table>
* <th><td>Identifier</td><td>Meaning</td><td>Default</td></th>
* <tr><td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
@@ -3430,10 +3444,13 @@ public abstract class Component
* <td>Go up a traversal cycle</td><td>None</td></tr>
* </table>
*
- * <p>Specifying null allows inheritance from the parent, or from the current
- * KeyboardFocusManager default set. If not null, the set must contain only
- * AWTKeyStrokes that are not already focus keys and are not KEY_TYPED
- * events.
+ * 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
@@ -3448,7 +3465,24 @@ public abstract class Component
public void setFocusTraversalKeys(int id, Set keystrokes)
{
if (keystrokes == null)
- throw new IllegalArgumentException();
+ {
+ 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;
@@ -3476,50 +3510,60 @@ public abstract class Component
name = "upCycleFocusTraversalKeys";
break;
default:
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException ();
}
- int i = keystrokes.size();
- Iterator iter = keystrokes.iterator();
+
+ 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)
+ Object o = iter.next ();
+ if (!(o instanceof AWTKeyStroke)
+ || sa.contains (o) || sb.contains (o)
|| ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException ();
}
+
if (focusTraversalKeys == null)
focusTraversalKeys = new Set[3];
- keystrokes = Collections.unmodifiableSet(new HashSet(keystrokes));
- firePropertyChange(name, focusTraversalKeys[id], keystrokes);
+
+ 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.
+ * 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
+ * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
+ * or UP_CYCLE_TRAVERSAL_KEYS
* @throws IllegalArgumentException if id is invalid
- * @see #setFocusTraversalKeys(int, Set)
+ * @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)
+ public Set getFocusTraversalKeys (int id)
{
- if (id < KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS
- || id > KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
+ 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);
+ s = parent.getFocusTraversalKeys (id);
+
return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
.getDefaultFocusTraversalKeys(id)) : s;
}
@@ -3528,269 +3572,417 @@ public abstract class Component
* 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
+ * @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 #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)
+ public boolean areFocusTraversalKeysSet (int id)
{
- if (id < KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS
- || id > KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
- throw new IllegalArgumentException();
+ 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;
}
/**
- * Sets whether focus traversal keys are enabled, which consumes traversal
- * keys and performs the focus event automatically.
+ * 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)
+ * @see #getFocusTraversalKeysEnabled ()
+ * @see #setFocusTraversalKeys (int, Set)
+ * @see #getFocusTraversalKeys (int)
* @since 1.4
*/
- public void setFocusTraversalKeysEnabled(boolean focusTraversalKeysEnabled)
+ public void setFocusTraversalKeysEnabled (boolean focusTraversalKeysEnabled)
{
- firePropertyChange("focusTraversalKeysEnabled",
- this.focusTraversalKeysEnabled,
- focusTraversalKeysEnabled);
+ firePropertyChange ("focusTraversalKeysEnabled",
+ this.focusTraversalKeysEnabled,
+ focusTraversalKeysEnabled);
this.focusTraversalKeysEnabled = focusTraversalKeysEnabled;
}
/**
- * Tests whether focus traversal keys are enabled. If they are, then focus
- * traversal keys are consumed and focus events performed automatically,
- * without the component seeing the keystrokes.
+ * 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 is enabled
- * @see #setFocusTraversalKeysEnabled(boolean)
- * @see #setFocusTraversalKeys(int, Set)
- * @see #getFocusTraversalKeys(int)
+ * @return true if focus traversal keys are enabled
+ * @see #setFocusTraversalKeysEnabled (boolean)
+ * @see #setFocusTraversalKeys (int, Set)
+ * @see #getFocusTraversalKeys (int)
* @since 1.4
*/
- public boolean getFocusTraversalKeysEnabled()
+ public boolean getFocusTraversalKeysEnabled ()
{
return focusTraversalKeysEnabled;
}
/**
- * Requests that this component be given focus. 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, visible, and focusable,
- * and the top-level Window must be able to receive focus. Thus, this
- * request may fail, or be delayed until the window receives focus. It is
- * recommended that <code>requestFocusInWindow</code> be used where
- * possible to be more platform-independent.
+ * 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.
*
- * @see #requestFocusInWindow()
+ * 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()
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
*/
- public void requestFocus()
+ public void requestFocus ()
{
- // If there's no peer then this component can't get the focus. We
- // treat it as a silent rejection of the request.
- if (peer != null)
- peer.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)
+ // 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 ();
+ eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED));
+ }
+ }
+ else
+ pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED);
+ }
+ }
}
/**
- * Requests that this component be given focus. 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, visible, and focusable,
- * and the top-level Window must be able to receive focus. Thus, this
- * request may fail, or be delayed until the window receives focus. It is
- * recommended that <code>requestFocusInWindow</code> be used where
- * possible to be more platform-independent.
+ * 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.
*
- * <p>If the return value is false, the request is guaranteed to fail. If
- * it is true, it will likely succeed unless the action is vetoed or
- * something in the native windowing system intervenes. The temporary flag,
- * and thus this method in general, is not designed for public use; rather
- * it is a hook for lightweight components to notify their container in
- * an attempt to reduce the amount of repainting necessary.
+ * 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 #requestFocusInWindow ()
* @see FocusEvent
- * @see #addFocusListener(FocusListener)
- * @see #isFocusable()
- * @see #isDisplayable()
- * @see KeyboardFocusManager#clearGlobalFocusOwner()
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
* @since 1.4
*/
- protected boolean requestFocus(boolean temporary)
+ protected boolean requestFocus (boolean temporary)
{
- // XXX Implement correctly.
- 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)
+ // 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 ();
+ 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;
}
/**
- * Requests that this component be given focus, if it resides in the
- * top-level window which already has focus. 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, visible, and focusable,
- * and the top-level Window must be focused.
+ * 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.
*
- * <p>If the return value is false, the request is guaranteed to fail. If
- * it is true, it will likely succeed unless the action is vetoed or
- * something in the native windowing system intervenes. The temporary flag,
- * and thus this method in general, is not designed for public use; rather
- * it is a hook for lightweight components to notify their container in
- * an attempt to reduce the amount of repainting necessary.
+ * 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 #requestFocus ()
* @see FocusEvent
- * @see #addFocusListener(FocusListener)
- * @see #isFocusable()
- * @see #isDisplayable()
- * @see KeyboardFocusManager#clearGlobalFocusOwner()
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
* @since 1.4
*/
- public boolean requestFocusInWindow()
+ public boolean requestFocusInWindow ()
{
- // XXX Implement correctly.
- requestFocus();
- return true;
+ return requestFocusInWindow (false);
}
/**
- * Requests that this component be given focus, if it resides in the
- * top-level window which already has focus. 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, visible, and focusable,
- * and the top-level Window must be focused.
+ * 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.
*
- * <p>If the return value is false, the request is guaranteed to fail. If
- * it is true, it will likely succeed unless the action is vetoed or
- * something in the native windowing system intervenes. The temporary flag,
- * and thus this method in general, is not designed for public use; rather
- * it is a hook for lightweight components to notify their container in
- * an attempt to reduce the amount of repainting necessary.
+ * 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 #requestFocus ()
* @see FocusEvent
- * @see #addFocusListener(FocusListener)
- * @see #isFocusable()
- * @see #isDisplayable()
- * @see KeyboardFocusManager#clearGlobalFocusOwner()
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
* @since 1.4
*/
- protected boolean requestFocusInWindow(boolean temporary)
+ protected boolean requestFocusInWindow (boolean temporary)
{
- // XXX Implement correctly.
- requestFocus();
- return true;
+ 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)
+ // 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 ();
+ 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.
+ * 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()
+ public void transferFocus ()
{
- Component next;
- if (parent == null)
- next = findNextFocusComponent(null);
- else
- next = parent.findNextFocusComponent(this);
- if (next != null && next != this)
- next.requestFocus();
+ 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.
+ * 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()
+ public Container getFocusCycleRootAncestor ()
{
- // XXX Implement.
- throw new Error("not implemented");
+ 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.
+ * 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)
+ public boolean isFocusCycleRoot (Container c)
{
- return c == getFocusCycleRootAncestor();
+ return c == getFocusCycleRootAncestor ();
}
/**
- * AWT 1.0 focus event processor.
+ * 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
+ * @deprecated use {@link #transferFocus ()} instead
*/
- public void nextFocus()
+ public void nextFocus ()
{
- transferFocus();
+ 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.
+ * Transfers focus to the previous component in the focus traversal
+ * order, as though this were the current focus owner.
*
- * @see #requestFocus()
+ * @see #requestFocus ()
* @since 1.4
*/
- public void transferFocusBackward()
+ public void transferFocusBackward ()
{
- // XXX Implement.
- throw new Error("not implemented");
+ 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.
+ * 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()
+ * @see #requestFocus ()
+ * @see #isFocusCycleRoot ()
* @since 1.4
*/
- public void transferFocusUpCycle()
+ public void transferFocusUpCycle ()
{
- // XXX Implement.
- throw new Error("not implemented");
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ manager.upFocusCycle (this);
}
/**
- * Tests if this component is the focus owner. Use {@link #isFocusOwner()}
- * instead.
+ * 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()
+ public boolean hasFocus ()
{
- return isFocusOwner();
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ Component focusOwner = manager.getFocusOwner ();
+
+ return this == focusOwner;
}
/**
@@ -3801,8 +3993,7 @@ public abstract class Component
*/
public boolean isFocusOwner()
{
- // XXX Implement.
- throw new Error("not implemented");
+ return hasFocus ();
}
/**
@@ -4337,6 +4528,8 @@ p * <li>the set of backward traversal keys
* 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
*/
@@ -4897,23 +5090,23 @@ p * <li>the set of backward traversal keys
* Tests whether this component can accept focus.
*
* @return true if this is focus traversable
- * @see #getAccessibleStateSet()
+ * @see #getAccessibleStateSet ()
* @see AccessibleState#FOCUSABLE
* @see AccessibleState#FOCUSED
*/
- public boolean isFocusTraversable()
+ public boolean isFocusTraversable ()
{
- return Component.this.isFocusTraversable();
+ return Component.this.isFocusTraversable ();
}
/**
* Requests focus for this component.
*
- * @see #isFocusTraversable()
+ * @see #isFocusTraversable ()
*/
- public void requestFocus()
+ public void requestFocus ()
{
- Component.this.requestFocus();
+ Component.this.requestFocus ();
}
/**
diff --git a/libjava/java/awt/Container.java b/libjava/java/awt/Container.java
index d666559..0482e65 100644
--- a/libjava/java/awt/Container.java
+++ b/libjava/java/awt/Container.java
@@ -46,10 +46,16 @@ import java.awt.peer.ContainerPeer;
import java.awt.peer.LightweightPeer;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
+import java.io.ObjectInputStream;
+import java.io.IOException;
+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.Iterator;
+import java.util.HashSet;
import java.util.Set;
import javax.accessibility.Accessible;
import javax.swing.SwingUtilities;
@@ -93,6 +99,21 @@ public class Container extends Component
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.
*/
@@ -397,6 +418,8 @@ public class Container extends Component
if (layoutMgr != null)
layoutMgr.removeLayoutComponent(r);
+ r.parent = null;
+
// Post event to notify of adding the container.
ContainerEvent ce = new ContainerEvent(this,
ContainerEvent.COMPONENT_REMOVED,
@@ -853,6 +876,11 @@ public class Container extends Component
{
return locate (x, y);
}
+
+ public Component getComponentAt(int index)
+ {
+ return component[index];
+ }
/**
* Returns the component located at the specified point. This is done
@@ -1068,9 +1096,89 @@ public class Container extends Component
throw new IllegalArgumentException ();
if (keystrokes == null)
- throw new IllegalArgumentException ();
+ {
+ Container parent = getParent ();
- throw new Error ("not implemented");
+ 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;
}
/**
@@ -1085,7 +1193,7 @@ public class Container extends Component
*
* @since 1.4
*/
- public Set getFocusTraversalKeys(int id)
+ public Set getFocusTraversalKeys (int id)
{
if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
@@ -1093,9 +1201,18 @@ public class Container extends Component
id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
throw new IllegalArgumentException ();
- return null;
+ 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.
@@ -1110,7 +1227,7 @@ public class Container extends Component
*
* @since 1.4
*/
- public boolean areFocusTraversalKeysSet(int id)
+ public boolean areFocusTraversalKeysSet (int id)
{
if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
@@ -1118,43 +1235,148 @@ public class Container extends Component
id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
throw new IllegalArgumentException ();
- return false;
+ return focusTraversalKeys != null && focusTraversalKeys[id] != null;
}
-
- public boolean isFocusCycleRoot(Container c)
+
+ /**
+ * 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;
}
-
- public void transferFocusBackward()
- {
- }
-
- public void setFocusTraversalPolicy(FocusTraversalPolicy policy)
+
+ /**
+ * 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;
}
-
- public FocusTraversalPolicy getFocusTraversalPolicy()
+
+ /**
+ * 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 ()
{
- return null;
+ 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;
}
-
- public boolean isFocusTraversalPolicySet()
+
+ /**
+ * 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 false;
+ return focusTraversalPolicy == null;
}
-
- public void setFocusCycleRoot(boolean focusCycleRoot)
+
+ /**
+ * 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.
+ *
+ * @return true if this is a focus cycle root, false otherwise
+ *
+ * @since 1.4
+ */
+ public void setFocusCycleRoot (boolean focusCycleRoot)
{
+ this.focusCycleRoot = focusCycleRoot;
}
-
- public boolean isFocusCycleRoot()
+
+ /**
+ * 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 false;
+ return focusCycleRoot;
}
-
- public void transferFocusDownCycle()
+
+ /**
+ * 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);
}
/**
@@ -1371,6 +1593,61 @@ public class Container extends Component
}
}
+ /**
+ * 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
diff --git a/libjava/java/awt/ContainerOrderFocusTraversalPolicy.java b/libjava/java/awt/ContainerOrderFocusTraversalPolicy.java
index ce4bdf8..fa7ab4a 100644
--- a/libjava/java/awt/ContainerOrderFocusTraversalPolicy.java
+++ b/libjava/java/awt/ContainerOrderFocusTraversalPolicy.java
@@ -41,7 +41,23 @@ 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
@@ -52,12 +68,15 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
*/
static final long serialVersionUID = 486933713763926351L;
+ /**
+ * True if implicit down cycling is enabled.
+ */
private boolean implicitDownCycleTraversal = true;
/**
* Creates the <code>ContainerOrderFocusTraversalPolicy</code> object.
*/
- public ContainerOrderFocusTraversalPolicy()
+ public ContainerOrderFocusTraversalPolicy ()
{
// Nothing to do here
}
@@ -66,37 +85,196 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
* 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)
+ public Component getComponentAfter (Container root, Component current)
{
- if (root == null
- || current == null)
- throw new IllegalArgumentException ();
-
- return null;
+ 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 current.
- * root must be a focus cycle root of current.
+ * 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)
+ public Component getComponentBefore (Container root, Component current)
{
- if (root == null
- || current == null)
- throw new IllegalArgumentException ();
+ if (root == null)
+ throw new IllegalArgumentException ("focus cycle root is null");
+ if (current == null)
+ throw new IllegalArgumentException ("current component is null");
- return 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)
@@ -117,18 +295,16 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
{
Component component = componentArray [i];
+ if (accept (component))
+ return component;
+
if (component instanceof Container)
{
- Component result = getLastComponent ((Container) component);
+ Component result = getFirstComponent ((Container) component);
if (result != null)
return result;
}
- else
- {
- if (accept (component))
- return component;
- }
}
return null;
@@ -137,9 +313,14 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
/**
* 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)
+ public Component getLastComponent (Container root)
{
if (root == null)
throw new IllegalArgumentException ();
@@ -153,10 +334,13 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
Component[] componentArray = root.getComponents ();
- for (int i = componentArray.length - 1; i >= 0; i++)
+ 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);
@@ -164,11 +348,6 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
if (result != null)
return result;
}
- else
- {
- if (accept (component))
- return component;
- }
}
return null;
@@ -177,28 +356,58 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
/**
* 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)
+ public Component getDefaultComponent (Container root)
{
return getFirstComponent (root);
}
- public void setImplicitDownCycleTraversal(boolean value)
+ /**
+ * 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;
}
- public boolean getImplicitDownCycleTraversal()
+ /**
+ * 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;
}
- protected boolean accept(Component current)
+ /**
+ * 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.isDisplayable ()
&& current.enabled
&& current.focusable);
}
-} // class ContainerOrderFocusTraversalPolicy
+}
diff --git a/libjava/java/awt/DefaultFocusTraversalPolicy.java b/libjava/java/awt/DefaultFocusTraversalPolicy.java
index ac3a178..73b1e95 100644
--- a/libjava/java/awt/DefaultFocusTraversalPolicy.java
+++ b/libjava/java/awt/DefaultFocusTraversalPolicy.java
@@ -39,17 +39,73 @@ exception statement from your version. */
package java.awt;
/**
- * STUB CLASS ONLY
+ * 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
{
- public DefaultFocusTraversalPolicy()
+ /**
+ * Construct a default focus traversal policy.
+ */
+ public DefaultFocusTraversalPolicy ()
{
}
- protected boolean accept(Component comp)
+ /**
+ * 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)
{
- throw new Error("not implemented");
+ if (comp.visible
+ && comp.isDisplayable ()
+ && comp.enabled)
+ {
+ if (comp.isFocusTraversableOverridden != 0
+ && comp.isFocusTraversable ())
+ return true;
+ else
+ {
+ 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;
}
-} // class DefaultFocusTraversalPolicy
+}
diff --git a/libjava/java/awt/DefaultKeyboardFocusManager.java b/libjava/java/awt/DefaultKeyboardFocusManager.java
index e2a2f68..79a9869 100644
--- a/libjava/java/awt/DefaultKeyboardFocusManager.java
+++ b/libjava/java/awt/DefaultKeyboardFocusManager.java
@@ -38,59 +38,423 @@ exception statement from your version. */
package java.awt;
-import java.awt.event.KeyEvent;
+import java.util.*;
+import java.awt.event.*;
-/**
- * STUB CLASS ONLY
- */
+// FIXME: finish documentation
public class DefaultKeyboardFocusManager extends KeyboardFocusManager
{
- public DefaultKeyboardFocusManager()
+ /**
+ * 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 ();
+ }
}
- public boolean dispatchEvent(AWTEvent e)
+ /** The {@link java.util.SortedSet} of current {@link
+ #EventDelayRequest}s. */
+ private SortedSet delayRequests = new TreeSet ();
+
+ public DefaultKeyboardFocusManager ()
{
- throw new Error("not implemented");
}
- public boolean dispatchKeyEvent(KeyEvent e)
+
+ public boolean dispatchEvent (AWTEvent e)
{
- throw new Error("not implemented");
+ 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;
+
+ target.dispatchEvent (e);
+ return true;
+ }
+ else if (e instanceof FocusEvent)
+ {
+ Component target = (Component) e.getSource ();
+
+ if (e.id == FocusEvent.FOCUS_GAINED
+ && !(target instanceof Window))
+ {
+ if (((FocusEvent) e).isTemporary ())
+ setGlobalFocusOwner (target);
+ else
+ setGlobalPermanentFocusOwner (target);
+ }
+
+ if (!(target instanceof Window))
+ target.dispatchEvent (e);
+
+ return true;
+ }
+ else if (e instanceof KeyEvent)
+ {
+ // Loop through all registered KeyEventDispatchers, giving
+ // each a chance to handle this event.
+ Iterator i = keyEventDispatchers.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 ();
+ 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;
}
- public boolean postProcessKeyEvent(KeyEvent e)
+
+ private boolean enqueueKeyEvent (KeyEvent e)
{
- throw new Error("not implemented");
+ 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 void processKeyEvent(Component comp, KeyEvent e)
+
+ public boolean dispatchKeyEvent (KeyEvent e)
{
- throw new Error("not implemented");
+ Component focusOwner = getGlobalPermanentFocusOwner ();
+
+ focusOwner.dispatchEvent (e);
+
+ // Loop through all registered KeyEventPostProcessors, giving
+ // each a chance to process this event.
+ Iterator i = keyEventPostProcessors.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;
}
- protected void enqueueKeyEvents(long after, Component comp)
+
+ public boolean postProcessKeyEvent (KeyEvent e)
+ {
+ // Check if this event represents a menu shortcut.
+
+ // MenuShortcuts are activated by Ctrl- KeyEvents.
+ int modifiers = e.getModifiers ();
+ if ((modifiers & KeyEvent.CTRL_MASK) != 0
+ || (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 (shortcut != null)
+ {
+ // Dispatch a new ActionEvent if this is a
+ // Shift- KeyEvent and the shortcut requires
+ // the Shift modifier, or if the shortcut
+ // doesn't require the Shift modifier.
+ if ((shortcut.usesShiftModifier ()
+ && ((modifiers & KeyEvent.SHIFT_MASK) != 0
+ || (modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0)
+ || !shortcut.usesShiftModifier ())
+ && shortcut.getKey () == e.getKeyCode ())
+ {
+ 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).
+ AWTKeyStroke oppositeKeystroke = AWTKeyStroke.getAWTKeyStroke (e.getKeyCode (),
+ e.getModifiers (),
+ !(e.id == KeyEvent.KEY_RELEASED));
+
+ 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))
+ {
+ focusNextComponent (comp);
+ e.consume ();
+ }
+ else if (backwardKeystrokes.contains (eventKeystroke))
+ {
+ focusPreviousComponent (comp);
+ e.consume ();
+ }
+ else if (upKeystrokes.contains (eventKeystroke))
+ {
+ upFocusCycle (comp);
+ e.consume ();
+ }
+ else if (comp instanceof Container
+ && downKeystrokes.contains (eventKeystroke))
+ {
+ downFocusCycle ((Container) comp);
+ e.consume ();
+ }
+ else if (forwardKeystrokes.contains (oppositeKeystroke)
+ || backwardKeystrokes.contains (oppositeKeystroke)
+ || upKeystrokes.contains (oppositeKeystroke)
+ || (comp instanceof Container &&
+ downKeystrokes.contains (oppositeKeystroke)))
+ e.consume ();
+ }
+
+ protected void enqueueKeyEvents (long after, Component untilFocused)
{
- throw new Error("not implemented");
+ delayRequests.add (new EventDelayRequest (after, untilFocused));
}
- protected void dequeueKeyEvents(long after, Component comp)
+
+ protected void dequeueKeyEvents (long after, Component untilFocused)
{
- throw new Error("not implemented");
+ // 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)
+
+ protected void discardKeyEvents (Component comp)
{
- throw new Error("not implemented");
+ // 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)
+
+ public void focusPreviousComponent (Component comp)
{
- throw new Error("not implemented");
+ Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
+ Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();
+ FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
+
+ Component previous = policy.getComponentBefore (focusCycleRoot, focusComp);
+ previous.requestFocusInWindow ();
}
- public void focusNextComponent(Component comp)
+
+ public void focusNextComponent (Component comp)
{
- throw new Error("not implemented");
+ Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
+ Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();
+ FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
+
+ Component next = policy.getComponentAfter (focusCycleRoot, focusComp);
+ next.requestFocusInWindow ();
}
- public void upFocusCycle(Component comp)
+
+ public void upFocusCycle (Component comp)
{
- throw new Error("not implemented");
+ Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
+ Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();
+
+ if (focusCycleRoot instanceof Window)
+ {
+ FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
+ Component defaultComponent = policy.getDefaultComponent (focusCycleRoot);
+ defaultComponent.requestFocusInWindow ();
+ }
+ else
+ {
+ Container parentFocusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor ();
+
+ focusCycleRoot.requestFocusInWindow ();
+ setGlobalCurrentFocusCycleRoot (parentFocusCycleRoot);
+ }
}
- public void downFocusCycle(Container cont)
+
+ public void downFocusCycle (Container cont)
{
- throw new Error("not implemented");
+ if (cont == null)
+ return;
+
+ if (cont.isFocusCycleRoot (cont))
+ {
+ FocusTraversalPolicy policy = cont.getFocusTraversalPolicy ();
+ Component defaultComponent = policy.getDefaultComponent (cont);
+ defaultComponent.requestFocusInWindow ();
+ setGlobalCurrentFocusCycleRoot (cont);
+ }
}
} // class DefaultKeyboardFocusManager
diff --git a/libjava/java/awt/EventDispatchThread.java b/libjava/java/awt/EventDispatchThread.java
index 91145e1..89b6095 100644
--- a/libjava/java/awt/EventDispatchThread.java
+++ b/libjava/java/awt/EventDispatchThread.java
@@ -67,7 +67,17 @@ class EventDispatchThread extends Thread
// We are interrupted when we should finish executing
return;
}
- queue.dispatchEvent(evt);
+
+ 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 (InterruptedException ie)
{
diff --git a/libjava/java/awt/Image.java b/libjava/java/awt/Image.java
index d4b75b8..451b092 100644
--- a/libjava/java/awt/Image.java
+++ b/libjava/java/awt/Image.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package java.awt;
import java.awt.image.AreaAveragingScaleFilter;
+import java.awt.image.FilteredImageSource;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.ReplicateScaleFilter;
@@ -179,7 +180,20 @@ public abstract class Image
*/
public Image getScaledInstance(int width, int height, int flags)
{
- throw new Error("not implemented");
+ 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");
+ }
}
/**
diff --git a/libjava/java/awt/KeyboardFocusManager.java b/libjava/java/awt/KeyboardFocusManager.java
index 867316b..8ebd9e171 100644
--- a/libjava/java/awt/KeyboardFocusManager.java
+++ b/libjava/java/awt/KeyboardFocusManager.java
@@ -39,34 +39,66 @@ exception statement from your version. */
package java.awt;
import java.awt.event.KeyEvent;
+import java.awt.event.FocusEvent;
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;
+// FIXME: finish documentation
+
/**
*
+ * FIXME: discuss applet contexts and thread groups and codebases
+ * being insulated.
+ *
+ * FIXME: discuss where default focus traversal key sets apply
+ * (inherited by child Components etc.)
+ *
* @author Eric Blake <ebb9@email.byu.edu>
+ * @author Thomas Fitzsimmons <fitzsim@redhat.com>
* @since 1.4
* @status partially updated to 1.4, needs documentation.
*/
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();
@@ -83,232 +115,402 @@ public abstract class KeyboardFocusManager
DEFAULT_BACKWARD_KEYS = Collections.unmodifiableSet(s);
}
- private static KeyboardFocusManager current
- = new DefaultKeyboardFocusManager();
-
- // XXX Not implemented correctly. I think a good implementation here may
- // be to have permanentFocusOwner be null, and fall back to focusOwner,
- // unless a temporary focus change is in effect.
- private static Component focusOwner;
- private static Component permanentFocusOwner;
-
- private static Window focusedWindow;
- private static Window activeWindow;
- private static Container focusCycleRoot;
-
+ /** 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;
- private Set[] defaultFocusKeys = new Set[] {
+
+ /** 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
};
- private final PropertyChangeSupport propertyChangeSupport
- = new PropertyChangeSupport(this);
- private final VetoableChangeSupport vetoableChangeSupport
- = new VetoableChangeSupport(this);
+ private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport (this);
+ 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();
-
- public KeyboardFocusManager()
+ /**
+ * Construct a KeyboardFocusManager.
+ */
+ public KeyboardFocusManager ()
{
}
- public static KeyboardFocusManager getCurrentKeyboardFocusManager()
+ /**
+ * 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 ()
{
- // XXX Need a way to divide this into contexts.
- return current;
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+ return (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup);
}
- public static void setCurrentKeyboardFocusManager(KeyboardFocusManager m)
+ /**
+ * 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();
+ SecurityManager sm = System.getSecurityManager ();
if (sm != null)
- sm.checkPermission(new AWTPermission("replaceKeyboardFocusManager"));
- // XXX Need a way to divide this into contexts.
- current = m == null ? new DefaultKeyboardFocusManager() : m;
- }
-
- public Component getFocusOwner()
+ sm.checkPermission (new AWTPermission ("replaceKeyboardFocusManager"));
+
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+ KeyboardFocusManager manager;
+
+ if (m == null)
+ manager = new DefaultKeyboardFocusManager ();
+ else
+ manager = m;
+
+ currentKeyboardFocusManagers.put (currentGroup, manager);
+ }
+
+ /**
+ * 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 ()
+ {
+ return (Component) getObject (currentFocusOwners);
+ }
+
+ /**
+ * 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)
{
- // XXX Need an easy way to test if this thread is in the context of the
- // global focus owner, to avoid creating the exception in the first place.
- try
- {
- return getGlobalFocusOwner();
- }
- catch (SecurityException e)
- {
- return null;
- }
- }
-
- protected Component getGlobalFocusOwner()
- {
- // XXX Need a way to test if this thread is in the context of the focus
- // owner, and throw a SecurityException if that is the case.
- // XXX Implement.
- return focusOwner;
- }
-
- protected void setGlobalFocusOwner(Component owner)
- {
- // XXX Should this send focus events to the components involved?
if (owner == null || owner.focusable)
- {
- firePropertyChange("focusOwner", focusOwner, owner);
- try
- {
- fireVetoableChange("focusOwner", focusOwner, owner);
- focusOwner = owner;
- }
- catch (PropertyVetoException e)
- {
- }
- }
- }
-
- public void clearGlobalFocusOwner()
- {
- // XXX Is this enough?
- setGlobalFocusOwner(null);
+ setGlobalObject (currentFocusOwners, owner, "focusOwner");
}
- public Component getPermanentFocusOwner()
+ /**
+ * 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 ()
{
- // XXX Need an easy way to test if this thread is in the context of the
- // global focus owner, to avoid creating the exception in the first place.
- try
+ synchronized (currentFocusOwners)
{
- return getGlobalPermanentFocusOwner();
- }
- catch (SecurityException e)
- {
- return null;
- }
- }
+ Component focusOwner = getGlobalFocusOwner ();
+ Component permanentFocusOwner = getGlobalPermanentFocusOwner ();
- protected Component getGlobalPermanentFocusOwner()
- {
- // XXX Need a way to test if this thread is in the context of the focus
- // owner, and throw a SecurityException if that is the case.
- // XXX Implement.
- return permanentFocusOwner == null ? focusOwner : permanentFocusOwner;
- }
+ setGlobalFocusOwner (null);
+ setGlobalPermanentFocusOwner (null);
- protected void setGlobalPermanentFocusOwner(Component focusOwner)
- {
- // XXX Should this send focus events to the components involved?
- if (focusOwner == null || focusOwner.focusable)
- {
- firePropertyChange("permanentFocusOwner", permanentFocusOwner,
- focusOwner);
- try
+ // Inform the old focus owner that it has lost permanent
+ // focus.
+ if (focusOwner != null)
{
- fireVetoableChange("permanentFocusOwner", permanentFocusOwner,
- focusOwner);
- permanentFocusOwner = focusOwner;
+ // 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));
}
- catch (PropertyVetoException e)
+
+ if (focusOwner != permanentFocusOwner)
{
+ EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
+ q.postEvent (new FocusEvent (permanentFocusOwner, FocusEvent.FOCUS_LOST, false));
}
}
}
- public Window getFocusedWindow()
+ /**
+ * 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)
{
- // XXX Need an easy way to test if this thread is in the context of the
- // global focus owner, to avoid creating the exception in the first place.
- try
- {
- return getGlobalFocusedWindow();
- }
- catch (SecurityException e)
- {
- return null;
- }
- }
-
- protected Window getGlobalFocusedWindow()
- {
- // XXX Need a way to test if this thread is in the context of the focus
- // owner, and throw a SecurityException if that is the case.
- // XXX Implement.
- return focusedWindow;
- }
-
- protected void setGlobalFocusedWindow(Window window)
+ 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)
{
- // XXX Should this send focus events to the windows involved?
if (window == null || window.focusable)
- {
- firePropertyChange("focusedWindow", focusedWindow, window);
- try
- {
- fireVetoableChange("focusedWindow", focusedWindow, window);
- focusedWindow = window;
- }
- catch (PropertyVetoException e)
- {
- }
- }
+ 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()
{
- // XXX Need an easy way to test if this thread is in the context of the
- // global focus owner, to avoid creating the exception in the first place.
- try
- {
- return getGlobalActiveWindow();
- }
- catch (SecurityException e)
- {
- return null;
- }
+ 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()
{
- // XXX Need a way to test if this thread is in the context of the focus
- // owner, and throw a SecurityException if that is the case.
- // XXX Implement.
- return activeWindow;
+ 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)
{
- // XXX Should this send focus events to the windows involved?
- firePropertyChange("activeWindow", activeWindow, window);
- try
- {
- fireVetoableChange("activeWindow", activeWindow, window);
- activeWindow = window;
- }
- catch (PropertyVetoException e)
- {
- }
+ setGlobalObject (currentActiveWindows, window, "activeWindow");
}
- public FocusTraversalPolicy getDefaultFocusTraversalPolicy()
+ /**
+ * 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();
+ defaultPolicy = new DefaultFocusTraversalPolicy ();
return defaultPolicy;
}
- public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy policy)
+ /**
+ * 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);
+ throw new IllegalArgumentException ();
+ firePropertyChange ("defaultFocusTraversalPolicy", defaultPolicy, policy);
defaultPolicy = policy;
}
- public void setDefaultFocusTraversalKeys(int id, Set keystrokes)
- {
+ /**
+ * 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();
+ throw new IllegalArgumentException ();
+
Set sa;
Set sb;
Set sc;
@@ -340,56 +542,82 @@ public abstract class KeyboardFocusManager
type = "downCycleDefaultFocusTraversalKeys";
break;
default:
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException ();
}
- int i = keystrokes.size();
- Iterator iter = keystrokes.iterator();
+ 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)
+ 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();
+ throw new IllegalArgumentException ();
}
- keystrokes = Collections.unmodifiableSet(new HashSet(keystrokes));
- firePropertyChange(type, defaultFocusKeys[id], keystrokes);
+ keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
+ firePropertyChange (type, defaultFocusKeys[id], keystrokes);
defaultFocusKeys[id] = keystrokes;
}
- public Set getDefaultFocusTraversalKeys(int id)
+ /**
+ * 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();
+ throw new IllegalArgumentException ();
return defaultFocusKeys[id];
}
- public Container getCurrentFocusCycleRoot()
+ /**
+ * 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 ()
{
- // XXX Need an easy way to test if this thread is in the context of the
- // global focus owner, to avoid creating the exception in the first place.
- try
- {
- return getGlobalCurrentFocusCycleRoot();
- }
- catch (SecurityException e)
- {
- return null;
- }
+ return (Container) getObject (currentFocusCycleRoots);
}
- protected Container getGlobalCurrentFocusCycleRoot()
+ /**
+ * 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 ()
{
- // XXX Need a way to test if this thread is in the context of the focus
- // owner, and throw a SecurityException if that is the case.
- // XXX Implement.
- return focusCycleRoot;
+ return (Container) getGlobalObject (currentFocusCycleRoots);
}
- public void setGlobalCurrentFocusCycleRoot(Container cycleRoot)
+ /**
+ * 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)
{
- firePropertyChange("currentFocusCycleRoot", focusCycleRoot, cycleRoot);
- focusCycleRoot = cycleRoot;
+ setGlobalObject (currentFocusCycleRoots, cycleRoot, "currentFocusCycleRoot");
}
public void addPropertyChangeListener(PropertyChangeListener l)
@@ -484,73 +712,196 @@ public abstract class KeyboardFocusManager
keyEventDispatchers.remove(dispatcher);
}
- protected List getKeyEventDispatchers()
+ protected List getKeyEventDispatchers ()
{
- return (List) keyEventDispatchers.clone();
+ return (List) keyEventDispatchers.clone ();
}
- public void addKeyEventPostProcessor(KeyEventPostProcessor postProcessor)
+ public void addKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
{
if (postProcessor != null)
- keyEventPostProcessors.add(postProcessor);
+ keyEventPostProcessors.add (postProcessor);
}
- public void removeKeyEventPostProcessor(KeyEventPostProcessor postProcessor)
+ public void removeKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
{
- keyEventPostProcessors.remove(postProcessor);
+ keyEventPostProcessors.remove (postProcessor);
}
- protected List getKeyEventPostProcessors()
+ protected List getKeyEventPostProcessors ()
{
- return (List) keyEventPostProcessors.clone();
+ return (List) keyEventPostProcessors.clone ();
}
- public abstract boolean dispatchEvent(AWTEvent e);
+ public abstract boolean dispatchEvent (AWTEvent e);
- public final void redispatchEvent(Component target, AWTEvent e)
+ public final void redispatchEvent (Component target, AWTEvent e)
{
- throw new Error("not implemented");
+ e.setSource (target);
+ dispatchEvent (e);
}
- public abstract boolean dispatchKeyEvent(KeyEvent e);
+ public abstract boolean dispatchKeyEvent (KeyEvent e);
- public abstract boolean postProcessKeyEvent(KeyEvent e);
+ public abstract boolean postProcessKeyEvent (KeyEvent e);
- public abstract void processKeyEvent(Component focused, KeyEvent e);
+ public abstract void processKeyEvent (Component focused, KeyEvent e);
- protected abstract void enqueueKeyEvents(long after, Component untilFocused);
+ protected abstract void enqueueKeyEvents (long after, Component untilFocused);
- protected abstract void dequeueKeyEvents(long after, Component untilFocused);
+ protected abstract void dequeueKeyEvents (long after, Component untilFocused);
- protected abstract void discardKeyEvents(Component comp);
+ protected abstract void discardKeyEvents (Component comp);
- public abstract void focusNextComponent(Component comp);
+ public abstract void focusNextComponent (Component comp);
- public abstract void focusPreviousComponent(Component comp);
+ public abstract void focusPreviousComponent (Component comp);
- public abstract void upFocusCycle(Component comp);
+ public abstract void upFocusCycle (Component comp);
- public abstract void downFocusCycle(Container cont);
+ public abstract void downFocusCycle (Container cont);
- public final void focusNextComponent()
+ public final void focusNextComponent ()
{
- focusNextComponent(focusOwner);
+ focusNextComponent (null);
}
- public final void focusPreviousComponent()
+ public final void focusPreviousComponent ()
{
- focusPreviousComponent(focusOwner);
+ focusPreviousComponent (null);
}
- public final void upFocusCycle()
+ public final void upFocusCycle ()
{
- upFocusCycle(focusOwner);
+ upFocusCycle (null);
}
- public final void downFocusCycle()
+ public final void downFocusCycle ()
{
+ Component focusOwner = getGlobalFocusOwner ();
if (focusOwner instanceof Container
- && ((Container) focusOwner).isFocusCycleRoot())
- downFocusCycle((Container) focusOwner);
+ && ((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)
+ {
+ }
+ }
}
-} // class KeyboardFocusManager
+}
diff --git a/libjava/java/awt/TextArea.java b/libjava/java/awt/TextArea.java
index 6f60ee6..f27c296 100644
--- a/libjava/java/awt/TextArea.java
+++ b/libjava/java/awt/TextArea.java
@@ -39,6 +39,9 @@ package java.awt;
import java.awt.peer.ComponentPeer;
import java.awt.peer.TextAreaPeer;
+import java.awt.event.KeyEvent;
+import java.util.HashSet;
+import java.util.Set;
/**
@@ -193,11 +196,19 @@ public class TextArea extends TextComponent implements java.io.Serializable
this.rows = rows;
this.columns = columns;
this.scrollbarVisibility = scrollbarVisibility;
- }
- /*
- * Instance Variables
- */
+ // 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
@@ -431,10 +442,8 @@ public class TextArea extends TextComponent implements java.io.Serializable
*/
public void addNotify ()
{
- if (getPeer () != null)
- return;
-
- setPeer ((ComponentPeer) getToolkit().createTextArea (this));
+ if (getPeer () == null)
+ setPeer ((ComponentPeer) getToolkit().createTextArea (this));
}
/**
@@ -458,10 +467,9 @@ public class TextArea extends TextComponent implements java.io.Serializable
public void appendText (String str)
{
TextAreaPeer peer = (TextAreaPeer) getPeer ();
- if (peer == null)
- return;
- peer.insert (str, peer.getText().length ());
+ if (peer != null)
+ peer.insert (str, peer.getText().length ());
}
/**
@@ -489,10 +497,9 @@ public class TextArea extends TextComponent implements java.io.Serializable
public void insertText (String str, int pos)
{
TextAreaPeer peer = (TextAreaPeer) getPeer ();
- if (peer == null)
- return;
- peer.insert (str, pos);
+ if (peer != null)
+ peer.insert (str, pos);
}
/**
@@ -530,10 +537,9 @@ public class TextArea extends TextComponent implements java.io.Serializable
public void replaceText (String str, int start, int end)
{
TextAreaPeer peer = (TextAreaPeer) getPeer ();
- if (peer == null)
- return;
- peer.replaceRange (str, start, end);
+ if (peer != null)
+ peer.replaceRange (str, start, end);
}
/**
diff --git a/libjava/java/awt/Window.java b/libjava/java/awt/Window.java
index 81e37fc..51b00dc 100644
--- a/libjava/java/awt/Window.java
+++ b/libjava/java/awt/Window.java
@@ -83,6 +83,8 @@ public class Window extends Container implements Accessible
private transient GraphicsConfiguration graphicsConfiguration;
private transient AccessibleContext accessibleContext;
+ private transient boolean shown;
+
/**
* This (package access) constructor is used by subclasses that want
* to build windows that do not have parents. Eg. toplevel
@@ -92,6 +94,9 @@ public class Window extends Container implements Accessible
Window()
{
visible = false;
+ // Windows are the only Containers that default to being focus
+ // cycle roots.
+ focusCycleRoot = true;
setLayout(new BorderLayout());
}
@@ -242,6 +247,23 @@ public class Window extends Container implements Accessible
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 (false);
+
+ shown = true;
+ }
}
public void hide()
@@ -627,9 +649,16 @@ public class Window extends Container implements Accessible
* @return The component that has focus, or <code>null</code> if no
* component has focus.
*/
- public Component getFocusOwner()
+ public Component getFocusOwner ()
{
- // FIXME
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ Window activeWindow = manager.getActiveWindow ();
+
+ // The currently-focused Component belongs to the active Window.
+ if (activeWindow == this)
+ return manager.getFocusOwner ();
+
return null;
}
diff --git a/libjava/java/awt/image/CropImageFilter.java b/libjava/java/awt/image/CropImageFilter.java
index 8ffc148..c9a170b 100644
--- a/libjava/java/awt/image/CropImageFilter.java
+++ b/libjava/java/awt/image/CropImageFilter.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package java.awt.image;
import java.util.Hashtable;
+import java.awt.Rectangle;
/**
* <br>
@@ -92,7 +93,7 @@ public class CropImageFilter extends ImageFilter
*/
public void setProperties(Hashtable props)
{
-// props.put("filters", "ReplicateScaleFilter");
+ props.put("filters", "CropImageFilter");
consumer.setProperties(props);
}
@@ -113,7 +114,27 @@ public class CropImageFilter extends ImageFilter
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);
+ 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);
+ }
}
/**
@@ -133,7 +154,27 @@ public class CropImageFilter extends ImageFilter
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);
+ 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/java/awt/image/MemoryImageSource.java b/libjava/java/awt/image/MemoryImageSource.java
index 5006afe..d861199 100644
--- a/libjava/java/awt/image/MemoryImageSource.java
+++ b/libjava/java/awt/image/MemoryImageSource.java
@@ -257,9 +257,15 @@ public class MemoryImageSource implements ImageProducer
ic.setProperties( props );
}
if( pixeli != null ) {
- ic.setPixels( 0, 0, width, height, cm, pixeli, offset, scansize );
+ int[] pixelbuf = new int[w * h];
+ for (int row = y; row < h; row++)
+ System.arraycopy(pixeli, row * scansize + x + offset, pixelbuf, row * w, w);
+ ic.setPixels( x, y, w, h, cm, pixelbuf, 0, w );
} else {
- ic.setPixels( 0, 0, width, height, cm, pixelb, offset, scansize );
+ byte[] pixelbuf = new byte[w * h];
+ for (int row = y; row < h; row++)
+ System.arraycopy(pixelb, row * scansize + x + offset, pixelbuf, row * w, w);
+ ic.setPixels( x, y, w, h, cm, pixelbuf, 0, w );
}
ic.imageComplete( ImageConsumer.SINGLEFRAME );
}
@@ -296,9 +302,15 @@ public class MemoryImageSource implements ImageProducer
ic.setProperties( props );
}
if( pixeli != null ) {
- ic.setPixels( 0, 0, width, height, cm, pixeli, offset, scansize );
+ int[] pixelbuf = new int[w * h];
+ for (int row = y; row < h; row++)
+ System.arraycopy(pixeli, row * scansize + x + offset, pixelbuf, row * w, w);
+ ic.setPixels( x, y, w, h, cm, pixelbuf, 0, w );
} else {
- ic.setPixels( 0, 0, width, height, cm, pixelb, offset, scansize );
+ byte[] pixelbuf = new byte[w * h];
+ for (int row = y; row < h; row++)
+ System.arraycopy(pixelb, row * scansize + x + offset, pixelbuf, row * w, w);
+ ic.setPixels( x, y, w, h, cm, pixelbuf, 0, w );
}
if( framenotify == true )
ic.imageComplete( ImageConsumer.SINGLEFRAME );
@@ -313,9 +325,14 @@ public class MemoryImageSource implements ImageProducer
int scansize)
{
+ pixeli = null;
+ pixelb = newpix;
+ cm = newmodel;
+ this.offset = offset;
+ this.scansize = scansize;
if( animated == true )
{
- //FIXME
+ newPixels();
}
}
@@ -325,9 +342,14 @@ public class MemoryImageSource implements ImageProducer
int scansize)
{
+ pixelb = null;
+ pixeli = newpix;
+ cm = newmodel;
+ this.offset = offset;
+ this.scansize = scansize;
if( animated == true )
{
- //FIXME
+ newPixels();
}
}
diff --git a/libjava/java/awt/image/RGBImageFilter.java b/libjava/java/awt/image/RGBImageFilter.java
index b15fe25..5718024 100644
--- a/libjava/java/awt/image/RGBImageFilter.java
+++ b/libjava/java/awt/image/RGBImageFilter.java
@@ -46,7 +46,7 @@ package java.awt.image;
*/
public abstract class RGBImageFilter extends ImageFilter
{
- protected ColorModel origmodel = ColorModel.getRGBdefault();
+ protected ColorModel origmodel;
protected ColorModel newmodel;
@@ -126,7 +126,7 @@ public abstract class RGBImageFilter extends ImageFilter
private int makeColor( byte a, byte r, byte g, byte b )
{
- return ( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (b << 8) | 0xff & g );
+ return ( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b );
}
/**
@@ -149,11 +149,15 @@ public abstract class RGBImageFilter extends ImageFilter
int off,
int scansize)
{
- int xp, yp;
+ int xp, yp, i;
+ i = 0;
for( xp = x; xp < ( x + w); xp++ )
for( yp = y; yp < (y + h); yp++ )
- pixels[ off + yp * scansize + xp ] = filterRGB( xp, yp, pixels[ off + yp * scansize + xp ] );
+ {
+ pixels[i] = filterRGB( xp, yp, pixels[i] );
+ i++;
+ }
}
@@ -172,15 +176,19 @@ public abstract class RGBImageFilter extends ImageFilter
* @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)
+ ColorModel model, byte[] pixels,
+ int offset, int scansize)
{
- if( model == origmodel ) {
+ if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel)
+ {
consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
- } else {
- //FIXME
- //convert to proper CM
- int pixelsi[] = new int[ pixels.length / 4 ];
- filterRGBPixels( x, y, w, h, pixelsi, 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);
}
}
@@ -199,35 +207,53 @@ public abstract class RGBImageFilter extends ImageFilter
* @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)
+ ColorModel model, int[] pixels,
+ int offset, int scansize)
{
- if( model == origmodel ) {
+ if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel)
+ {
consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
- } else {
+ }
+ 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 void convertColorModelToDefault( int x, int y, int w, int h,
- ColorModel model, int pixels[], int offset, int scansize)
- {
- int xp, yp;
+ 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;
+ }
- for( xp = x; xp < ( x + w); xp++ )
- for( yp = y; yp < (y + h); yp++ )
- pixels[ offset + yp * scansize + xp ] = makeColorbyDefaultCM( pixels[ offset + yp * scansize + xp ] );
-
- }
- private int makeColorbyDefaultCM( int rgb )
- {
- return makeColor( origmodel.getRed( rgb ), origmodel.getGreen( rgb ), origmodel.getGreen( rgb ), origmodel.getBlue( rgb ) );
- }
+ 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 & (b << 8) | 0xff & g );
+ return (int)( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b );
}
diff --git a/libjava/java/awt/image/ReplicateScaleFilter.java b/libjava/java/awt/image/ReplicateScaleFilter.java
index 97992e8..a572da7 100644
--- a/libjava/java/awt/image/ReplicateScaleFilter.java
+++ b/libjava/java/awt/image/ReplicateScaleFilter.java
@@ -104,7 +104,27 @@ public class ReplicateScaleFilter extends ImageFilter
*/
public void setDimensions(int width, int height)
{
- consumer.setDimensions(width, 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);
}
/**
@@ -136,7 +156,18 @@ public class ReplicateScaleFilter extends ImageFilter
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);
+ 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);
}
/**
@@ -156,8 +187,58 @@ public class ReplicateScaleFilter extends ImageFilter
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);
+ 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);
}
+ protected 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;
+ }
+
+ protected 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;
+ }
}