diff options
Diffstat (limited to 'libjava')
97 files changed, 17323 insertions, 5538 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 0ad3633277a..092623c1f5f 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,559 @@ +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. + 2004-05-26 Jerry Quinn <jlquinn@optonline.net> PR libgcj/8321 diff --git a/libjava/Makefile.am b/libjava/Makefile.am index 2f72f96343e..e8fac90557d 100644 --- a/libjava/Makefile.am +++ b/libjava/Makefile.am @@ -1325,9 +1325,12 @@ javax/swing/plaf/basic/BasicCheckBoxUI.java \ javax/swing/plaf/basic/BasicGraphicsUtils.java \ javax/swing/plaf/basic/BasicLabelUI.java \ javax/swing/plaf/basic/BasicListUI.java \ +javax/swing/plaf/basic/BasicMenuUI.java \ +javax/swing/plaf/basic/BasicMenuBarUI.java \ javax/swing/plaf/basic/BasicMenuItemUI.java \ javax/swing/plaf/basic/BasicOptionPaneUI.java \ javax/swing/plaf/basic/BasicPanelUI.java \ +javax/swing/plaf/basic/BasicPopupMenuUI.java \ javax/swing/plaf/basic/BasicProgressBarUI.java \ javax/swing/plaf/basic/BasicRootPaneUI.java \ javax/swing/plaf/basic/BasicRadioButtonUI.java \ diff --git a/libjava/Makefile.in b/libjava/Makefile.in index 2ee14dd1a0a..a68a718616c 100644 --- a/libjava/Makefile.in +++ b/libjava/Makefile.in @@ -1004,9 +1004,12 @@ javax/swing/plaf/basic/BasicCheckBoxUI.java \ javax/swing/plaf/basic/BasicGraphicsUtils.java \ javax/swing/plaf/basic/BasicLabelUI.java \ javax/swing/plaf/basic/BasicListUI.java \ +javax/swing/plaf/basic/BasicMenuUI.java \ +javax/swing/plaf/basic/BasicMenuBarUI.java \ javax/swing/plaf/basic/BasicMenuItemUI.java \ javax/swing/plaf/basic/BasicOptionPaneUI.java \ javax/swing/plaf/basic/BasicPanelUI.java \ +javax/swing/plaf/basic/BasicPopupMenuUI.java \ javax/swing/plaf/basic/BasicProgressBarUI.java \ javax/swing/plaf/basic/BasicRootPaneUI.java \ javax/swing/plaf/basic/BasicRadioButtonUI.java \ @@ -4667,9 +4670,12 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \ .deps/javax/swing/plaf/basic/BasicLabelUI.P \ .deps/javax/swing/plaf/basic/BasicListUI.P \ .deps/javax/swing/plaf/basic/BasicLookAndFeel.P \ +.deps/javax/swing/plaf/basic/BasicMenuBarUI.P \ .deps/javax/swing/plaf/basic/BasicMenuItemUI.P \ +.deps/javax/swing/plaf/basic/BasicMenuUI.P \ .deps/javax/swing/plaf/basic/BasicOptionPaneUI.P \ .deps/javax/swing/plaf/basic/BasicPanelUI.P \ +.deps/javax/swing/plaf/basic/BasicPopupMenuUI.P \ .deps/javax/swing/plaf/basic/BasicProgressBarUI.P \ .deps/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.P \ .deps/javax/swing/plaf/basic/BasicRadioButtonUI.P \ diff --git a/libjava/gnu/java/awt/peer/gtk/GdkGraphics.java b/libjava/gnu/java/awt/peer/gtk/GdkGraphics.java index d36ac2d5019..8ea6817f33e 100644 --- a/libjava/gnu/java/awt/peer/gtk/GdkGraphics.java +++ b/libjava/gnu/java/awt/peer/gtk/GdkGraphics.java @@ -46,6 +46,7 @@ import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; import java.awt.Shape; +import java.awt.SystemColor; import java.awt.image.ImageObserver; import java.text.AttributedCharacterIterator; @@ -149,7 +150,10 @@ public class GdkGraphics extends Graphics return true; } - return drawImage (img, x, y, component.getBackground (), observer); + if (component != null) + return drawImage (img, x, y, component.getBackground (), observer); + else + return drawImage (img, x, y, SystemColor.window, observer); } public boolean drawImage (Image img, int x, int y, int width, int height, @@ -168,8 +172,12 @@ public class GdkGraphics extends Graphics public boolean drawImage (Image img, int x, int y, int width, int height, ImageObserver observer) { - return drawImage (img, x, y, width, height, component.getBackground (), - observer); + if (component != null) + return drawImage (img, x, y, width, height, component.getBackground (), + observer); + else + return drawImage (img, x, y, width, height, SystemColor.window, + observer); } public boolean drawImage (Image img, int dx1, int dy1, int dx2, int dy2, @@ -191,8 +199,12 @@ public class GdkGraphics extends Graphics int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { - return drawImage (img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, - component.getBackground (), observer); + if (component != null) + return drawImage (img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, + component.getBackground (), observer); + else + return drawImage (img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, + SystemColor.window, observer); } native public void drawLine (int x1, int y1, int x2, int y2); diff --git a/libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java b/libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java index 633eb096483..3e77047f72f 100644 --- a/libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java +++ b/libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java @@ -823,13 +823,13 @@ public class GdkGraphics2D extends Graphics2D public void setClip (int x, int y, int width, int height) { - clip = new Rectangle2D.Double ((double)x, (double)y, - (double)width, (double)height); - setClip(clip); + setClip(new Rectangle2D.Double ((double)x, (double)y, + (double)width, (double)height)); } public void setClip (Shape s) { + clip = s; if (s != null) { cairoNewPath (); diff --git a/libjava/gnu/java/awt/peer/gtk/GtkButtonPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkButtonPeer.java index 86c7c37e6df..cdd5f9ca907 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkButtonPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkButtonPeer.java @@ -54,9 +54,10 @@ public class GtkButtonPeer extends GtkComponentPeer public native void connectJObject (); public native void connectSignals (); - native void gtkSetFont(String name, int style, int size); + native void gtkSetFont (String name, int style, int size); native void gtkSetLabel(String label); native void gtkWidgetSetForeground (int red, int green, int blue); + native void gtkActivate (); public GtkButtonPeer (Button b) { @@ -87,8 +88,11 @@ public class GtkButtonPeer extends GtkComponentPeer { KeyEvent ke = (KeyEvent) e; if (!ke.isConsumed () && ke.getKeyCode () == KeyEvent.VK_SPACE) - postActionEvent (((Button)awtComponent).getActionCommand (), - ke.getModifiers ()); + { + postActionEvent (((Button) awtComponent).getActionCommand (), + ke.getModifiers ()); + gtkActivate (); + } } super.handleEvent (e); @@ -100,9 +104,4 @@ public class GtkButtonPeer extends GtkComponentPeer args.add ("label", ((Button)component).getLabel ()); } - - public void setFont (Font f) - { - gtkSetFont(f.getName(), f.getStyle(), f.getSize()); - } } diff --git a/libjava/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java index 2cff9cc1016..a4657988184 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java @@ -56,7 +56,7 @@ public class GtkCheckboxPeer extends GtkComponentPeer boolean state); public native void nativeSetCheckboxGroup (GtkCheckboxGroupPeer group); public native void connectSignals (); - public native void gtkSetFont (String name, int style, int size); + native void gtkSetFont (String name, int style, int size); public native void gtkSetLabel (String label); public GtkCheckboxPeer (Checkbox c) @@ -87,11 +87,6 @@ public class GtkCheckboxPeer extends GtkComponentPeer gtkSetLabel (label); } - public void setFont (Font f) - { - gtkSetFont(f.getName(), f.getStyle(), f.getSize()); - } - public void setCheckboxGroup (CheckboxGroup group) { GtkCheckboxGroupPeer gp diff --git a/libjava/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkComponentPeer.java index 1a9d963b78e..fe52ef0a2dd 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkComponentPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkComponentPeer.java @@ -54,12 +54,14 @@ import java.awt.GraphicsConfiguration; import java.awt.Image; import java.awt.Insets; import java.awt.ItemSelectable; +import java.awt.KeyboardFocusManager; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.FocusEvent; import java.awt.event.ItemEvent; +import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.PaintEvent; @@ -91,6 +93,9 @@ public class GtkComponentPeer extends GtkGenericPeer native void gtkWidgetSetCursor (int type); native void gtkWidgetSetBackground (int red, int green, int blue); native void gtkWidgetSetForeground (int red, int green, int blue); + native void gtkWidgetRequestFocus (); + native void gtkWidgetDispatchKeyEvent (int id, long when, int mods, + int keyCode, int keyLocation); native void gtkSetFont (String name, int style, int size); native void gtkWidgetQueueDrawArea(int x, int y, int width, int height); native void addExposeFilter(); @@ -138,10 +143,10 @@ public class GtkComponentPeer extends GtkGenericPeer awtComponent.getX(), awtComponent.getY(), dims[0], dims[1]); - } + } + Rectangle bounds = awtComponent.getBounds (); setBounds (bounds.x, bounds.y, bounds.width, bounds.height); - } catch (RuntimeException ex) { ; } } @@ -222,6 +227,7 @@ public class GtkComponentPeer extends GtkGenericPeer public void handleEvent (AWTEvent event) { int id = event.getID(); + KeyEvent ke = null; switch (id) { @@ -251,6 +257,16 @@ public class GtkComponentPeer extends GtkGenericPeer } } break; + case KeyEvent.KEY_PRESSED: + ke = (KeyEvent) event; + gtkWidgetDispatchKeyEvent (ke.getID (), ke.getWhen (), ke.getModifiers (), + ke.getKeyCode (), ke.getKeyLocation ()); + break; + case KeyEvent.KEY_RELEASED: + ke = (KeyEvent) event; + gtkWidgetDispatchKeyEvent (ke.getID (), ke.getWhen (), ke.getModifiers (), + ke.getKeyCode (), ke.getKeyLocation ()); + break; } } @@ -335,7 +351,11 @@ public class GtkComponentPeer extends GtkGenericPeer new Rectangle (x, y, width, height))); } - native public void requestFocus (); + public void requestFocus () + { + gtkWidgetRequestFocus (); + postFocusEvent (FocusEvent.FOCUS_GAINED, false); + } public void reshape (int x, int y, int width, int height) { @@ -453,10 +473,28 @@ public class GtkComponentPeer extends GtkGenericPeer } protected void postKeyEvent (int id, long when, int mods, - int keyCode, char keyChar, int keyLocation) - { - q.postEvent (new KeyEvent (awtComponent, id, when, mods, - keyCode, keyChar, keyLocation)); + int keyCode, char keyChar, int keyLocation) + { + KeyEvent keyEvent = new KeyEvent (awtComponent, id, when, mods, + keyCode, keyChar, keyLocation); + + // Also post a KEY_TYPED event if keyEvent is a key press that + // doesn't represent an action or modifier key. + if (keyEvent.getID () == KeyEvent.KEY_PRESSED + && (!keyEvent.isActionKey () + && keyCode != KeyEvent.VK_SHIFT + && keyCode != KeyEvent.VK_CONTROL + && keyCode != KeyEvent.VK_ALT)) + { + synchronized (q) + { + q.postEvent (keyEvent); + q.postEvent (new KeyEvent (awtComponent, KeyEvent.KEY_TYPED, when, mods, + KeyEvent.VK_UNDEFINED, keyChar, keyLocation)); + } + } + else + q.postEvent (keyEvent); } protected void postFocusEvent (int id, boolean temporary) diff --git a/libjava/gnu/java/awt/peer/gtk/GtkDialogPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkDialogPeer.java index 6aefba608e6..4febbef9c9a 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkDialogPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkDialogPeer.java @@ -41,7 +41,10 @@ package gnu.java.awt.peer.gtk; import java.awt.AWTEvent; import java.awt.Component; import java.awt.Dialog; +import java.awt.Graphics; import java.awt.peer.DialogPeer; +import java.awt.Rectangle; +import java.awt.event.PaintEvent; public class GtkDialogPeer extends GtkWindowPeer implements DialogPeer @@ -50,6 +53,33 @@ public class GtkDialogPeer extends GtkWindowPeer { super (dialog); } + + public Graphics getGraphics () + { + Graphics g; + if (GtkToolkit.useGraphics2D ()) + g = new GdkGraphics2D (this); + else + g = new GdkGraphics (this); + g.translate (-insets.left, -insets.top); + return g; + } + + protected void postMouseEvent(int id, long when, int mods, int x, int y, + int clickCount, boolean popupTrigger) + { + super.postMouseEvent (id, when, mods, + x + insets.left, y + insets.top, + clickCount, popupTrigger); + } + + protected void postExposeEvent (int x, int y, int width, int height) + { + q.postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT, + new Rectangle (x + insets.left, + y + insets.top, + width, height))); + } void create () { diff --git a/libjava/gnu/java/awt/peer/gtk/GtkImage.java b/libjava/gnu/java/awt/peer/gtk/GtkImage.java index fa81b912589..57c3d45c697 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkImage.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkImage.java @@ -241,7 +241,7 @@ public class GtkImage extends Image implements ImageConsumer return; } - if (scansize == width) + if (scansize == width && height == 1) { System.arraycopy (pixels, offset, pixelCache, y * this.width + x, diff --git a/libjava/gnu/java/awt/peer/gtk/GtkImagePainter.java b/libjava/gnu/java/awt/peer/gtk/GtkImagePainter.java index a5a8d095985..0476c8cf00f 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkImagePainter.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkImagePainter.java @@ -119,6 +119,11 @@ public class GtkImagePainter implements Runnable, ImageConsumer static int[] convertPixels (int[] pixels, ColorModel model) { + if (pixels == null || model == null) + { + return null; + } + if (model.equals (ColorModel.getRGBdefault ())) return pixels; @@ -133,6 +138,11 @@ public class GtkImagePainter implements Runnable, ImageConsumer static int[] convertPixels (byte[] pixels, ColorModel model) { + if (pixels == null || model == null) + { + return null; + } + int ret[] = new int[pixels.length]; for (int i = 0; i < pixels.length; i++) @@ -178,8 +188,8 @@ public class GtkImagePainter implements Runnable, ImageConsumer setPixels (int x, int y, int width, int height, ColorModel model, byte[] pixels, int offset, int scansize) { - setPixels (x, y, width, height, model, convertPixels (pixels, model), - offset, scansize); + setPixels (x, y, width, height, ColorModel.getRGBdefault(), + convertPixels (pixels, model), offset, scansize); } public void diff --git a/libjava/gnu/java/awt/peer/gtk/GtkLabelPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkLabelPeer.java index cf39372ec2f..c28b7f597cc 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkLabelPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkLabelPeer.java @@ -47,7 +47,7 @@ public class GtkLabelPeer extends GtkComponentPeer implements LabelPeer { native void create (String text, float alignment); - native void gtkSetFont(String name, int style, int size); + native void gtkSetFont (String name, int style, int size); native void nativeSetAlignment (float alignment); native public void setText (String text); @@ -63,11 +63,6 @@ public class GtkLabelPeer extends GtkComponentPeer super (l); } - public void setFont (Font f) - { - gtkSetFont(f.getName(), f.getStyle(), f.getSize()); - } - public void setAlignment (int alignment) { nativeSetAlignment (getGtkAlignment (alignment)); diff --git a/libjava/gnu/java/awt/peer/gtk/GtkListPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkListPeer.java index 7517c64655f..9ca30c92fa9 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkListPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkListPeer.java @@ -48,13 +48,22 @@ import java.awt.peer.ListPeer; public class GtkListPeer extends GtkComponentPeer implements ListPeer { -// native void create (ComponentPeer parent, String [] items, boolean mode); + void create () + { + List list = (List) awtComponent; + + create (list.getRows ()); + + setMultipleMode (list.isMultipleMode ()); + } - native void create (); + native void create (int rows); native void connectJObject (); native void connectSignals (); + native void gtkSetFont (String name, int style, int size); + native void gtkWidgetRequestFocus (); - native void getSize (int rows, int dims[]); + native void getSize (int rows, int visibleRows, int dims[]); public GtkListPeer (List list) { @@ -100,7 +109,8 @@ public class GtkListPeer extends GtkComponentPeer { int dims[] = new int[2]; - getSize (rows, dims); + int visibleRows = ((List) awtComponent).getRows(); + getSize (rows, visibleRows, dims); return new Dimension (dims[0], dims[1]); } @@ -108,7 +118,8 @@ public class GtkListPeer extends GtkComponentPeer { int dims[] = new int[2]; - getSize (rows, dims); + int visibleRows = ((List) awtComponent).getRows(); + getSize (rows, visibleRows, dims); return new Dimension (dims[0], dims[1]); } @@ -129,19 +140,19 @@ public class GtkListPeer extends GtkComponentPeer { if (e.getID () == MouseEvent.MOUSE_CLICKED && isEnabled ()) { - /* Only generate the ActionEvent on the second click of - a multiple click */ + // Only generate the ActionEvent on the second click of a + // multiple click. MouseEvent me = (MouseEvent) e; if (!me.isConsumed () && (me.getModifiers () & MouseEvent.BUTTON1_MASK) != 0 && me.getClickCount() == 2) { - String selectedItem = ((List)awtComponent).getSelectedItem (); + String selectedItem = ((List) awtComponent).getSelectedItem (); - /* Double-click only generates an Action event - if something is selected */ + // Double-click only generates an Action event if + // something is selected. if (selectedItem != null) - postActionEvent (((List)awtComponent).getSelectedItem (), + postActionEvent (((List) awtComponent).getSelectedItem (), me.getModifiers ()); } } @@ -151,9 +162,10 @@ public class GtkListPeer extends GtkComponentPeer KeyEvent ke = (KeyEvent) e; if (!ke.isConsumed () && ke.getKeyCode () == KeyEvent.VK_ENTER) { - String selectedItem = ((List)awtComponent).getSelectedItem (); + String selectedItem = ((List) awtComponent).getSelectedItem (); - /* Enter only generates an Action event if something is selected */ + // Enter only generates an Action event if something is + // selected. if (selectedItem != null) postActionEvent (selectedItem, ke.getModifiers ()); } diff --git a/libjava/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java index 63d6fa86fe1..18e4d204897 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java @@ -50,6 +50,7 @@ public class GtkTextAreaPeer extends GtkTextComponentPeer native void create (int width, int height, int scrollbarVisibility); native void gtkSetFont (String name, int style, int size); + native void gtkWidgetRequestFocus (); void create () { @@ -171,9 +172,4 @@ public class GtkTextAreaPeer extends GtkTextComponentPeer { insert (str, pos); } - - public void setFont (Font f) - { - gtkSetFont (f.getName (), f.getStyle (), f.getSize ()); - } } diff --git a/libjava/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java index 8ee06d6f2b3..5662336b193 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java @@ -154,11 +154,6 @@ public class GtkTextFieldPeer extends GtkTextComponentPeer setEchoChar (c); } - public void setFont (Font f) - { - gtkSetFont (f.getName (), f.getStyle (), f.getSize ()); - } - public void handleEvent (AWTEvent e) { if (e.getID () == KeyEvent.KEY_PRESSED) diff --git a/libjava/gnu/java/awt/peer/gtk/GtkToolkit.java b/libjava/gnu/java/awt/peer/gtk/GtkToolkit.java index ed1c567624b..c9739c359b1 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkToolkit.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkToolkit.java @@ -428,9 +428,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit return q; } - protected void loadSystemColors (int[] systemColors) - { - } + protected native void loadSystemColors (int[] systemColors); public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e) { diff --git a/libjava/java/applet/Applet.java b/libjava/java/applet/Applet.java index 27c8aafb7fb..009b18cedc0 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 41cdad53fd6..a084dcf24a0 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 d52818af683..3ca2b4f7aae 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 d66655934ac..0482e654736 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 ce4bdf8bc0e..fa7ab4ad69a 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 ac3a1786cc6..73b1e95a9a4 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 e2a2f688e74..79a98697430 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 91145e1bb48..89b6095578f 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 d4b75b88822..451b092e6de 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 867316ba843..8ebd9e1713c 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 6f60ee69c2f..f27c29695f4 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 81e37fc7d06..51b00dc175d 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 8ffc148b22b..c9a170b9b3b 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 5006afe79e5..d86119993ec 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 b15fe25d0e7..5718024e761 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 97992e8f2a2..a572da7c3bd 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; + } } diff --git a/libjava/javax/swing/Box.java b/libjava/javax/swing/Box.java index d2faeac557e..6c3579c8ded 100644 --- a/libjava/javax/swing/Box.java +++ b/libjava/javax/swing/Box.java @@ -39,6 +39,12 @@ exception statement from your version. */ package javax.swing; import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import java.awt.LayoutManager; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.AWTError; /** * Needs some work I guess.... @@ -49,8 +55,127 @@ public class Box extends JComponent implements Accessible { private static final long serialVersionUID = 1525417495883046342L; - public Box(int a) + protected class AccessibleBox extends AccessibleAWTContainer { - setLayout(new BoxLayout(this, a)); + protected AccessibleBox() + { + } + + public AccessibleRole getAccessibleRole() + { + return null; + } } + + public static class Filler extends JComponent implements Accessible + { + protected class AccessibleBoxFiller// extends AccessibleAWTComponent + { + protected AccessibleBoxFiller() + { + } + + public AccessibleRole getAccessibleRole() + { + return null; + } + } + + protected AccessibleContext accessibleContext; + + private transient Dimension min, pref, max; + + public Filler(Dimension min, Dimension pref, Dimension max) + { + changeShape(min, pref, max); + } + + public void changeShape(Dimension min, Dimension pref, Dimension max) + { + this.min = min; + this.pref = pref; + this.max = max; + } + + public AccessibleContext getAccessibleContext() + { +// if (accessibleContext == null) +// accessibleContext = new AccessibleBoxFiller(); + return accessibleContext; + } + + public Dimension getMaximumSize() + { + return max; + } + + public Dimension getMinimumSize() + { + return min; + } + + public Dimension getPreferredSize() + { + return pref; + } + } + + public Box(int axis) + { + setLayout(new BoxLayout(this, axis)); + } + + public static Component createGlue() + { + return null; + } + + public static Box createHorizontalBox() + { + return null; + } + + public static Component createHorizontalGlue() + { + return null; + } + + public static Component createHorizontalStrut(int width) + { + return null; + } + + public static Component createRigidArea(Dimension d) + { + return null; + } + + public static Box createVerticalBox() + { + return null; + } + + public static Component createVerticalGlue() + { + return null; + } + + public static Component createVerticalStrut(int height) + { + return null; + } + + public void setLayout(LayoutManager l) + { + throw new AWTError("Not allowed to set layout managers for boxes."); + } + + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleBox(); + return accessibleContext; + } + + } diff --git a/libjava/javax/swing/JApplet.java b/libjava/javax/swing/JApplet.java index 82976d38c7b..43ce3e2f107 100644 --- a/libjava/javax/swing/JApplet.java +++ b/libjava/javax/swing/JApplet.java @@ -49,7 +49,7 @@ import java.awt.event.KeyEvent; import java.awt.event.WindowEvent; import javax.accessibility.AccessibleContext; -public class JApplet extends Applet +public class JApplet extends Applet implements RootPaneContainer { public final static int HIDE_ON_CLOSE = 0; @@ -87,20 +87,20 @@ public class JApplet extends Applet public void setLayout(LayoutManager manager) { super.setLayout(manager); } - void setLayeredPane(JLayeredPane layeredPane) + public void setLayeredPane(JLayeredPane layeredPane) { getRootPane().setLayeredPane(layeredPane); } - JLayeredPane getLayeredPane() + public JLayeredPane getLayeredPane() { return getRootPane().getLayeredPane(); } - JRootPane getRootPane() + public JRootPane getRootPane() { if (rootPane == null) setRootPane(createRootPane()); return rootPane; } - void setRootPane(JRootPane root) + public void setRootPane(JRootPane root) { if (rootPane != null) remove(rootPane); @@ -109,19 +109,19 @@ public class JApplet extends Applet add(rootPane, BorderLayout.CENTER); } - JRootPane createRootPane() + public JRootPane createRootPane() { return new JRootPane(); } - Container getContentPane() + public Container getContentPane() { return getRootPane().getContentPane(); } - void setContentPane(Container contentPane) + public void setContentPane(Container contentPane) { getRootPane().setContentPane(contentPane); } - Component getGlassPane() + public Component getGlassPane() { return getRootPane().getGlassPane(); } - void setGlassPane(Component glassPane) + public void setGlassPane(Component glassPane) { getRootPane().setGlassPane(glassPane); } diff --git a/libjava/javax/swing/JCheckBoxMenuItem.java b/libjava/javax/swing/JCheckBoxMenuItem.java index 968b25e9d41..f2399e2d8b3 100644 --- a/libjava/javax/swing/JCheckBoxMenuItem.java +++ b/libjava/javax/swing/JCheckBoxMenuItem.java @@ -39,135 +39,210 @@ package javax.swing; import java.io.IOException; import java.io.ObjectOutputStream; - import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; +/** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.3 $ + */ public class JCheckBoxMenuItem extends JMenuItem implements SwingConstants, Accessible { - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- private static final String uiClassID = "CheckBoxMenuItemUI"; private boolean state; private Object[] selectedObjects; - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- + /** + * Creates a new JCheckBoxMenuItem object. + */ public JCheckBoxMenuItem() { this(null, null); - } // JCheckBoxMenuItem() + } + /** + * Creates a new JCheckBoxMenuItem object. + * + * @param icon DOCUMENT ME! + */ public JCheckBoxMenuItem(Icon icon) { this(null, icon); - } // JCheckBoxMenuItem() + } + /** + * Creates a new JCheckBoxMenuItem object. + * + * @param text DOCUMENT ME! + */ public JCheckBoxMenuItem(String text) { this(text, null); - } // JCheckBoxMenuItem() + } + /** + * Creates a new JCheckBoxMenuItem object. + * + * @param action DOCUMENT ME! + */ public JCheckBoxMenuItem(Action action) { this(); setAction(action); - } // JCheckBoxMenuItem() - + } + + /** + * Creates a new JCheckBoxMenuItem object. + * + * @param text DOCUMENT ME! + * @param icon DOCUMENT ME! + */ public JCheckBoxMenuItem(String text, Icon icon) { this(text, icon, false); - } // JCheckBoxMenuItem() - + } + + /** + * Creates a new JCheckBoxMenuItem object. + * + * @param text DOCUMENT ME! + * @param state DOCUMENT ME! + */ public JCheckBoxMenuItem(String text, boolean state) { this(text, null, state); - } // JCheckBoxMenuItem() - + } + + /** + * Creates a new JCheckBoxMenuItem object. + * + * @param text DOCUMENT ME! + * @param icon DOCUMENT ME! + * @param state DOCUMENT ME! + */ public JCheckBoxMenuItem(String text, Icon icon, boolean state) { super(text, icon); setModel(new JToggleButton.ToggleButtonModel()); this.state = state; - } // JCheckBoxMenuItem() - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- + } + + /** + * DOCUMENT ME! + * + * @param stream DOCUMENT ME! + * + * @throws IOException DOCUMENT ME! + */ private void writeObject(ObjectOutputStream stream) throws IOException { // TODO - } // writeObject() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public String getUIClassID() { return uiClassID; - } // getUIClassID() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public boolean getState() { return state; - } // getState() + } + /** + * DOCUMENT ME! + * + * @param state DOCUMENT ME! + */ public synchronized void setState(boolean state) { this.state = state; - } // setState() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public Object[] getSelectedObjects() { return selectedObjects; - } // getSelectedObjects() + } + /** + * DOCUMENT ME! + */ public void requestFocus() { // TODO - } // requestFocus() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ protected String paramString() { return "JCheckBoxMenuItem"; - } // paramString() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public AccessibleContext getAccessibleContext() { if (accessibleContext == null) - { - accessibleContext = new AccessibleJCheckBoxMenuItem(this); - } + accessibleContext = new AccessibleJCheckBoxMenuItem(this); return accessibleContext; - } // getAccessibleContext() - - //------------------------------------------------------------- - // Classes ---------------------------------------------------- - //------------------------------------------------------------- + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.3 $ + */ protected class AccessibleJCheckBoxMenuItem extends AccessibleJMenuItem { - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- + /** + * Creates a new AccessibleJCheckBoxMenuItem object. + * + * @param component DOCUMENT ME! + */ protected AccessibleJCheckBoxMenuItem(JCheckBoxMenuItem component) { super(component); // TODO - } // AccessibleJCheckBoxMenuItem() + } - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public AccessibleRole getAccessibleRole() { return AccessibleRole.CHECK_BOX; - } // getAccessibleRole() - } // AccessibleJCheckBoxMenuItem -} // JCheckBoxMenuItem + } + } +} diff --git a/libjava/javax/swing/JComponent.java b/libjava/javax/swing/JComponent.java index 7b2261fa43b..b191635ea77 100644 --- a/libjava/javax/swing/JComponent.java +++ b/libjava/javax/swing/JComponent.java @@ -35,7 +35,6 @@ this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ - package javax.swing; import java.awt.Color; @@ -55,6 +54,7 @@ import java.awt.event.ContainerListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.MouseEvent; +import java.awt.geom.Rectangle2D; import java.awt.image.ImageObserver; import java.awt.peer.LightweightPeer; import java.beans.PropertyChangeListener; @@ -63,7 +63,8 @@ import java.beans.VetoableChangeListener; import java.io.Serializable; import java.util.EventListener; import java.util.Hashtable; - +import java.util.Locale; +import java.util.Vector; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; @@ -74,242 +75,372 @@ import javax.swing.event.EventListenerList; import javax.swing.event.SwingPropertyChangeSupport; import javax.swing.plaf.ComponentUI; + /** * Every component in swing inherits from this class (JLabel, JButton, etc). - * It contains generic methods to manage events, properties and sizes. - * Actual drawing of the component is channeled to a look-and-feel class - * that is implemented elsewhere. + * It contains generic methods to manage events, properties and sizes. Actual + * drawing of the component is channeled to a look-and-feel class that is + * implemented elsewhere. * - * @author Ronald Veldema (rveldema@cs.vu.nl) + * @author Ronald Veldema (rveldema&064;cs.vu.nl) + * @author Graydon Hoare (graydon&064;redhat.com) */ public abstract class JComponent extends Container implements Serializable { static final long serialVersionUID = -5242478962609715464L; - protected EventListenerList listenerList = new EventListenerList(); - - /** - * accessibleContext + /** + * Accessibility support is currently missing. */ + protected AccessibleContext accessibleContext; - - Dimension pref,min,max; + + public abstract class AccessibleJComponent + extends AccessibleAWTContainer + { + protected class AccessibleFocusHandler + implements FocusListener + { + protected AccessibleFocusHandler(AccessibleJComponent component){} + public void focusGained(FocusEvent event){} + public void focusLost(FocusEvent valevent){} + } + + protected class AccessibleContainerHandler + implements ContainerListener + { + protected AccessibleContainerHandler(AccessibleJComponent component) {} + public void componentAdded(ContainerEvent event) {} + public void componentRemoved(ContainerEvent valevent) {} + } + + protected ContainerListener accessibleContainerHandler; + protected FocusListener accessibleFocusHandler; + + protected AccessibleJComponent(JComponent component) {} + public void addPropertyChangeListener(PropertyChangeListener listener) {} + public void removePropertyChangeListener(PropertyChangeListener listener) {} + public int getAccessibleChildrenCount() { return 0; } + public Accessible getAccessibleChild(int value0) { return null; } + public AccessibleStateSet getAccessibleStateSet() { return null; } + public String getAccessibleName() { return null; } + public String getAccessibleDescription() { return null; } + public AccessibleRole getAccessibleRole() { return null; } + protected String getBorderTitle(Border value0) { return null; } + } + + /** + * An explicit value for the component's preferred size; if not set by a + * user, this is calculated on the fly by delegating to the {@link + * ComponentUI.getPreferredSize} method on the {@link #ui} property. + */ + Dimension preferredSize; + + /** + * An explicit value for the component's minimum size; if not set by a + * user, this is calculated on the fly by delegating to the {@link + * ComponentUI.getMinimumSize} method on the {@link #ui} property. + */ + Dimension minimumSize; + + /** + * An explicit value for the component's maximum size; if not set by a + * user, this is calculated on the fly by delegating to the {@link + * ComponentUI.getMaximumSize} method on the {@link #ui} property. + */ + Dimension maximumSize; + + + /** + * A value between 0.0 and 1.0 indicating the preferred horizontal + * alignment of the component, relative to its siblings. The values + * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link + * #RIGHT_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>, + * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout + * managers use this property. + * + * @see #getAlignmentX + * @see #setAlignmentX + * @see javax.swing.OverlayLayout + * @see javax.swing.BoxLayout + */ + float alignmentX = 0.0f; + + /** + * A value between 0.0 and 1.0 indicating the preferred vertical + * alignment of the component, relative to its siblings. The values + * {@link #TOP_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link + * #BOTTOM_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>, + * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout + * managers use this property. + * + * @see #getAlignmentY + * @see #setAlignmentY + * @see javax.swing.OverlayLayout + * @see javax.swing.BoxLayout + */ + float alignmentY = 0.0f; + + /** + * The border painted around this component. + * + * @see #paintBorder + */ Border border; - JToolTip tooltip; - String tool_tip_text; - boolean use_double_buffer = false, opaque; - Image doubleBuffer; - int doubleBufferWidth = -1; - int doubleBufferHeight = -1; + + /** + * A tooltip associated with this component. + * + * @see #setToolTip + * @see #getToolTip + * @see #toolTipText + */ + JToolTip toolTip; + + /** + * The text to show in the tooltip associated with this component. + * + * @see #setToolTipText + * @see #getToolTipText + * @see #toolTip + */ + String toolTipText; + + /** + * <p>Whether to double buffer this component when painting. This flag + * should generally be <code>false</code>, except for top level + * components such as {@link JFrame} or {@link JApplet}.</p> + * + * <p>All children of a double buffered component are painted into the + * double buffer automatically, so only the top widget in a window needs + * to be double buffered.</p> + * + * @see #setDoubleBuffered + * @see #isDoubleBuffered + * @see #paintLock + * @see #paint + */ + boolean doubleBuffered = false; + + /** + * A set of flags indicating which debugging graphics facilities should + * be enabled on this component. The values should be a combination of + * {@link DebugGraphics.NONE_OPTION}, {@link DebugGraphics.LOG_OPTION}, + * {@link DebugGraphics.FLASH_OPTION}, or {@link + * DebugGraphics.BUFFERED_OPTION}. + * + * @see setDebugGraphicsOptions + * @see getDebugGraphicsOptions + * @see DebugGraphics + * @see getComponentGraphics + */ + int debugGraphicsOptions; + + /** + * <p>This property controls two independent behaviors simultaneously.</p> + * + * <p>First, it controls whether to fill the background of this widget + * when painting its body. This affects calls to {@link + * JComponent#paintComponent}, which in turn calls {@link + * ComponentUI#update} on the component's {@link #ui} property. If the + * component is opaque during this call, the background will be filled + * before calling {@link ComponentUI#paint}. This happens merely as a + * convenience; you may fill the component's background yourself too, + * but there is no need to do so if you will be filling with the same + * color.</p> + * + * <p>Second, it the opaque property informs swing's repaint system + * whether it will be necessary to paint the components "underneath" this + * component, in Z-order. If the component is opaque, it is considered to + * completely occlude components "underneath" it, so they will not be + * repainted along with the opaque component.</p> + * + * <p>The default value for this property is <code>false</code>, but most + * components will want to set it to <code>true</code> when installing UI + * defaults in {@link ComponentUI#installUI}.</p> + * + * @see #setOpaque + * @see #isOpaque + * @see #paintComponent + */ + boolean opaque = false; + + /** + * The user interface delegate for this component. Event delivery and + * repainting of the component are usually delegated to this object. + * + * @see #setUI + * @see #getUI + * @see #updateUI + */ ComponentUI ui; + + /** + * A hint to the focus system that this component should or should not + * get focus. If this is <code>false</code>, swing will not try to + * request focus on this component; if <code>true</code>, swing might + * try to request focus, but the request might fail. Thus it is only + * a hint guiding swing's behavior. + * + * @see #requestFocus + * @see #isRequestFocusEnabled + * @see #setRequestFocusEnabled + */ + boolean requestFocusEnabled; + + /** + * Flag indicating behavior of this component when the mouse is dragged + * outside the component and the mouse <em>stops moving</em>. If + * <code>true</code>, synthetic mouse events will be delivered on regular + * timed intervals, continuing off in the direction the mouse exited the + * component, until the mouse is released or re-enters the component. + * + * @see setAutoscrolls + * @see getAutoscrolls + */ + boolean autoscrolls = false; + + /** + * Listeners for events other than {@link PropertyChangeEvent} are + * handled by this listener list. PropertyChangeEvents are handled in + * {@link #changeSupport}. + */ + EventListenerList listenerList = new EventListenerList(); + + /** + * Support for {@link PropertyChangeEvent} events. This is constructed + * lazily when the component gets its first {@link + * PropertyChangeListener} subscription; until then it's an empty slot. + */ private SwingPropertyChangeSupport changeSupport; - - Hashtable prop_hash; + + + /** + * Storage for "client properties", which are key/value pairs associated + * with this component by a "client", such as a user application or a + * layout manager. This is lazily constructed when the component gets its + * first client property. + */ + private Hashtable clientProperties; + + /** + * A lock held during recursive painting; this is used to serialize + * access to the double buffer, and also to select the "top level" + * object which should acquire the double buffer in a given widget + * tree (which may have multiple double buffered children). + * + * @see #doubleBuffered + * @see #paint + */ + private static final Object paintLock = new Object(); + + + /** + * The default locale of the component. + * + * @see #getDefaultLocale + * @see #setDefaultLocale + */ + private static Locale defaultLocale; - /** - * AccessibleJComponent - */ - public abstract class AccessibleJComponent - extends AccessibleAWTContainer { - - //------------------------------------------------------------- - // Classes ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * AccessibleFocusHandler - */ - protected class AccessibleFocusHandler implements FocusListener { - /** - * Constructor AccessibleFocusHandler - * @param component TODO - */ - protected AccessibleFocusHandler(AccessibleJComponent component) { - // TODO - } // AccessibleFocusHandler() - - /** - * focusGained - * @param event TODO - */ - public void focusGained(FocusEvent event) { - // TODO - } // focusGained() - - /** - * focusLost - * @param event TODO - */ - public void focusLost(FocusEvent valevent) { - // TODO - } // focusLost() - } // AccessibleFocusHandler - - /** - * AccessibleContainerHandler - */ - protected class AccessibleContainerHandler implements ContainerListener { - /** - * Constructor AccessibleContainerHandler - * @param component TODO - */ - protected AccessibleContainerHandler(AccessibleJComponent component) { - // TODO - } // AccessibleContainerHandler() - - /** - * componentAdded - * @param event TODO - */ - public void componentAdded(ContainerEvent event) { - // TODO - } // componentAdded() - - /** - * componentRemoved - * @param event TODO - */ - public void componentRemoved(ContainerEvent valevent) { - // TODO - } // componentRemoved() - } // AccessibleContainerHandler - - /** - * accessibleContainerHandler - */ - protected ContainerListener accessibleContainerHandler; - - /** - * accessibleFocusHandler - */ - protected FocusListener accessibleFocusHandler; - - /** - * Constructor AccessibleJComponent - * @param component TODO - */ - protected AccessibleJComponent(JComponent component) { -// super((Container)component); - // TODO - } // AccessibleJComponent() - - /** - * addPropertyChangeListener - * @param listener TODO - */ - public void addPropertyChangeListener(PropertyChangeListener listener) { - // TODO - } // addPropertyChangeListener() - - /** - * removePropertyChangeListener - * @param listener TODO - */ - public void removePropertyChangeListener(PropertyChangeListener listener) { - // TODO - } // removePropertyChangeListener() - - /** - * getAccessibleChildrenCount - * @returns int - */ - public int getAccessibleChildrenCount() { - return 0; // TODO - } // getAccessibleChildrenCount() - - /** - * getAccessibleChild - * @param value0 TODO - * @returns Accessible - */ - public Accessible getAccessibleChild(int value0) { - return null; // TODO - } // getAccessibleChild() - - /** - * getAccessibleStateSet - * @returns AccessibleStateSet - */ - public AccessibleStateSet getAccessibleStateSet() { - return null; // TODO - } // getAccessibleStateSet() - - /** - * getAccessibleName - * @returns String - */ - public String getAccessibleName() { - return null; // TODO - } // getAccessibleName() - - /** - * getAccessibleDescription - * @returns String - */ - public String getAccessibleDescription() { - return null; // TODO - } // getAccessibleDescription() - - /** - * getAccessibleRole - * @returns AccessibleRole - */ - public AccessibleRole getAccessibleRole() { - return null; // TODO - } // getAccessibleRole() - - /** - * getBorderTitle - * @param value0 TODO - * @returns String - */ - protected String getBorderTitle(Border value0) { - return null; // TODO - } // getBorderTitle() - - - } // AccessibleJComponent - - - public JComponent() - { - super(); - super.setLayout(new FlowLayout()); - - //eventMask |= AWTEvent.COMP_KEY_EVENT_MASK; - // enableEvents( AWTEvent.KEY_EVENT_MASK ); - - //updateUI(); // get a proper ui - } - - public boolean contains(int x, int y) - { - //return dims.contains(x,y); - return super.contains(x,y); - } - - public void addNotify() - { - //Notification to this component that it now has a parent component. - super.addNotify(); - } - - Hashtable get_prop_hash() - { - if (prop_hash == null) - prop_hash = new Hashtable(); - return prop_hash; - } - - public Object getClientProperty(Object key) - { return get_prop_hash().get(key); } - - public void putClientProperty(Object key, Object value) - { get_prop_hash().put(key, value); } + /** + * Constant used to indicate that no condition has been assigned to a + * particular action. + * + * @see #registerKeyboardAction + */ + public static final int UNDEFINED_CONDITION = -1; + + /** + * Constant used to indicate that an action should be performed only when + * the component has focus. + * + * @see #registerKeyboardAction + */ + public static final int WHEN_FOCUSED = 0; + + /** + * Constant used to indicate that an action should be performed only when + * the component is an ancestor of the component which has focus. + * + * @see #registerKeyboardAction + */ + public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1; + + /** + * Constant used to indicate that an action should be performed only when + * the component is in the window which has focus. + * + * @see #registerKeyboardAction + */ + public static final int WHEN_IN_FOCUSED_WINDOW = 2; + + + public JComponent() + { + super(); + super.setLayout(new FlowLayout()); + defaultLocale = Locale.getDefault(); + debugGraphicsOptions = DebugGraphics.NONE_OPTION; + } + + /** + * Helper to lazily construct and return the client properties table. + * + * @return The current client properties table + * + * @see #clientProperties + * @see #getClientProperty + * @see #putClientProperty + */ + private Hashtable getClientProperties() + { + if (clientProperties == null) + clientProperties = new Hashtable(); + return clientProperties; + } + + /** + * Get a client property associated with this component and a particular + * key. + * + * @param key The key with which to look up the client property + * + * @return A client property associated with this object and key + * + * @see #clientProperties + * @see #getClientProperties + * @see #putClientProperty + */ + public Object getClientProperty(Object key) + { + return getClientProperties().get(key); + } + + /** + * Add a client property <code>value</code> to this component, associated + * with <code>key</code>. If there is an existing client property + * associated with <code>key</code>, it will be replaced. + * + * @param key The key of the client property association to add + * @param value The value of the client property association to add + * + * @see #clientProperties + * @see #getClientProperties + * @see #getClientProperty + */ + public void putClientProperty(Object key, Object value) + { + getClientProperties().put(key, value); + } /** * Unregister an <code>AncestorListener</code>. + * + * @param listener The listener to unregister + * + * @see addAncestorListener */ public void removeAncestorListener(AncestorListener listener) { @@ -318,6 +449,11 @@ public abstract class JComponent extends Container implements Serializable /** * Unregister a <code>PropertyChangeListener</code>. + * + * @param listener The listener to register + * + * @see #addPropertyChangeListener + * @see #changeSupport */ public void removePropertyChangeListener(PropertyChangeListener listener) { @@ -327,14 +463,26 @@ public abstract class JComponent extends Container implements Serializable /** * Unregister a <code>PropertyChangeListener</code>. + * + * @param propertyName The property name to unregister the listener from + * @param listener The listener to unregister + * + * @see #addPropertyChangeListener + * @see #changeSupport */ - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { - listenerList.remove(PropertyChangeListener.class, listener); + if (changeSupport != null) + changeSupport.removePropertyChangeListener(propertyName, listener); } /** * Unregister a <code>VetoableChangeChangeListener</code>. + * + * @param listener The listener to unregister + * + * @see #addVetoableChangeListener */ public void removeVetoableChangeListener(VetoableChangeListener listener) { @@ -343,6 +491,10 @@ public abstract class JComponent extends Container implements Serializable /** * Register an <code>AncestorListener</code>. + * + * @param listener The listener to register + * + * @see #removeVetoableChangeListener */ public void addAncestorListener(AncestorListener listener) { @@ -350,7 +502,15 @@ public abstract class JComponent extends Container implements Serializable } /** - * Register a <code>PropertyChangeListener</code>. + * Register a <code>PropertyChangeListener</code>. This listener will + * receive any PropertyChangeEvent, regardless of property name. To + * listen to a specific property name, use {@link + * #addPropertyChangeListener(String,PropertyChangeListener)} instead. + * + * @param listener The listener to register + * + * @see #removePropertyChangeListener + * @see #changeSupport */ public void addPropertyChangeListener(PropertyChangeListener listener) { @@ -360,15 +520,29 @@ public abstract class JComponent extends Container implements Serializable } /** - * Register a <code>PropertyChangeListener</code>. + * Register a <code>PropertyChangeListener</code> for a specific, named + * property. To listen to all property changes, regardless of name, use + * {@link #addPropertyChangeListener(PropertyChangeListener)} instead. + * + * @param propertyName The property name to listen to + * @param listener The listener to register + * + * @see #removePropertyChangeListener + * @see #changeSupport */ - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { listenerList.add(PropertyChangeListener.class, listener); } /** * Register a <code>VetoableChangeListener</code>. + * + * @param listener The listener to register + * + * @see #removeVetoableChangeListener + * @see #listenerList */ public void addVetoableChangeListener(VetoableChangeListener listener) { @@ -376,722 +550,1345 @@ public abstract class JComponent extends Container implements Serializable } /** - * Return all registered listeners of a special type. - * - * @since 1.3 + * Return all registered listeners of a particular type. + * + * @param listenerType The type of listener to return + * + * @return All listeners in the {@link #listenerList} which + * are of the specified type + * + * @see #listenerList */ - public EventListener[] getListeners (Class listenerType) + public EventListener[] getListeners(Class listenerType) { - return listenerList.getListeners (listenerType); + return listenerList.getListeners(listenerType); } - + /** - * Return all registered <code>Ancestor</code> objects. - * - * @since 1.4 + * Return all registered <code>AncestorListener</code> objects. + * + * @return The set of <code>AncestorListener</code> objects in {@link + * #listenerList} */ public AncestorListener[] getAncestorListeners() { - return (AncestorListener[]) getListeners (AncestorListener.class); + return (AncestorListener[]) getListeners(AncestorListener.class); } /** * Return all registered <code>VetoableChangeListener</code> objects. - * - * @since 1.4 + * + * @return The set of <code>VetoableChangeListener</code> objects in {@link + * #listenerList} */ public VetoableChangeListener[] getVetoableChangeListeners() { - return (VetoableChangeListener[]) getListeners (VetoableChangeListener.class); - } - - public void computeVisibleRect(Rectangle rect) - { - //Returns the Component's "visible rect rectangle" - the intersection of the visible rectangles for this component and all of its ancestors. - //super.computeVisibleRect(rect); - } - - public PropertyChangeListener[] getPropertyChangeListeners(String property) - { - return changeSupport == null ? new PropertyChangeListener[0] - : changeSupport.getPropertyChangeListeners(property); - } - - public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Boolean(oldValue), - new Boolean(newValue)); - } - public void firePropertyChange(String propertyName, byte oldValue, byte newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Byte(oldValue), - new Byte(newValue)); - } - public void firePropertyChange(String propertyName, char oldValue, char newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Character(oldValue), - new Character(newValue)); - } - - public void firePropertyChange(String propertyName, double oldValue, double newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Double(oldValue), - new Double(newValue)); - } - - public void firePropertyChange(String propertyName, float oldValue, float newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Float(oldValue), - new Float(newValue)); - } - public void firePropertyChange(String propertyName, int oldValue, int newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Integer(oldValue), - new Integer(newValue)); - } - public void firePropertyChange(String propertyName, long oldValue, long newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Long(oldValue), - new Long(newValue)); - } - - protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, oldValue, newValue); - } - public void firePropertyChange(String propertyName, short oldValue, short newValue) - { - if (changeSupport != null) - changeSupport.firePropertyChange(propertyName, new Short(oldValue), - new Short(newValue)); - } - - protected void fireVetoableChange(String propertyName, Object oldValue, Object newValue) - throws PropertyVetoException - { - // Support for reporting constrained property changes. - } - - public AccessibleContext getAccessibleContext() - { - // Get the AccessibleContext associated with this JComponent - return null; - } - - public ActionListener getActionForKeyStroke(KeyStroke aKeyStroke) - { - //Return the object that will perform the action registered for a given keystroke. - return null; - } - public float getAlignmentX() - { - // Overrides Container.getAlignmentX to return the vertical alignment. - return 0; - } - - public float getAlignmentY() - { - // Overrides Container.getAlignmentY to return the horizontal alignment. - return 0; - } - public boolean getAutoscrolls() - { - //Returns true if this component automatically scrolls its contents when dragged, (when contained in a component that supports scrolling, like JViewport - return false; - } - - public void setBorder(Border border) - { - //System.out.println("set border called !, new border = " + border); - this.border = border; - revalidate(); - repaint(); - } - - public Border getBorder() - { return border; } - - - public Rectangle getBounds(Rectangle rv) - { - if (rv == null) - return new Rectangle(getX(),getY(),getWidth(),getHeight()); - else - { - rv.setBounds(getX(),getY(),getWidth(),getHeight()); - return rv; - } - } - - protected Graphics getComponentGraphics(Graphics g) - { return g; } - - public int getConditionForKeyStroke(KeyStroke aKeyStroke) - { - //Return the condition that determines whether a registered action occurs in response to the specified keystroke. - return 0; - } - public int getDebugGraphicsOptions() - { - return 0; - } - - public Graphics getGraphics() - { return super.getGraphics(); } - - - // static MantaNative void DebugMe(Border b); - - public Insets getInsets() - { - // System.out.println("watch this border"); - // DebugMe(border); - // System.out.println("border = " + border); - - if (border == null) - { - //System.out.println("compares to null !"); - return super.getInsets(); - } - // System.out.println("compare failed !"); - return getBorder().getBorderInsets(this); - } - - public Insets getInsets(Insets insets) - { - Insets t = getInsets(); - - if (insets == null) - return t; - - - return new Insets(t.top, t.left, t.bottom, t.right); - } - public Point getLocation(Point rv) - { - //Store the x,y origin of this component into "return value" rv and return rv. - - if (rv == null) - return new Point(getX(), - getY()); - - rv.setLocation(getX(), - getY()); - return rv; - } - - public Dimension getMaximumSize() - { - if (max != null) - { - //System.out.println("HAVE_MAX_SIZE = " + max); - return max; - } - if (ui != null) - { - Dimension s = ui.getMaximumSize(this); - if (s != null) - { - //System.out.println(" UI-MAX = " + s + ", UI = " + ui + ", IM="+this); - return s; - } - } - Dimension p = super.getMaximumSize(); - //System.out.println(" MAX = " + p + ", COMP="+this); - return p; - } - - public Dimension getMinimumSize() - { - if (min != null) - { - //System.out.println("HAVE_MIN_SIZE = " + min); - return min; - } - if (ui != null) - { - Dimension s = ui.getMinimumSize(this); - if (s != null) - { - // System.out.println(" UI-MIN = " + s + ", UI = " + ui + ", IM="+this); - return s; - } - } - Dimension p = super.getMinimumSize(); - // System.out.println(" MIN = " + p + ", COMP="+this); - return p; - } - - public Dimension getPreferredSize() - { - if (pref != null) - { - //System.out.println("HAVE_PREF_SIZE = " + pref); - return pref; - } - - if (ui != null) - { - Dimension s = ui.getPreferredSize(this); - if (s != null) - { - //System.out.println(" UI-PREF = " + s + ", UI = " + ui + ", IM="+this); - return s; - } - } - Dimension p = super.getPreferredSize(); - // System.out.println(" PREF = " + p + ", COMP="+this); - return p; - } - - public Component getNextFocusableComponent() - { - // Return the next focusable component or null if the focus manager should choose the next focusable component automatically - return null; - } - - - public KeyStroke[] getRegisteredKeyStrokes() - { - // Return the KeyStrokes that will initiate registered actions. - return null; - } - - public JRootPane getRootPane() - { - JRootPane p = SwingUtilities.getRootPane(this); - System.out.println("root = " + p); - return p; - } - - public Dimension getSize(Dimension rv) - { - // System.out.println("JComponent, getsize()"); - if (rv == null) - return new Dimension(getWidth(), - getHeight()); - else - { - rv.setSize(getWidth(), - getHeight()); - return rv; - } - } - - public JToolTip createToolTip() - { - if (tooltip == null) - tooltip = new JToolTip(tool_tip_text); - return tooltip; - } - - public Point getToolTipLocation(MouseEvent event) - { return null; } - - public void setToolTipText(String text) - { tool_tip_text = text; } - - public String getToolTipText() - { return tool_tip_text; } - - public String getToolTipText(MouseEvent event) - { return tool_tip_text; } - - public Container getTopLevelAncestor() - { - // Returns the top-level ancestor of this component (either the containing Window or Applet), or null if this component has not been added to any container. - System.out.println("JComponent, getTopLevelAncestor()"); - return null; - } - - public Rectangle getVisibleRect() - { - /// Returns the Component's "visible rectangle" - the intersection of this components visible rectangle: - System.out.println("JComponent, getVisibleRect()"); - return null; - } - - public void grabFocus() - { - // Set the focus on the receiving component. - } - - public boolean hasFocus() - { - // Returns true if this Component has the keyboard focus. - return false; - } - - public boolean isDoubleBuffered() - { return use_double_buffer; } - - public boolean isFocusCycleRoot() - { - // Override this method and return true if your component is the root of of a component tree with its own focus cycle. - return false; - } - - public boolean isFocusTraversable() - { - // Identifies whether or not this component can receive the focus. - return false; - } - - public static boolean isLightweightComponent(Component c) - { - return c.getPeer() instanceof LightweightPeer; - } - - public boolean isManagingFocus() - { - // Override this method and return true if your JComponent manages focus. - return false; - } - - public boolean isOpaque() - { return opaque; } - - public boolean isOptimizedDrawingEnabled() - { - // Returns true if this component tiles its children, - return true; - } - - public boolean isPaintingTile() - { - // Returns true if the receiving component is currently painting a tile. - return false; - } - - public boolean isRequestFocusEnabled() - { - // Return whether the receiving component can obtain the focus by calling requestFocus - return false; - } - - public boolean isValidateRoot() - { - // If this method returns true, revalidate() calls by descendants of this component will cause the entire tree beginning with this root to be validated. - return false; - } - - public void paint(Graphics g) - { - Graphics g2 = g; - Rectangle r = getBounds (); - - if (use_double_buffer) - { - - if (doubleBuffer == null - || doubleBufferWidth != r.width - || doubleBufferHeight != r.height) - { - doubleBuffer = createImage(r.width, r.height); - doubleBufferWidth = r.width; - doubleBufferHeight = r.height; - } - - g2 = doubleBuffer.getGraphics (); - if (this.getBackground() != null) - { - Color save = g2.getColor(); - g2.setColor(this.getBackground()); - g2.fillRect (0, 0, r.width, r.height); - g2.setColor(save); - } - else - g2.clearRect(0, 0, r.width, r.height); - } - - paintBorder(g2); - paintComponent(g2); - paintChildren(g2); - - if (use_double_buffer) - { - // always draw at 0,0, because regardless of your current bounds, - // the graphics object you were passed was positioned so the origin - // was at the upper left corner of your bounds. - g.drawImage (doubleBuffer, 0, 0, (ImageObserver)null); - } - } - - protected void paintBorder(Graphics g) - { - // System.out.println("PAINT_BORDER x XXXXXXX x x x x x x x x x x x x:" + getBorder() + ", THIS="+this); - - // Paint the component's border. - if (getBorder() != null) - { - //System.out.println("PAINT_BORDER x XXXXXXX x x x x x x x x x x x x:" + getBorder() + ", THIS="+this); - - getBorder().paintBorder(this, - g, - 0, - 0, - getWidth(), - getHeight()); - } - } - - protected void paintChildren(Graphics g) - { - // Paint this component's children. - super.paint(g); - } - - protected void paintComponent(Graphics g) - { - // If the UI delegate is non-null, call its paint method. - if (ui != null) - { - ui.paint(g, this); - } - } - - /** - * Paint the specified region in this component and all of - * its descendants that overlap the region, immediately. - */ - public void paintImmediately(int x, int y, int w, int h) - { - - //Ronald: this shoudld probably redirect to the PLAF .... - } - - public void paintImmediately(Rectangle r) - { - /// Paint the specified region now. - paintImmediately((int)r.getX(), - (int)r.getY(), - (int)r.getWidth(), - (int)r.getHeight()); - } - protected String paramString() - { - // Returns a string representation of this JComponent. - return "JComponent"; - } - - public void registerKeyboardAction(ActionListener anAction, - KeyStroke aKeyStroke, - int aCondition) - { - registerKeyboardAction(anAction, - null, - aKeyStroke, - aCondition); - } - - public void registerKeyboardAction(ActionListener anAction, - String aCommand, - KeyStroke aKeyStroke, - int aCondition) - { - // Register a new keyboard action. - } - - - public void removeNotify() - { - // Notification to this component that it no longer has a parent component. - } - - public void repaint(long tm, int x, int y, int width, int height) - { - // Adds the specified region to the dirty region list if the component is showing. - //System.out.println("JC: repaint"); - super.repaint(tm, x,y,width,height); - } - - public void repaint(Rectangle r) - { - // Adds the specified region to the dirty region list if the component is showing. - repaint((long)0, - (int)r.getX(), - (int)r.getY(), - (int)r.getWidth(), - (int)r.getHeight()); - } - - public boolean requestDefaultFocus() - { - // Request the focus for the component that should have the focus by default. - return false; - } - - public void requestFocus() - { - // Set focus on the receiving component if isRequestFocusEnabled returns true - super.requestFocus(); - } - - public void resetKeyboardActions() - { - // Unregister all keyboard actions - } - - public void reshape(int x, int y, int w, int h) - { - /// Moves and resizes this component. - super.reshape(x,y,w,h); - } - - public void revalidate() - { - // Support for deferred automatic layout. - if (getParent() == null) - invalidate(); - } - - public void scrollRectToVisible(Rectangle aRect) - { - // Forwards the scrollRectToVisible() message to the JComponent's parent. - } - - public void setAlignmentX(float alignmentX) - { - // Set the the vertical alignment. - } - - public void setAlignmentY(float alignmentY) - { - // Set the the horizontal alignment. - } - - public void setAutoscrolls(boolean autoscrolls) - { - // If true this component will automatically scroll its contents when dragged, if contained in a component that supports scrolling, such as JViewport - } - - public void setDebugGraphicsOptions(int debugOptions) - { - // Enables or disables diagnostic information about every graphics operation performed within the component or one of its children. - } - - public void setDoubleBuffered(boolean aFlag) - { - use_double_buffer = aFlag; - } - - public void setEnabled(boolean enabled) - { - // Sets whether or not this component is enabled. - super.setEnabled(enabled); - repaint(); - } - - public void setFont(Font font) - { - super.setFont(font); - revalidate(); - repaint(); - } - - public void setBackground(Color bg) - { - super.setBackground(bg); - revalidate(); - repaint(); - } - public void setForeground(Color fg) - { - super.setForeground(fg); - revalidate(); - repaint(); - } - - public void setMaximumSize(Dimension maximumSize) - { max = maximumSize; } - - public void setMinimumSize(Dimension minimumSize) - { min = minimumSize; } - - public void setPreferredSize(Dimension preferredSize) - { pref = preferredSize; } - - public void setNextFocusableComponent(Component aComponent) - { - // Specifies the next component to get the focus after this one, for example, when the tab key is pressed. - } - - public void setOpaque(boolean isOpaque) - { - opaque = isOpaque; - revalidate(); - repaint(); - } - - - public void setRequestFocusEnabled(boolean aFlag) - { - } - - - public void setVisible(boolean aFlag) - { - // Makes the component visible or invisible. - - super.setVisible(aFlag); - if (getParent() != null) - { - Rectangle dims = getBounds(); - getParent().repaint((int)dims.getX(), - (int)dims.getY(), - (int)dims.getWidth(), - (int)dims.getHeight()); - } - } - - public void unregisterKeyboardAction(KeyStroke aKeyStroke) - { - // Unregister a keyboard action. - } - - - public void update(Graphics g) - { - paint(g); - } - - public String getUIClassID() - { - /// Return the UIDefaults key used to look up the name of the swing. - return "ComponentUI"; - } - - protected void setUI(ComponentUI newUI) - { - if (ui != null) - { - ui.uninstallUI(this); - } - - // Set the look and feel delegate for this component. - ui = newUI; - - if (ui != null) - { - ui.installUI(this); - } - - revalidate(); - repaint(); - } - - public void updateUI() - { - // Resets the UI property to a value from the current look and feel. - System.out.println("update UI not overwritten in class: " + this); - } + return (VetoableChangeListener[]) getListeners(VetoableChangeListener.class); + } + + /** + * Return all <code>PropertyChangeListener</code> objects registered to listen + * for a particular property. + * + * @param property The property to return the listeners of + * + * @return The set of <code>PropertyChangeListener</code> objects in + * {@link #changeSupport} registered to listen on the specified propert + */ + public PropertyChangeListener[] getPropertyChangeListeners(String property) + { + return changeSupport == null ? new PropertyChangeListener[0] + : changeSupport.getPropertyChangeListeners(property); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with <code>boolean</code> values. + */ + public void firePropertyChange(String propertyName, boolean oldValue, + boolean newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Boolean(oldValue), + new Boolean(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with <code>byte</code> values. + */ + public void firePropertyChange(String propertyName, byte oldValue, + byte newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Byte(oldValue), + new Byte(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with <code>char</code> values. + */ + public void firePropertyChange(String propertyName, char oldValue, + char newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Character(oldValue), + new Character(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with <code>double</code> values. + */ + public void firePropertyChange(String propertyName, double oldValue, + double newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Double(oldValue), + new Double(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with <code>float</code> values. + */ + public void firePropertyChange(String propertyName, float oldValue, + float newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Float(oldValue), + new Float(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with <code>int</code> values. + */ + public void firePropertyChange(String propertyName, int oldValue, + int newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Integer(oldValue), + new Integer(newValue)); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with <code>long</code> values. + */ + public void firePropertyChange(String propertyName, long oldValue, + long newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Long(oldValue), + new Long(newValue)); + } + + /** + * Call {@link PropertyChangeListener#propertyChange} on all listeners + * registered to listen to a given property. Any method which changes + * the specified property of this component should call this method. + * + * @param propertyName The property which changed + * @param oldValue The old value of the property + * @param newValue The new value of the property + * + * @see #changeSupport + * @see #addPropertyChangeListener + * @see #removePropertyChangeListener + */ + protected void firePropertyChange(String propertyName, Object oldValue, + Object newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * A variant of {@link #firePropertyChange(String,Object,Object)} + * for properties with <code>short</code> values. + */ + public void firePropertyChange(String propertyName, short oldValue, + short newValue) + { + if (changeSupport != null) + changeSupport.firePropertyChange(propertyName, new Short(oldValue), + new Short(newValue)); + } + + /** + * Call {@link VetoableChangeListener#vetoableChange} on all listeners + * registered to listen to a given property. Any method which changes + * the specified property of this component should call this method. + * + * @param propertyName The property which changed + * @param oldValue The old value of the property + * @param newValue The new value of the property + * + * @throws PropertyVetoException if the change was vetoed by a listener + * + * @see addVetoableChangeListener + * @see removeVetoableChangeListener + */ + protected void fireVetoableChange(String propertyName, Object oldValue, + Object newValue) + throws PropertyVetoException + { + // Support for reporting constrained property changes. + } + + /** + * Get the value of the accessibleContext property for this component. + * + * @return the current value of the property + */ + public AccessibleContext getAccessibleContext() + { + return null; + } + + /** + * Get the ActionListener (typically an {@link Action} object) which is + * associated with a particular keystroke. + * + * @param aKeyStroke The keystroke to retrieve the action of + * + * @return The action associated with the specified keystroke + */ + public ActionListener getActionForKeyStroke(KeyStroke aKeyStroke) + { + return null; + } + + /** + * Get the value of the {@link #alignmentX} property. + * + * @return The current value of the property. + * + * @see #setAlignmentX + * @see #alignmentY + */ + public float getAlignmentX() + { + return alignmentX; + } + + /** + * Get the value of the {@link #alignmentY} property. + * + * @return The current value of the property. + * + * @see #setAlignmentY + * @see #alignmentX + */ + public float getAlignmentY() + { + return alignmentY; + } + + /** + * Get the current value of the {@link #autoscrolls} property. + * + * @return The current value of the property + */ + public boolean getAutoscrolls() + { + return autoscrolls; + } + + /** + * Set the value of the {@link #border} property, revalidate + * and repaint this component. + * + * @param border The new value of the property + * + * @see #getBorder + */ + public void setBorder(Border border) + { + this.border = border; + revalidate(); + repaint(); + } + + /** + * Get the value of the {@link #border} property. + * + * @return The property's current value + * + * @see #setBorder + */ + public Border getBorder() + { + return border; + } + + /** + * Get the component's current bounding box. If a rectangle is provided, + * use this as the return value (adjusting its fields in place); + * otherwise (of <code>null</code> is provided) return a new {@link + * Rectangle}. + * + * @param rv Optional return value to use + * + * @return A rectangle bounding the component + */ + public Rectangle getBounds(Rectangle rv) + { + if (rv == null) + return new Rectangle(getX(), getY(), getWidth(), getHeight()); + else + { + rv.setBounds(getX(), getY(), getWidth(), getHeight()); + return rv; + } + } + + /** + * Prepares a graphics context for painting this object. If {@link + * #debugGraphicsOptions} is not equal to {@link + * DebugGraphics#NONE_OPTION}, produce a new {@link DebugGraphics} object + * wrapping the parameter. Otherwise configure the parameter with this + * component's foreground color and font. + * + * @param g The graphics context to wrap or configure + * + * @return A graphics context to paint this object with + * + * @see #debugGraphicsOptions + * @see #paint + */ + protected Graphics getComponentGraphics(Graphics g) + { + g.setFont(this.getFont()); + g.setColor(this.getForeground()); + return g; + } + + /** + * Return the condition that determines whether a registered action + * occurs in response to the specified keystroke. + * + * @param aKeyStroke The keystroke to return the condition of + * + * @return One of the values {@link #UNDEFINED_CONDITION}, {@link + * #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or {@link + * #WHEN_IN_FOCUSED_WINDOW} + * + * @see #registerKeyboardAction + * @see #unregisterKeyboardAction + * @see #resetKeyboardActiond + */ + public int getConditionForKeyStroke(KeyStroke aKeyStroke) + { + return UNDEFINED_CONDITION; + } + + /** + * Get the value of the {@link #debugGraphicsOptions} property. + * + * @return The current value of the property. + * + * @see #setDebugGraphicsOptions + * @see #debugGraphicsOptions + */ + public int getDebugGraphicsOptions() + { + return 0; + } + + /** + * Get the component's insets, which are calculated from + * the {@link #border} property. If the border is <code>null</code>, + * calls {@link Container#getInsets}. + * + * @return The component's current insets + */ + public Insets getInsets() + { + if (border == null) + return super.getInsets(); + return getBorder().getBorderInsets(this); + } + + /** + * Get the component's insets, which are calculated from the {@link + * #border} property. If the border is <code>null</code>, calls {@link + * Container#getInsets}. The passed-in {@link Insets} value will be + * used as the return value, if possible. + * + * @param insets Return value object to reuse, if possible + * + * @return The component's current insets + */ + public Insets getInsets(Insets insets) + { + Insets t = getInsets(); + + if (insets == null) + return t; + + insets.left = t.left; + insets.right = t.right; + insets.top = t.top; + insets.bottom = t.bottom; + return insets; + } + + /** + * Get the component's location. The passed-in {@link Point} value + * will be used as the return value, if possible. + * + * @param rv Return value object to reuse, if possible + * + * @return The component's current location + */ + public Point getLocation(Point rv) + { + if (rv == null) + return new Point(getX(), getY()); + + rv.setLocation(getX(), getY()); + return rv; + } + + /** + * Get the component's maximum size. If the {@link #maximumSize} property + * has been explicitly set, it is returned. If the {@link #maximumSize} + * property has not been set but the {@link ui} property has been, the + * result of {@link ComponentUI#getMaximumSize} is returned. If neither + * property has been set, the result of {@link Container#getMaximumSize} + * is returned. + * + * @return The maximum size of the component + * + * @see #maximumSize + * @see #setMaximumSize + */ + public Dimension getMaximumSize() + { + if (maximumSize != null) + return maximumSize; + + if (ui != null) + { + Dimension s = ui.getMaximumSize(this); + if (s != null) + return s; + } + + Dimension p = super.getMaximumSize(); + return p; + } + + /** + * Get the component's minimum size. If the {@link #minimumSize} property + * has been explicitly set, it is returned. If the {@link #minimumSize} + * property has not been set but the {@link ui} property has been, the + * result of {@link ComponentUI#getMinimumSize} is returned. If neither + * property has been set, the result of {@link Container#getMinimumSize} + * is returned. + * + * @return The minimum size of the component + * + * @see #minimumSize + * @see #setMinimumSize + */ + public Dimension getMinimumSize() + { + if (minimumSize != null) + return minimumSize; + + if (ui != null) + { + Dimension s = ui.getMinimumSize(this); + if (s != null) + return s; + } + + Dimension p = super.getMinimumSize(); + return p; + } + + /** + * Get the component's preferred size. If the {@link #preferredSize} + * property has been explicitly set, it is returned. If the {@link + * #preferredSize} property has not been set but the {@link ui} property + * has been, the result of {@link ComponentUI#getPreferredSize} is + * returned. If neither property has been set, the result of {@link + * Container#getPreferredSize} is returned. + * + * @return The preferred size of the component + * + * @see #preferredSize + * @see #setPreferredSize + */ + public Dimension getPreferredSize() + { + if (preferredSize != null) + return preferredSize; + + if (ui != null) + { + Dimension s = ui.getPreferredSize(this); + if (s != null) + return s; + } + Dimension p = super.getPreferredSize(); + return p; + } + + /** + * Return the value of the {@link #nextFocusableComponent} property. + * + * @deprecated See {@link java.awt.FocusTraversalPolicy} + * + * @return The current value of the property, or <code>null</code> + * if none has been set. + */ + public Component getNextFocusableComponent() + { + return null; + } + + /** + * Return the set of {@link KeyStroke} objects which are registered + * to initiate actions on this component. + * + * @return An array of the registered keystrokes + */ + public KeyStroke[] getRegisteredKeyStrokes() + { + return null; + } + + /** + * Returns the first ancestor of this component which is a {@link JRootPane}. + * Equivalent to calling <code>SwingUtilities.getRootPane(this);</code>. + * + * @return An ancestral JRootPane, or <code>null</code> if none exists. + */ + public JRootPane getRootPane() + { + JRootPane p = SwingUtilities.getRootPane(this); + return p; + } + + /** + * Get the component's size. The passed-in {@link Dimension} value + * will be used as the return value, if possible. + * + * @param rv Return value object to reuse, if possible + * + * @return The component's current size + */ + public Dimension getSize(Dimension rv) + { + if (rv == null) + return new Dimension(getWidth(), getHeight()); + else + { + rv.setSize(getWidth(), getHeight()); + return rv; + } + } + + /** + * Return the {@link #toolTip} property of this component, creating it and + * setting it if it is currently <code>null</code>. This method can be + * overridden in subclasses which wish to control the exact form of + * tooltip created. + * + * @return The current toolTip + */ + public JToolTip createToolTip() + { + if (toolTip == null) + toolTip = new JToolTip(toolTipText); + return toolTip; + } + + /** + * Return the location at which the {@link #toolTip} property should be + * displayed, when triggered by a particular mouse event. + * + * @param event The event the tooltip is being presented in response to + * + * @return The point at which to display a tooltip, or <code>null</code> + * if swing is to choose a default location. + */ + public Point getToolTipLocation(MouseEvent event) + { + return null; + } + + /** + * Set the value of the {@link #toolTipText} property. + * + * @param text The new property value + * + * @see #getToolTipText + */ + public void setToolTipText(String text) + { + toolTipText = text; + } + /** + * Get the value of the {@link #toolTipText} property. + * + * @return The current property value + * + * @see #setToolTipText + */ + public String getToolTipText() + { + return toolTipText; + } + + /** + * Get the value of the {@link #toolTipText} property, in response to a + * particular mouse event. + * + * @param event The mouse event which triggered the tooltip + * + * @return The current property value + * + * @see #setToolTipText + */ + public String getToolTipText(MouseEvent event) + { + return toolTipText; + } + + /** + * Return the top level ancestral container (usually a {@link + * java.awt.Window} or {@link java.awt.Applet}) which this component is + * contained within, or <code>null</code> if no ancestors exist. + * + * @return The top level container, if it exists + */ + public Container getTopLevelAncestor() + { + Container c = getParent(); + for (Container peek = c; peek != null; peek = peek.getParent()) + c = peek; + return c; + } + + /** + * Compute the component's visible rectangle, which is defined + * recursively as either the component's bounds, if it has no parent, or + * the intersection of the component's bounds with the visible rectangle + * of its parent. + * + * @param rect The return value slot to place the visible rectangle in + */ + public void computeVisibleRect(Rectangle rect) + { + Component c = getParent(); + if (c != null && c instanceof JComponent) + { + ((JComponent) c).computeVisibleRect(rect); + rect.translate(-getX(), -getY()); + Rectangle2D.intersect(rect, + new Rectangle(0, 0, getWidth(), getHeight()), + rect); + } + else + rect.setRect(0, 0, getWidth(), getHeight()); + } + + /** + * Return the component's visible rectangle in a new {@link Rectangle}, + * rather than via a return slot. + * + * @return The component's visible rectangle + * + * @see #computeVisibleRect(Rectangle) + */ + public Rectangle getVisibleRect() + { + Rectangle r = new Rectangle(); + computeVisibleRect(r); + return r; + } + + /** + * <p>Requests that this component receive input focus, giving window + * focus to the top level ancestor of this component. Only works on + * displayable, focusable, visible components.</p> + * + * <p>This method should not be called by clients; it is intended for + * focus implementations. Use {@link Component#requestFocus} instead.</p> + * + * @see {@link Component#requestFocus} + */ + public void grabFocus() + { + } + + /** + * Get the value of the {@link #doubleBuffered} property. + * + * @return The property's current value + */ + public boolean isDoubleBuffered() + { + return doubleBuffered; + } + + /** + * Return <code>true</code> if the provided component has no native peer; + * in other words, if it is a "lightweight component". + * + * @param c The component to test for lightweight-ness + * + * @return Whether or not the component is lightweight + */ + public static boolean isLightweightComponent(Component c) + { + return c.getPeer() instanceof LightweightPeer; + } + + /** + * Return <code>true<code> if you wish this component to manage its own + * focus. In particular: if you want this component to be sent + * <code>TAB</code> and <code>SHIFT+TAB</code> key events, and to not + * have its children considered as focus transfer targets. If + * <code>true</code>, focus traversal around this component changes to + * <code>CTRL+TAB</code> and <code>CTRL+SHIFT+TAB</code>. + * + * @return <code>true</code> if you want this component to manage its own + * focus, otherwise (by default) <code>false</code> + * + * @deprecated Use {@link Component.setFocusTraversalKeys(int,Set)} and + * {@link Container.setFocusCycleRoot(boolean)} instead + */ + public boolean isManagingFocus() + { + return false; + } + + /** + * Return the current value of the {@link opaque} property. + * + * @return The current property value + */ + public boolean isOpaque() + { + return opaque; + } + + /** + * Return <code>true</code> if the component can guarantee that none of its + * children will overlap in Z-order. This is a hint to the painting system. + * The default is to return <code>true</code>, but some components such as + * {@link JLayeredPane} should override this to return <code>false</code>. + * + * @return Whether the component tiles its children + */ + public boolean isOptimizedDrawingEnabled() + { + return true; + } + + /** + * Return <code>true</code> if this component is currently painting a tile. + * + * @return Whether the component is painting a tile + */ + public boolean isPaintingTile() + { + return false; + } + + /** + * Get the value of the {@link #requestFocusEnabled} property. + * + * @return The current value of the property + */ + public boolean isRequestFocusEnabled() + { + return requestFocusEnabled; + } + + /** + * Return <code>true</code> if this component is a validation root; this + * will cause calls to {@link #invalidate} in this component's children + * to be "captured" at this component, and not propagate to its parents. + * For most components this should return <code>false</code>, but some + * components such as {@link JViewPort} will want to return + * <code>true</code>. + * + * @return Whether this component is a validation root + */ + public boolean isValidateRoot() + { + return false; + } + + /** + * <p>Paint the component. This is a delicate process, and should only be + * called from the repaint thread, under control of the {@link + * RepaintManager}. Client code should usually call {@link #repaint} to + * trigger painting.</p> + * + * <p>This method will acquire a double buffer from the {@link + * RepaintManager} if the component's {@link #doubleBuffered} property is + * <code>true</code> and the <code>paint</code> call is the + * <em>first</em> recursive <code>paint</code> call inside swing.</p> + * + * <p>The method will also modify the provided {@link Graphics} context + * via the {@link #getComponentGraphics} method. If you want to customize + * the graphics object used for painting, you should override that method + * rather than <code>paint</code>.</p> + * + * <p>The body of the <code>paint</code> call involves calling {@link + * #paintComponent}, {@link #paintBorder}, and {@link #paintChildren} in + * order. If you want to customize painting behavior, you should override + * one of these methods rather than <code>paint</code>.</p> + * + * <p>For more details on the painting sequence, see <a + * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">this + * article</a>.</p> + * + * @param g The graphics context to paint with + * + * @see #paintImmediately + */ + public void paint(Graphics g) + { + Graphics g2 = g; + Image doubleBuffer = null; + RepaintManager rm = RepaintManager.currentManager(this); + + if (isDoubleBuffered() + && (rm.isDoubleBufferingEnabled()) + && (! Thread.holdsLock(paintLock))) + { + doubleBuffer = rm.getOffscreenBuffer(this, getWidth(), getHeight()); + } + + synchronized (paintLock) + { + if (doubleBuffer != null) + { + g2 = doubleBuffer.getGraphics(); + g2.setClip(g.getClipBounds()); + } + + g2 = getComponentGraphics(g2); + paintComponent(g2); + paintBorder(g2); + paintChildren(g2); + + if (doubleBuffer != null) + g.drawImage(doubleBuffer, 0, 0, (ImageObserver) null); + } + } + + /** + * Paint the component's border. This usually means calling {@link + * Border#paintBorder} on the {@link #border} property, if it is + * non-<code>null</code>. You may override this if you wish to customize + * border painting behavior. The border is painted after the component's + * body, but before the component's children. + * + * @param g The graphics context with which to paint the border + * + * @see #paint + * @see #paintChildren + * @see #paintComponent + */ + protected void paintBorder(Graphics g) + { + if (getBorder() != null) + getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight()); + } + + /** + * Paint the component's children. This usually means calling {@link + * Container#paint}, which recursively calls {@link #paint} on any of the + * component's children, with appropriate changes to coordinate space and + * clipping region. You may override this if you wish to customize + * children painting behavior. The children are painted after the + * component's body and border. + * + * @param g The graphics context with which to paint the children + * + * @see #paint + * @see #paintBorder + * @see #paintComponent + */ + protected void paintChildren(Graphics g) + { + super.paint(g); + } + + /** + * Paint the component's body. This usually means calling {@link + * ComponentUI#update} on the {@link #ui} property of the component, if + * it is non-<code>null</code>. You may override this if you wish to + * customize the component's body-painting behavior. The component's body + * is painted first, before the border and children. + * + * @param g The graphics context with which to paint the body + * + * @see #paint + * @see #paintBorder + * @see #paintChildren + */ + protected void paintComponent(Graphics g) + { + if (ui != null) + ui.update(g, this); + } + + /** + * A variant of {@link #paintImmediately(Rectangle)} which takes + * integer parameters. + * + * @param x The left x coordinate of the dirty region + * @param y The top y coordinate of the dirty region + * @param w The width of the dirty region + * @param h The height of the dirty region + */ + public void paintImmediately(int x, int y, int w, int h) + { + paintImmediately(new Rectangle(x, y, w, h)); + } + + /** + * Transform the provided dirty rectangle for this component into the + * appropriate ancestral {@link JRootPane} and call {@link #paint} on + * that root pane. This method is called from the {@link RepaintManager} + * and should always be called within the painting thread. + * + * @param r The dirty rectangle to paint + */ + public void paintImmediately(Rectangle r) + { + Component root = this.getRootPane(); + if (root == null || ! root.isShowing()) + return; + Graphics g = root.getGraphics(); + if (g == null) + return; + + Rectangle clip = SwingUtilities.convertRectangle(this, r, root); + g.setClip(clip); + root.paint(g); + g.dispose(); + } + + /** + * Return a string representation for this component, for use in + * debugging. + * + * @return A string describing this component. + */ + protected String paramString() + { + return "JComponent"; + } + + /** + * A variant of {@link + * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which + * provides <code>null</code> for the command name. + */ + public void registerKeyboardAction(ActionListener act, + KeyStroke stroke, + int cond) + { + registerKeyboardAction(act, null, stroke, cond); + } + + /** + * An obsolete method to register a keyboard action on this component. + * You should use <code>getInputMap</code> and <code>getActionMap</code> + * to fetch mapping tables from keystrokes to commands, and commands to + * actions, respectively, and modify those mappings directly. + * + * @param anAction The action to be registered + * @param aCommand The command to deliver in the delivered {@link + * java.awt.ActionEvent} + * @param aKeyStroke The keystroke to register on + * @param aCondition One of the values {@link #UNDEFINED_CONDITION}, + * {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or + * {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must + * be met for the action to be fired + * + * @see #unregisterKeyboardAction + * @see #getConditionForKeystroke + * @see #resetKeyboardActiond + */ + public void registerKeyboardAction(ActionListener act, + String cmd, + KeyStroke stroke, + int cond) + { + } + + /** + * Remove a keyboard action registry. + * + * @param stroke The keystroke to unregister + * + * @see #registerKeyboardAction + * @see #getConditionForKeystroke + * @see #resetKeyboardActiond + */ + public void unregisterKeyboardAction(KeyStroke aKeyStroke) + { + } + + + /** + * Reset all keyboard action registries. + * + * @see #registerKeyboardAction + * @see #unregisterKeyboardAction + * @see #getConditionForKeystroke + */ + public void resetKeyboardActions() + { + } + + + /** + * Mark the described region of this component as dirty in the current + * {@link RepaintManager}. This will queue an asynchronous repaint using + * the system painting thread in the near future. + * + * @param tm ignored + * @param x coordinate of the region to mark as dirty + * @param y coordinate of the region to mark as dirty + * @param width dimension of the region to mark as dirty + * @param height dimension of the region to mark as dirty + */ + public void repaint(long tm, int x, int y, int width, int height) + { + Rectangle dirty = new Rectangle(x, y, width, height); + Rectangle vis = getVisibleRect(); + dirty = dirty.intersection(vis); + RepaintManager.currentManager(this).addDirtyRegion(this, dirty.x, dirty.y, + dirty.width, + dirty.height); + } + + /** + * Mark the described region of this component as dirty in the current + * {@link RepaintManager}. This will queue an asynchronous repaint using + * the system painting thread in the near future. + * + * @param r The rectangle to mark as dirty + */ + public void repaint(Rectangle r) + { + repaint((long) 0, (int) r.getX(), (int) r.getY(), (int) r.getWidth(), + (int) r.getHeight()); + } + + /** + * Request focus on the default component of this component's {@link + * FocusTraversalPolicy}. + * + * @return The result of {@link #requestFocus} + * + * @deprecated Use {@link #requestFocus()} on the default component provided from + * the {@link FocusTraversalPolicy} instead. + */ + public boolean requestDefaultFocus() + { + return false; + } + + /** + * Queue a an invalidation and revalidation of this component, using + * {@link RepaintManager#addInvalidComponent}. + */ + public void revalidate() + { + RepaintManager.currentManager(this).addInvalidComponent(this); + } + + /** + * Calls <code>scrollRectToVisible</code> on the component's parent. + * Components which can service this call should override. + * + * @param r The rectangle to make visible + */ + public void scrollRectToVisible(Rectangle r) + { + Component p = getParent(); + if (p != null && p instanceof JComponent) + ((JComponent) p).scrollRectToVisible(r); + } + + /** + * Set the value of the {@link #alignmentX} property. + * + * @param a The new value of the property + */ + public void setAlignmentX(float a) + { + alignmentX = a; + } + + /** + * Set the value of the {@link #alignmentY} property. + * + * @param a The new value of the property + */ + public void setAlignmentY(float a) + { + alignmentY = a; + } + + /** + * Set the value of the {@link #autoscrolls} property. + * + * @param a The new value of the property + */ + public void setAutoscrolls(boolean a) + { + autoscrolls = a; + } + + /** + * Set the value of the {@link #debugGraphicsOptions} property. + * + * @param debugOptions The new value of the property + */ + public void setDebugGraphicsOptions(int debugOptions) + { + debugGraphicsOptions = debugOptions; + } + + /** + * Set the value of the {@link #doubleBuffered} property. + * + * @param db The new value of the property + */ + public void setDoubleBuffered(boolean db) + { + doubleBuffered = db; + } + + /** + * Set the value of the {@link #enabled} property, revalidate + * and repaint this component. + * + * @param e The new value of the property + */ + public void setEnabled(boolean e) + { + super.setEnabled(e); + revalidate(); + repaint(); + } + + /** + * Set the value of the {@link #font} property, revalidate + * and repaint this component. + * + * @param f The new value of the property + */ + public void setFont(Font f) + { + super.setFont(f); + revalidate(); + repaint(); + } + + /** + * Set the value of the {@link #background} property, revalidate + * and repaint this component. + * + * @param bg The new value of the property + */ + public void setBackground(Color bg) + { + super.setBackground(bg); + revalidate(); + repaint(); + } + + /** + * Set the value of the {@link #foreground} property, revalidate + * and repaint this component. + * + * @param fg The new value of the property + */ + public void setForeground(Color fg) + { + super.setForeground(fg); + revalidate(); + repaint(); + } + + /** + * Set the value of the {@link #maximumSize} property, revalidate + * and repaint this component. + * + * @param max The new value of the property + */ + public void setMaximumSize(Dimension max) + { + maximumSize = max; + revalidate(); + repaint(); + } + + /** + * Set the value of the {@link #minimumSize} property, revalidate + * and repaint this component. + * + * @param min The new value of the property + */ + public void setMinimumSize(Dimension min) + { + minimumSize = min; + revalidate(); + repaint(); + } + + /** + * Set the value of the {@link #preferredSize} property, revalidate + * and repaint this component. + * + * @param pref The new value of the property + */ + public void setPreferredSize(Dimension pref) + { + preferredSize = pref; + } + + /** + * Set the specified component to be the next component in the + * focus cycle, overriding the {@link FocusTraversalPolicy} for + * this component. + * + * @param aComponent The component to set as the next focusable + * + * @deprecated Use FocusTraversalPolicy instead + */ + public void setNextFocusableComponent(Component aComponent) + { + } + + /** + * Set the value of the {@link #requestFocusEnabled} property. + * + * @param e The new value of the property + */ + public void setRequestFocusEnabled(boolean e) + { + requestFocusEnabled = e; + } + + /** + * Set the value of the {@link #opaque} property, revalidate and repaint + * this component. + * + * @param isOpaque The new value of the property + * + * @see ComponentUI#update + */ + public void setOpaque(boolean isOpaque) + { + opaque = isOpaque; + revalidate(); + repaint(); + } + + /** + * Set the value of the visible property, and revalidate / repaint the + * component. + * + * @param v The new value of the property + */ + public void setVisible(boolean v) + { + super.setVisible(v); + revalidate(); + repaint(); + } + + /** + * Call {@link paint}. + * + * @param g The graphics context to paint into + */ + public void update(Graphics g) + { + paint(g); + } + + /** + * Get the value of the UIClassID property. This property should be a key + * in the {@link UIDefaults} table managed by {@link UIManager}, the + * value of which is the name of a class to load for the component's + * {@link ui} property. + * + * @return A "symbolic" name which will map to a class to use for the + * component's UI, such as <code>"ComponentUI"</code> + * + * @see #setUI + * @see #updateUI + */ + public String getUIClassID() + { + return "ComponentUI"; + } + + /** + * Install a new UI delegate as the component's {@link ui} property. In + * the process, this will call {@link ComponentUI.uninstallUI} on any + * existing value for the {@link ui} property, and {@link + * ComponentUI.installUI} on the new UI delegate. + * + * @param newUI The new UI delegate to install + * + * @see #updateUI + * @see #getUIClassID + */ + protected void setUI(ComponentUI newUI) + { + if (ui != null) + ui.uninstallUI(this); + + ui = newUI; + + if (ui != null) + ui.installUI(this); + + revalidate(); + repaint(); + } + + /** + * This method should be overridden in subclasses. In JComponent, the + * method does nothing. In subclasses, it should a UI delegate + * (corresponding to the symbolic name returned from {@link + * getUIClassID}) from the {@link UIManager}, and calls {@link setUI} + * with the new delegate. + */ + public void updateUI() + { + System.out.println("update UI not overwritten in class: " + this); + } + + public static Locale getDefaultLocale() + { + return defaultLocale; + } + + public static void setDefaultLocale(Locale l) + { + defaultLocale = l; + } } diff --git a/libjava/javax/swing/JDialog.java b/libjava/javax/swing/JDialog.java index 8d43b761d96..b9f547e5542 100644 --- a/libjava/javax/swing/JDialog.java +++ b/libjava/javax/swing/JDialog.java @@ -35,7 +35,6 @@ this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ - package javax.swing; import java.awt.BorderLayout; @@ -45,251 +44,518 @@ import java.awt.Dialog; import java.awt.Dimension; import java.awt.Frame; import java.awt.Graphics; +import java.awt.GraphicsConfiguration; import java.awt.LayoutManager; import java.awt.event.KeyEvent; import java.awt.event.WindowEvent; +import java.awt.IllegalComponentStateException; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; + /** - * Unlike JComponent derivatives, JDialog inherits from - * java.awt.Dialog. But also lets a look-and-feel component to its work. + * Unlike JComponent derivatives, JDialog inherits from java.awt.Dialog. But + * also lets a look-and-feel component to its work. * - * @author Ronald Veldema (rveldema@cs.vu.nl) + * @author Ronald Veldema (rveldema_AT_cs.vu.nl) */ -public class JDialog extends Dialog implements Accessible, WindowConstants +public class JDialog extends Dialog implements Accessible, WindowConstants, + RootPaneContainer { - protected AccessibleContext accessibleContext; - - private int close_action = HIDE_ON_CLOSE; - - /*************************************************** - * - * - * constructors - * - * - *************/ - - public JDialog(Frame owner) - { - this(owner, "dialog"); - } - - public JDialog(Frame owner, - String s) - { - this(owner, s, true); - } - - public JDialog(Frame owner, - String s, - boolean modeld) - { - super(owner, s, modeld); - } - - public JDialog(Frame owner, - // String s, - boolean modeld) - { - super(owner, "JDialog", modeld); - } + + /** DOCUMENT ME! */ + protected AccessibleContext accessibleContext; + + /** The single RootPane in the Dialog. */ + protected JRootPane rootPane; + + /** Whether checking is enabled on the RootPane */ + protected boolean rootPaneCheckingEnabled = true; + + /** The default action taken when closed. */ + private int close_action = HIDE_ON_CLOSE; + + /** Whether JDialogs are decorated by the L&F. */ + private static boolean decorated = false; + + /** + * Creates a new non-modal JDialog with no title + * using a shared Frame as the owner. + */ + public JDialog() + { + this(SwingUtilities.getOwnerFrame(), "", false, null); + } + + /** + * Creates a new non-modal JDialog with no title + * using the given owner. + * + * @param owner The owner of the JDialog. + */ public JDialog(Dialog owner) { - this(owner, "dialog"); - } - - public JDialog(Dialog owner, - String s) - { - this(owner, s, true); - } - - public JDialog(Dialog owner, - String s, - boolean modeld) - { - super(owner, s, modeld); - } - - - /*************************************************** - * - * - * methods, this part is shared with JDialog, JFrame - * - * - *************/ + this(owner, "", false, null); + } - - private boolean checking; - protected JRootPane rootPane; + /** + * Creates a new JDialog with no title using the + * given modal setting and owner. + * + * @param owner The owner of the JDialog. + * @param modal Whether the JDialog is modal. + */ + public JDialog(Dialog owner, boolean modal) + { + this(owner, "", modal, null); + } - void setLocationRelativeTo(Component c) - { - } + /** + * Creates a new non-modal JDialog using the + * given title and owner. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + */ + public JDialog(Dialog owner, String title) + { + this(owner, title, false, null); + } + /** + * Creates a new JDialog using the given modal + * settings, title, and owner. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + * @param modal Whether the JDialog is modal. + */ + public JDialog(Dialog owner, String title, boolean modal) + { + this(owner, title, modal, null); + } - protected void frameInit() - { - super.setLayout(new BorderLayout(1, 1)); - getRootPane(); // will do set/create - } - + /** + * Creates a new JDialog using the given modal + * settings, title, owner and graphics configuration. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + * @param modal Whether the JDialog is modal. + * @param gc The Graphics Configuration to use. + */ + public JDialog(Dialog owner, String title, boolean modal, + GraphicsConfiguration gc) + { + super(owner, title, modal, gc); + dialogInit(); + } + + /** + * Creates a new non-modal JDialog with no title + * using the given owner. + * + * @param owner The owner of the JDialog. + */ + public JDialog(Frame owner) + { + this(owner, "", false, null); + } + + /** + * Creates a new JDialog with no title using the + * given modal setting and owner. + * + * @param owner The owner of the JDialog. + * @param modal Whether the JDialog is modal. + */ + public JDialog(Frame owner, boolean modal) + { + this(owner, "", modal, null); + } + + /** + * Creates a new non-modal JDialog using the + * given title and owner. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + */ + public JDialog(Frame owner, String title) + { + this(owner, title, false, null); + } + + /** + * Creates a new JDialog using the given modal + * settings, title, and owner. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + * @param modal Whether the JDialog is modal. + */ + public JDialog(Frame owner, String title, boolean modal) + { + this(owner, title, modal, null); + } + + /** + * Creates a new JDialog using the given modal + * settings, title, owner and graphics configuration. + * + * @param owner The owner of the JDialog. + * @param title The title of the JDialog. + * @param modal Whether the JDialog is modal. + * @param gc The Graphics Configuration to use. + */ + public JDialog(Frame owner, String title, boolean modal, + GraphicsConfiguration gc) + { + super((owner == null) ? SwingUtilities.getOwnerFrame() : owner, + title, modal, gc); + dialogInit(); + } + + /** + * This method is called to initialize the + * JDialog. It sets the layout used, the locale, + * and creates the RootPane. + */ + protected void dialogInit() + { + // FIXME: Do a check on GraphicsEnvironment.isHeadless() + setRootPaneCheckingEnabled(false); + setLocale(JComponent.getDefaultLocale()); + getRootPane(); // will do set/create + setRootPaneCheckingEnabled(true); + invalidate(); + + } + + /** + * This method returns whether JDialogs will have their + * window decorations provided by the Look and Feel. + * + * @return Whether the window decorations are L&F provided. + */ + public static boolean isDefaultLookAndFeelDecorated() + { + return decorated; + } + + /** + * This method sets whether JDialogs will have their + * window decorations provided by the Look and Feel. + * + * @param defaultLookAndFeelDecorated Whether the window + * decorations are L&F provided. + */ + public static void setDefaultLookAndFeelDecorated(boolean defaultLookAndFeelDecorated) + { + decorated = defaultLookAndFeelDecorated; + } + + /** + * This method returns the preferred size of + * the JDialog. + * + * @return The preferred size. + */ public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); return d; } - JMenuBar getJMenuBar() - { return getRootPane().getJMenuBar(); } - - void setJMenuBar(JMenuBar menubar) - { getRootPane().setJMenuBar(menubar); } - + /** + * This method returns the JMenuBar used + * in this JDialog. + * + * @return The JMenuBar in the JDialog. + */ + public JMenuBar getJMenuBar() + { + return getRootPane().getJMenuBar(); + } - public void setLayout(LayoutManager manager) - { super.setLayout(manager); } + /** + * This method sets the JMenuBar used + * in this JDialog. + * + * @param menubar The JMenuBar to use. + */ + public void setJMenuBar(JMenuBar menubar) + { + getRootPane().setJMenuBar(menubar); + } - void setLayeredPane(JLayeredPane layeredPane) - { getRootPane().setLayeredPane(layeredPane); } - - JLayeredPane getLayeredPane() - { return getRootPane().getLayeredPane(); } - - JRootPane getRootPane() - { - if (rootPane == null) - setRootPane(createRootPane()); - return rootPane; - } - - void setRootPane(JRootPane root) - { - if (rootPane != null) - remove(rootPane); - - rootPane = root; - add(rootPane, BorderLayout.CENTER); - } - - JRootPane createRootPane() - { return new JRootPane(); } - - Container getContentPane() - { return getRootPane().getContentPane(); } - - void setContentPane(Container contentPane) - { getRootPane().setContentPane(contentPane); } - - Component getGlassPane() - { return getRootPane().getGlassPane(); } - - void setGlassPane(Component glassPane) - { getRootPane().setGlassPane(glassPane); } + /** + * This method sets the LayoutManager used in the JDialog. + * This method will throw an Error if rootPaneChecking is + * enabled. + * + * @param manager The LayoutManager to use. + */ + public void setLayout(LayoutManager manager) + { + if (isRootPaneCheckingEnabled()) + throw new Error("rootPaneChecking is enabled - cannot set layout."); + super.setLayout(manager); + } - - protected void addImpl(Component comp, Object constraints, int index) - { super.addImpl(comp, constraints, index); } + /** + * This method sets the JLayeredPane used in the JDialog. + * If the given JLayeredPane is null, then this method + * will throw an Error. + * + * @param layeredPane The JLayeredPane to use. + */ + public void setLayeredPane(JLayeredPane layeredPane) + { + if (layeredPane == null) + throw new IllegalComponentStateException("layeredPane cannot be null."); + getRootPane().setLayeredPane(layeredPane); + } + /** + * This method returns the JLayeredPane used with this JDialog. + * + * @return The JLayeredPane used with this JDialog. + */ + public JLayeredPane getLayeredPane() + { + return getRootPane().getLayeredPane(); + } - public void remove(Component comp) - { getContentPane().remove(comp); } - - protected boolean isRootPaneCheckingEnabled() - { return checking; } + /** + * This method returns the JRootPane used with this JDialog. + * + * @return The JRootPane used with this JDialog. + */ + public JRootPane getRootPane() + { + if (rootPane == null) + setRootPane(createRootPane()); + return rootPane; + } + /** + * This method sets the JRootPane used with this JDialog. + * + * @param root The JRootPane to use. + */ + protected void setRootPane(JRootPane root) + { + if (rootPane != null) + remove(rootPane); - protected void setRootPaneCheckingEnabled(boolean enabled) - { checking = enabled; } + rootPane = root; + rootPane.show(); + add(rootPane); + } + /** + * This method creates a new JRootPane. + * + * @return A new JRootPane. + */ + protected JRootPane createRootPane() + { + return new JRootPane(); + } - public void update(Graphics g) - { paint(g); } + /** + * This method returns the ContentPane + * in the JRootPane. + * + * @return The ContentPane in the JRootPane. + */ + public Container getContentPane() + { + return getRootPane().getContentPane(); + } - protected void processKeyEvent(KeyEvent e) - { super.processKeyEvent(e); } + /** + * This method sets the ContentPane to use with this + * JDialog. If the ContentPane given is null, this method + * will throw an exception. + * + * @param contentPane The ContentPane to use with the JDialog. + */ + public void setContentPane(Container contentPane) + { + if (contentPane == null) + throw new IllegalComponentStateException("contentPane cannot be null."); + getRootPane().setContentPane(contentPane); + } - ///////////////////////////////////////////////////////////////////////////////// - + /** + * This method returns the GlassPane for this JDialog. + * + * @return The GlassPane for this JDialog. + */ + public Component getGlassPane() + { + return getRootPane().getGlassPane(); + } + + /** + * This method sets the GlassPane for this JDialog. + * + * @param glassPane The GlassPane for this JDialog. + */ + public void setGlassPane(Component glassPane) + { + getRootPane().setGlassPane(glassPane); + } + + /** + * This method is called when a component is added to the + * the JDialog. Calling this method with rootPaneCheckingEnabled + * will cause an Error to be thrown. + * + * @param comp The component to add. + * @param constraints The constraints. + * @param index The position of the component. + */ + protected void addImpl(Component comp, Object constraints, int index) + { + if (isRootPaneCheckingEnabled()) + throw new Error("rootPaneChecking is enabled - adding components disallowed."); + super.addImpl(comp, constraints, index); + } + + /** + * This method removes a component from the JDialog. + * + * @param comp The component to remove. + */ + public void remove(Component comp) + { + // The path changes if the component == root. + if (comp == rootPane) + super.remove(rootPane); + else + getContentPane().remove(comp); + } - protected void processWindowEvent(WindowEvent e) - { - super.processWindowEvent(e); - switch (e.getID()) + /** + * This method returns whether rootPane checking is enabled. + * + * @return Whether rootPane checking is enabled. + */ + protected boolean isRootPaneCheckingEnabled() + { + return rootPaneCheckingEnabled; + } + + /** + * This method sets whether rootPane checking is enabled. + * + * @param enabled Whether rootPane checking is enabled. + */ + protected void setRootPaneCheckingEnabled(boolean enabled) + { + rootPaneCheckingEnabled = enabled; + } + + /** + * This method simply calls paint and returns. + * + * @param g The Graphics object to paint with. + */ + public void update(Graphics g) + { + paint(g); + } + + + /** + * This method handles window events. This allows the JDialog + * to honour its default close operation. + * + * @param e The WindowEvent. + */ + protected void processWindowEvent(WindowEvent e) + { + // System.out.println("PROCESS_WIN_EV-1: " + e); + super.processWindowEvent(e); + // System.out.println("PROCESS_WIN_EV-2: " + e); + switch (e.getID()) + { + case WindowEvent.WINDOW_CLOSING: + { + switch (getDefaultCloseOperation()) { - case WindowEvent.WINDOW_CLOSING: - { - switch(close_action) - { - case EXIT_ON_CLOSE: - { - System.exit(0); - break; - } - case DISPOSE_ON_CLOSE: - { - dispose(); - break; - } - case HIDE_ON_CLOSE: - { - setVisible(false); - break; - } - case DO_NOTHING_ON_CLOSE: - break; - } - break; - } - - case WindowEvent.WINDOW_CLOSED: - case WindowEvent.WINDOW_OPENED: - case WindowEvent.WINDOW_ICONIFIED: - case WindowEvent.WINDOW_DEICONIFIED: - case WindowEvent.WINDOW_ACTIVATED: - case WindowEvent.WINDOW_DEACTIVATED: + case DISPOSE_ON_CLOSE: + { + dispose(); + break; + } + case HIDE_ON_CLOSE: + { + setVisible(false); break; + } + case DO_NOTHING_ON_CLOSE: + break; } - } - - - /** - * Defines what happens when this frame is closed. Can be one off - * <code>EXIT_ON_CLOSE</code>, - * <code>DISPOSE_ON_CLOSE</code>, - * <code>HIDE_ON_CLOSE</code> or - * <code>DO_NOTHING_ON_CLOSE</code>. - * The default is <code>HIDE_ON_CLOSE</code>. - * When <code>EXIT_ON_CLOSE</code> is specified this method calls - * <code>SecurityManager.checkExit(0)</code> which might throw a - * <code>SecurityException</code>. When the specified operation is - * not one of the above a <code>IllegalArgumentException</code> is - * thrown. + break; + } + case WindowEvent.WINDOW_CLOSED: + case WindowEvent.WINDOW_OPENED: + case WindowEvent.WINDOW_ICONIFIED: + case WindowEvent.WINDOW_DEICONIFIED: + case WindowEvent.WINDOW_ACTIVATED: + case WindowEvent.WINDOW_DEACTIVATED: + break; + } + } + + /** + * This method sets the action to take + * when the JDialog is closed. + * + * @param operation The action to take. */ public void setDefaultCloseOperation(int operation) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null && operation == EXIT_ON_CLOSE) - sm.checkExit(0); - - if (operation != EXIT_ON_CLOSE && operation != DISPOSE_ON_CLOSE - && operation != HIDE_ON_CLOSE && operation != DO_NOTHING_ON_CLOSE) - throw new IllegalArgumentException("operation = " + operation); - - close_action = operation; + if (operation == DO_NOTHING_ON_CLOSE || + operation == HIDE_ON_CLOSE || + operation == DISPOSE_ON_CLOSE) + close_action = operation; + else + throw new IllegalArgumentException("Default close operation must be one of DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE, or DISPOSE_ON_CLOSE"); } - + + /** + * This method returns the action taken when + * the JDialog is closed. + * + * @return The action to take. + */ public int getDefaultCloseOperation() - { return close_action; } + { + return close_action; + } - protected String paramString() - { return "JDialog"; } + /** + * This method returns a String describing the JDialog. + * + * @return A String describing the JDialog. + */ + protected String paramString() + { + return "JDialog"; + } - public AccessibleContext getAccessibleContext() - { - return null; - } + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + return null; + } } diff --git a/libjava/javax/swing/JFrame.java b/libjava/javax/swing/JFrame.java index 1062c9603b7..5c362cee7ab 100644 --- a/libjava/javax/swing/JFrame.java +++ b/libjava/javax/swing/JFrame.java @@ -57,7 +57,7 @@ import javax.accessibility.AccessibleContext; * * @author Ronald Veldema (rveldema@cs.vu.nl) */ -public class JFrame extends Frame implements WindowConstants +public class JFrame extends Frame implements WindowConstants, RootPaneContainer { protected AccessibleContext accessibleContext; @@ -121,20 +121,20 @@ public class JFrame extends Frame implements WindowConstants public void setLayout(LayoutManager manager) { super.setLayout(manager); } - void setLayeredPane(JLayeredPane layeredPane) + public void setLayeredPane(JLayeredPane layeredPane) { getRootPane().setLayeredPane(layeredPane); } - JLayeredPane getLayeredPane() + public JLayeredPane getLayeredPane() { return getRootPane().getLayeredPane(); } - JRootPane getRootPane() + public JRootPane getRootPane() { if (rootPane == null) setRootPane(createRootPane()); return rootPane; } - void setRootPane(JRootPane root) + public void setRootPane(JRootPane root) { if (rootPane != null) remove(rootPane); @@ -143,19 +143,19 @@ public class JFrame extends Frame implements WindowConstants add(rootPane, BorderLayout.CENTER); } - JRootPane createRootPane() + public JRootPane createRootPane() { return new JRootPane(); } - public Container getContentPane() + public Container getContentPane() { return getRootPane().getContentPane(); } - void setContentPane(Container contentPane) + public void setContentPane(Container contentPane) { getRootPane().setContentPane(contentPane); } - Component getGlassPane() + public Component getGlassPane() { return getRootPane().getGlassPane(); } - void setGlassPane(Component glassPane) + public void setGlassPane(Component glassPane) { getRootPane().setGlassPane(glassPane); } diff --git a/libjava/javax/swing/JLayeredPane.java b/libjava/javax/swing/JLayeredPane.java index 7002b6e0c86..37cd01221ce 100644 --- a/libjava/javax/swing/JLayeredPane.java +++ b/libjava/javax/swing/JLayeredPane.java @@ -329,7 +329,7 @@ public class JLayeredPane extends JComponent implements Accessible throw new IllegalArgumentException (); super.swapComponents (curr, targ); - validate(); + revalidate(); repaint(); } @@ -537,7 +537,7 @@ public class JLayeredPane extends JComponent implements Accessible { componentToLayer.put (c, getObjectForLayer (layer)); setPosition(c, position); - validate(); + revalidate(); repaint(); } @@ -562,13 +562,13 @@ public class JLayeredPane extends JComponent implements Accessible else layer = DEFAULT_LAYER; - int newIdx = insertIndexForLayer(layer.intValue (), -1); + int newIdx = insertIndexForLayer(layer.intValue (), index); componentToLayer.put (comp, layer); incrLayer (layer); super.addImpl(comp, null, newIdx); - validate(); + revalidate(); repaint(); } } diff --git a/libjava/javax/swing/JList.java b/libjava/javax/swing/JList.java index e8d2228bcdd..b20c450c256 100644 --- a/libjava/javax/swing/JList.java +++ b/libjava/javax/swing/JList.java @@ -40,6 +40,7 @@ package javax.swing; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; +import java.awt.Point; import java.awt.Rectangle; import java.util.Vector; import javax.accessibility.Accessible; @@ -532,6 +533,19 @@ public class JList extends JComponent implements Accessible, Scrollable } /** + * For each element <code>a[i]</code> of the provided array + * <code>a</code>, calls {@link #setSelectedIndex} on <code>a[i]</code>. + * + * @see #setSelectionMode + * @see #selectionModel + */ + public void setSelectedIndices(int [] a) + { + for (int i = 0; i < a.length; ++i) + setSelectedIndex(a[i]); + } + + /** * Returns the minimum index of an element in the list which is currently * selected. * @@ -546,6 +560,32 @@ public class JList extends JComponent implements Accessible, Scrollable } /** + * Returns the indices of values in the {@link #model} property which are + * selected. + * + * @return An array of model indices, each of which is selected according + * to the {@link #selection} property + */ + public int[] getSelectedIndices() + { + int lo, hi, n, i, j; + if (selectionModel.isSelectionEmpty()) + return new int[0]; + lo = selectionModel.getMinSelectionIndex(); + hi = selectionModel.getMaxSelectionIndex(); + n = 0; + for (i = lo; i < hi; ++i) + if (selectionModel.isSelectedIndex(i)) + n++; + int [] v = new int[n]; + j = 0; + for (i = lo; i < hi; ++i) + if (selectionModel.isSelectedIndex(i)) + v[j++] = i; + return v; + } + + /** * Indicates whether the list element at a given index value is * currently selected. * @@ -568,6 +608,8 @@ public class JList extends JComponent implements Accessible, Scrollable * * @return The first selected element, or <code>null</code> if no element * is selected. + * + * @see getSelectedValues */ public Object getSelectedValue() { @@ -578,6 +620,23 @@ public class JList extends JComponent implements Accessible, Scrollable } /** + * Returns all the values in the list's {@link #model} property which + * are selected, according to the list's {@link #selectionModel} property. + * + * @return An array containing all the selected values + * + * @see getSelectedValue + */ + public Object[] getSelectedValues() + { + int [] idx = getSelectedIndices(); + Object [] v = new Object[idx.length]; + for (int i = 0; i < idx.length; ++i) + v[i] = getModel().getElementAt(i); + return v; + } + + /** * Gets the value of the {@link #selectionBackground} property. * * @return The current value of the property @@ -720,6 +779,8 @@ public class JList extends JComponent implements Accessible, Scrollable if (model != null) model.addListDataListener(listListener); firePropertyChange(MODEL_PROPERTY_CHANGED, old, m); + revalidate(); + repaint(); } @@ -744,6 +805,8 @@ public class JList extends JComponent implements Accessible, Scrollable if (selectionModel != null) selectionModel.addListSelectionListener(listListener); firePropertyChange(SELECTION_MODEL_PROPERTY_CHANGED, old, l); + revalidate(); + repaint(); } /** @@ -842,11 +905,11 @@ public class JList extends JComponent implements Accessible, Scrollable * {@link Scrollable} interface, which interacts with {@link * ScrollPaneLayout} and {@link Viewport} to define scrollable objects. * - * @return The preferred size, or <code>null</code> + * @return The preferred size */ public Dimension getPreferredScrollableViewportSize() { - return null; + return getPreferredSize(); } /** @@ -875,6 +938,71 @@ public class JList extends JComponent implements Accessible, Scrollable public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { + ListUI lui = this.getUI(); + if (orientation == SwingConstants.VERTICAL) + { + if (direction > 0) + { + // Scrolling down + Point bottomLeft = new Point(visibleRect.x, + visibleRect.y + visibleRect.height); + int curIdx = lui.locationToIndex(this, bottomLeft); + Rectangle curBounds = lui.getCellBounds(this, curIdx, curIdx); + if (curBounds.y + curBounds.height == bottomLeft.y) + { + // we are at the exact bottom of the current cell, so we + // are being asked to scroll to the end of the next one + if (curIdx + 1 < model.getSize()) + { + // there *is* a next item in the list + Rectangle nxtBounds = lui.getCellBounds(this, curIdx + 1, curIdx + 1); + return nxtBounds.height; + } + else + { + // no next item, no advance possible + return 0; + } + } + else + { + // we are part way through an existing cell, so we are being + // asked to scroll to the bottom of it + return (curBounds.y + curBounds.height) - bottomLeft.y; + } + } + else + { + // scrolling up + Point topLeft = new Point(visibleRect.x, visibleRect.y); + int curIdx = lui.locationToIndex(this, topLeft); + Rectangle curBounds = lui.getCellBounds(this, curIdx, curIdx); + if (curBounds.y == topLeft.y) + { + // we are at the exact top of the current cell, so we + // are being asked to scroll to the top of the previous one + if (curIdx > 0) + { + // there *is* a previous item in the list + Rectangle nxtBounds = lui.getCellBounds(this, curIdx - 1, curIdx - 1); + return -nxtBounds.height; + } + else + { + // no previous item, no advance possible + return 0; + } + } + else + { + // we are part way through an existing cell, so we are being + // asked to scroll to the top of it + return curBounds.y - topLeft.y; + } + } + } + + // FIXME: handle horizontal scrolling (also wrapping?) return 1; } @@ -904,7 +1032,10 @@ public class JList extends JComponent implements Accessible, Scrollable public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { - return 1; + if (orientation == VERTICAL) + return visibleRect.height * direction; + else + return visibleRect.width * direction; } /** diff --git a/libjava/javax/swing/JMenu.java b/libjava/javax/swing/JMenu.java index 8a6004b41a0..b7d1b826983 100644 --- a/libjava/javax/swing/JMenu.java +++ b/libjava/javax/swing/JMenu.java @@ -46,724 +46,796 @@ import java.beans.PropertyChangeListener; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.util.EventListener; import java.util.Hashtable; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; import javax.accessibility.AccessibleSelection; +import javax.swing.event.ChangeListener; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; -import javax.swing.event.ChangeListener; +import javax.swing.plaf.MenuItemUI; + /** - * JMenu - * @author Andrew Selkirk - * @version 1.0 + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.1 $ */ -public class JMenu - extends JMenuItem - implements Accessible, MenuElement +public class JMenu extends JMenuItem implements Accessible, MenuElement { static final long serialVersionUID = 4227225638931828014L; - - //------------------------------------------------------------- - // Classes ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * AccessibleJMenu - */ - protected class AccessibleJMenu extends AccessibleJMenuItem - implements AccessibleSelection { - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor AccessibleJMenu - * @param component TODO - */ - protected AccessibleJMenu(JMenu component) { - super(component); - // TODO - } // AccessibleJMenu() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * getAccessibleChildrenCount - * @returns int - */ - public int getAccessibleChildrenCount() { - return 0; // TODO - } // getAccessibleChildrenCount() - - /** - * getAccessibleChild - * @param value0 TODO - * @returns Accessible - */ - public Accessible getAccessibleChild(int value0) { - return null; // TODO - } // getAccessibleChild() - - /** - * getAccessibleSelection - * @returns AccessibleSelection - */ - public AccessibleSelection getAccessibleSelection() { - return null; // TODO - } // getAccessibleSelection() - - /** - * getAccessibleSelection - * @param value0 TODO - * @returns Accessible - */ - public Accessible getAccessibleSelection(int value0) { - return null; // TODO - } // getAccessibleSelection() - - /** - * isAccessibleChildSelected - * @param value0 TODO - * @returns boolean - */ - public boolean isAccessibleChildSelected(int value0) { - return false; // TODO - } // isAccessibleChildSelected() - - /** - * getAccessibleRole - * @returns AccessibleRole - */ - public AccessibleRole getAccessibleRole() { - return AccessibleRole.MENU; - } // getAccessibleRole() - - /** - * getAccessibleSelectionCount - * @returns int - */ - public int getAccessibleSelectionCount() { - return 0; // TODO - } // getAccessibleSelectionCount() - - /** - * addAccessibleSelection - * @param value0 TODO - */ - public void addAccessibleSelection(int value0) { - // TODO - } // addAccessibleSelection() - - /** - * removeAccessibleSelection - * @param value0 TODO - */ - public void removeAccessibleSelection(int value0) { - // TODO - } // removeAccessibleSelection() - - /** - * clearAccessibleSelection - */ - public void clearAccessibleSelection() { - // TODO - } // clearAccessibleSelection() - - /** - * selectAllAccessibleSelection - */ - public void selectAllAccessibleSelection() { - // TODO - } // selectAllAccessibleSelection() - - - } // AccessibleJMenu - - /** - * WinListener - */ - protected class WinListener extends WindowAdapter implements Serializable { - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * popupMenu - */ - JPopupMenu popupMenu; - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor WinListener - * @param value0 TODO - * @param value1 TODO - */ - public WinListener(JMenu value0, JPopupMenu value1) { - // TODO - } // WinListener() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * windowClosing - * @param value0 TODO - */ - public void windowClosing(WindowEvent value0) { - // TODO - } // windowClosing() - - - } // WinListener - - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * uiClassID - */ - private static final String uiClassID = "MenuUI"; - - /** - * popupMenu - */ - private JPopupMenu popupMenu; - - /** - * menuChangeListener - */ - private ChangeListener menuChangeListener; - - /** - * menuEvent - */ - private MenuEvent menuEvent; - - /** - * listenerRegistry - */ - private static Hashtable listenerRegistry = null; // TODO - - /** - * delay - */ - private int delay; - - /** - * TRACE - */ - private static final boolean TRACE = false; // TODO - - /** - * VERBOSE - */ - private static final boolean VERBOSE = false; // TODO - - /** - * DEBUG - */ - private static final boolean DEBUG = false; // TODO - - /** - * popupListener - */ - protected JMenu.WinListener popupListener; - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor JMenu - */ - public JMenu() { - // TODO - } // JMenu() - - /** - * Constructor JMenu - * @param text TODO - */ - public JMenu(String text) { - // TODO - } // JMenu() - - /** - * Constructor JMenu - * @param action TODO - */ - public JMenu(Action action) { - // TODO - } // JMenu() - - /** - * Constructor JMenu - * @param text TODO - * @param tearoff TODO - */ - public JMenu(String text, boolean tearoff) { - // TODO - } // JMenu() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * writeObject - * @param stream TODO - * @exception IOException TODO - */ - private void writeObject(ObjectOutputStream stream) throws IOException { - // TODO - } // writeObject() - - /** - * add - * @param value0 TODO - * @returns JMenuItem - */ - public JMenuItem add(JMenuItem item) { - return null; // TODO - } // add() - - /** - * add - * @param component TODO - * @returns Component - */ - public Component add(Component component) { - return null; // TODO - } // add() - - /** - * add - * @param component TODO - * @param index TODO - * @returns Component - */ - public Component add(Component component, int index) { - return null; // TODO - } // add() - - /** - * add - * @param text TODO - * @returns JMenuItem - */ - public JMenuItem add(String text) { - return null; // TODO - } // add() - - /** - * add - * @param action TODO - * @returns JMenuItem - */ - public JMenuItem add(Action action) { - return null; // TODO - } // add() - - /** - * remove - * @param item TODO - */ - public void remove(JMenuItem item) { - // TODO - } // remove() - - /** - * remove - * @param index TODO - */ - public void remove(int index) { - // TODO - } // remove() - - /** - * remove - * @param component TODO - */ - public void remove(Component component) { - // TODO - } // remove() - - /** - * removeAll - */ - public void removeAll() { - // TODO - } // removeAll() - - /** - * insert - * @param text TODO - * @param index TODO - */ - public void insert(String text, int index) { - // TODO - } // insert() - - /** - * insert - * @param item TODO - * @param index TODO - * @returns JMenuItem - */ - public JMenuItem insert(JMenuItem item, int index) { - return null; // TODO - } // insert() - - /** - * insert - * @param action TODO - * @param index TODO - * @returns JMenuItem - */ - public JMenuItem insert(Action action, int index) { - return null; // TODO - } // insert() - - /** - * updateUI - */ - public void updateUI() { - //setUI((MenuUI) UIManager.get(this)); - invalidate(); - } // updateUI() - - /** - * getUIClassID - * @returns String - */ - public String getUIClassID() { - return uiClassID; - } // getUIClassID() - - /** - * setModel - * @param model TODO - */ - public void setModel(ButtonModel model) { - // TODO - } // setModel() - - /** - * isSelected - * @returns boolean - */ - public boolean isSelected() { - return false; // TODO - } // isSelected() - - /** - * setSelected - * @param selected TODO - */ - public void setSelected(boolean selected) { - // TODO - } // setSelected() - - /** - * isPopupMenuVisible - * @returns boolean - */ - public boolean isPopupMenuVisible() { - return false; // TODO - } // isPopupMenuVisible() - - /** - * setPopupMenuVisible - * @param popup TODO - */ - public void setPopupMenuVisible(boolean popup) { - // TODO - } // setPopupMenuVisible() - - /** - * getPopupMenuOrigin - * @returns Point - */ - protected Point getPopupMenuOrigin() { - return null; // TODO - } // getPopupMenuOrigin() - - /** - * getDelay - * @returns int - */ - public int getDelay() { - return 0; // TODO - } // getDelay() - - /** - * setDelay - * @param value0 TODO - */ - public void setDelay(int delay) { - // TODO - } // setDelay() - - /** - * setMenuLocation - * @param x TODO - * @param y TODO - */ - public void setMenuLocation(int x, int y) { - // TODO - } // setMenuLocation() - - /** - * createActionComponent - * @param action TODO - * @returns JMenuItem - */ - protected JMenuItem createActionComponent(Action action) { - return null; // TODO - } // createActionComponent() - - /** - * createActionChangeListener - * @param item TODO - * @returns PropertyChangeListener - */ - protected PropertyChangeListener createActionChangeListener(JMenuItem item) { - return null; // TODO - } // createActionChangeListener() - - /** - * addSeparator - */ - public void addSeparator() { - // TODO - } // addSeparator() - - /** - * insertSeparator - * @param index TODO - */ - public void insertSeparator(int index) { - // TODO - } // insertSeparator() - - /** - * getItem - * @param index TODO - * @returns JMenuItem - */ - public JMenuItem getItem(int index) { - return null; // TODO - } // getItem() - - /** - * getItemCount - * @returns int - */ - public int getItemCount() { - return 0; // TODO - } // getItemCount() - - /** - * isTearOff - * @returns boolean - */ - public boolean isTearOff() { - return false; // TODO - } // isTearOff() - - /** - * getMenuComponentCount - * @returns int - */ - public int getMenuComponentCount() { - return 0; // TODO - } // getMenuComponentCount() - - /** - * getMenuComponent - * @param index TODO - * @returns Component - */ - public Component getMenuComponent(int index) { - return null; // TODO - } // getMenuComponent() - - /** - * getMenuComponents - * @returns Component[] - */ - public Component[] getMenuComponents() { - return null; // TODO - } // getMenuComponents() - - /** - * isTopLevelMenu - * @returns boolean - */ - public boolean isTopLevelMenu() { - return false; // TODO - } // isTopLevelMenu() - - /** - * isMenuComponent - * @param component TODO - * @returns boolean - */ - public boolean isMenuComponent(Component component) { - return false; // TODO - } // isMenuComponent() - - /** - * getPopupMenu - * @returns JPopupMenu - */ - public JPopupMenu getPopupMenu() { - return null; // TODO - } // getPopupMenu() - - /** - * addMenuListener - * @param listener TODO - */ - public void addMenuListener(MenuListener listener) { - // TODO - } // addMenuListener() - - /** - * removeMenuListener - * @param listener TODO - */ - public void removeMenuListener(MenuListener listener) { - // TODO - } // removeMenuListener() - - /** - * fireMenuSelected - */ - protected void fireMenuSelected() { - // TODO - } // fireMenuSelected() - - /** - * fireMenuDeselected - */ - protected void fireMenuDeselected() { - // TODO - } // fireMenuDeselected() - - /** - * fireMenuCanceled - */ - protected void fireMenuCanceled() { - // TODO - } // fireMenuCanceled() - - /** - * createMenuChangeListener - * @returns ChangeListener - */ - private ChangeListener createMenuChangeListener() { - return null; // TODO - } // createMenuChangeListener() - - /** - * createWinListener - * @param popup TODO - * @returns JMenu.WinListener - */ - protected JMenu.WinListener createWinListener(JPopupMenu popup) { - return null; // TODO - } // createWinListener() - - /** - * menuSelectionChanged - * @param value0 TODO - */ - public void menuSelectionChanged(boolean changed) { - // TODO - } // menuSelectionChanged() - - /** - * getSubElements - * @returns MenuElement[] - */ - public MenuElement[] getSubElements() { - return null; // TODO - } // getSubElements() - - /** - * getComponent - * @returns Component - */ - public Component getComponent() { - return null; // TODO - } // getComponent() - - /** - * setAccelerator - * @param keystroke TODO - */ - public void setAccelerator(KeyStroke keystroke) { - // TODO - } // setAccelerator() - - /** - * processKeyEvent - * @param event TODO - */ - protected void processKeyEvent(KeyEvent event) { - // TODO - } // processKeyEvent() - - /** - * doClick - * @param time TODO - */ - public void doClick(int time) { - // TODO - } // doClick() - - /** - * paramString - * @returns String - */ - protected String paramString() { - return null; // TODO - } // paramString() - - /** - * getAccessibleContext - * @returns AccessibleContext - */ - public AccessibleContext getAccessibleContext() { - if (accessibleContext == null) { - accessibleContext = new AccessibleJMenu(this); - } // if - return accessibleContext; - } // getAccessibleContext() - - -} // JMenu + private static final String uiClassID = "MenuUI"; + private static Hashtable listenerRegistry = null; + private JPopupMenu popupMenu = new JPopupMenu(); + private ChangeListener menuChangeListener; + private MenuEvent menuEvent; + private int delay; + protected JMenu.WinListener popupListener; + + /** + * Creates a new JMenu object. + */ + public JMenu() + { + super(); + } + + /** + * Creates a new JMenu object. + * + * @param text DOCUMENT ME! + */ + public JMenu(String text) + { + super(text); + } + + /** + * Creates a new JMenu object. + * + * @param action DOCUMENT ME! + */ + public JMenu(Action action) + { + super(action); + } + + /** + * Creates a new JMenu object. + * + * @param text DOCUMENT ME! + * @param tearoff DOCUMENT ME! + */ + public JMenu(String text, boolean tearoff) + { + } + + /** + * DOCUMENT ME! + * + * @param stream DOCUMENT ME! + * + * @throws IOException DOCUMENT ME! + */ + private void writeObject(ObjectOutputStream stream) throws IOException + { + } + + /** + * DOCUMENT ME! + * + * @param item DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenuItem add(JMenuItem item) + { + return popupMenu.add(item); + } + + /** + * DOCUMENT ME! + * + * @param component DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component add(Component component) + { + return popupMenu.add(component); + } + + /** + * DOCUMENT ME! + * + * @param component DOCUMENT ME! + * @param index DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component add(Component component, int index) + { + return popupMenu.add(component, index); + } + + /** + * DOCUMENT ME! + * + * @param text DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenuItem add(String text) + { + return popupMenu.add(text); + } + + /** + * DOCUMENT ME! + * + * @param action DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenuItem add(Action action) + { + return popupMenu.add(action); + } + + /** + * DOCUMENT ME! + * + * @param item DOCUMENT ME! + */ + public void remove(JMenuItem item) + { + popupMenu.remove(item); + } + + /** + * DOCUMENT ME! + * + * @param index DOCUMENT ME! + */ + public void remove(int index) + { + popupMenu.remove(index); + } + + /** + * DOCUMENT ME! + * + * @param component DOCUMENT ME! + */ + public void remove(Component component) + { + int index = popupMenu.getComponentIndex(component); + popupMenu.remove(index); + } + + /** + * DOCUMENT ME! + */ + public void removeAll() + { + popupMenu.removeAll(); + } + + /** + * DOCUMENT ME! + * + * @param text DOCUMENT ME! + * @param index DOCUMENT ME! + */ + public void insert(String text, int index) + { + popupMenu.insert(new JMenuItem(text), index); + } + + /** + * DOCUMENT ME! + * + * @param item DOCUMENT ME! + * @param index DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenuItem insert(JMenuItem item, int index) + { + popupMenu.insert(item, index); + + return item; + } + + /** + * DOCUMENT ME! + * + * @param action DOCUMENT ME! + * @param index DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenuItem insert(Action action, int index) + { + JMenuItem item = new JMenuItem(action); + popupMenu.insert(item, index); + + return item; + } + + /** + * DOCUMENT ME! + */ + public void updateUI() + { + super.setUI((MenuItemUI) UIManager.getUI(this)); + invalidate(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getUIClassID() + { + return uiClassID; + } + + /** + * DOCUMENT ME! + * + * @param model DOCUMENT ME! + */ + public void setModel(ButtonModel model) + { + super.setModel(model); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isSelected() + { + return super.isSelected(); + } + + /** + * DOCUMENT ME! + * + * @param selected DOCUMENT ME! + */ + public void setSelected(boolean selected) + { + super.setSelected(selected); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isPopupMenuVisible() + { + return popupMenu.isVisible(); + } + + /** + * DOCUMENT ME! + * + * @param popup DOCUMENT ME! + */ + public void setPopupMenuVisible(boolean popup) + { + if (isEnabled()) + popupMenu.setVisible(popup); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected Point getPopupMenuOrigin() + { + // if menu in the menu bar + if (isTopLevelMenu()) + return new Point(0, this.getHeight()); + + // if submenu + return new Point(this.getWidth(), 0); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getDelay() + { + return delay; + } + + /** + * DOCUMENT ME! + * + * @param delay DOCUMENT ME! + */ + public void setDelay(int delay) + { + this.delay = delay; + } + + /** + * DOCUMENT ME! + * + * @param x DOCUMENT ME! + * @param y DOCUMENT ME! + */ + public void setMenuLocation(int x, int y) + { + popupMenu.setLocation(x, y); + } + + /** + * DOCUMENT ME! + * + * @param action DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected JMenuItem createActionComponent(Action action) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param item DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected PropertyChangeListener createActionChangeListener(JMenuItem item) + { + return null; + } + + /** + * DOCUMENT ME! + */ + public void addSeparator() + { + } + + /** + * DOCUMENT ME! + * + * @param index DOCUMENT ME! + */ + public void insertSeparator(int index) + { + } + + /** + * DOCUMENT ME! + * + * @param index DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenuItem getItem(int index) + { + Component c = popupMenu.getComponentAtIndex(index); + + if (c instanceof JMenuItem) + return (JMenuItem) c; + else + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getItemCount() + { + return 0; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isTearOff() + { + return false; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getMenuComponentCount() + { + return popupMenu.getComponentCount(); + } + + /** + * DOCUMENT ME! + * + * @param index DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component getMenuComponent(int index) + { + return (Component) popupMenu.getComponentAtIndex(index); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component[] getMenuComponents() + { + return popupMenu.getComponents(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isTopLevelMenu() + { + if (getParent() instanceof JMenuBar) + return true; + else + return false; + } + + /** + * DOCUMENT ME! + * + * @param component DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isMenuComponent(Component component) + { + return false; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JPopupMenu getPopupMenu() + { + return popupMenu; + } + + /** + * DOCUMENT ME! + * + * @param listener DOCUMENT ME! + */ + public void addMenuListener(MenuListener listener) + { + listenerList.add(MenuListener.class, listener); + } + + /** + * DOCUMENT ME! + * + * @param listener DOCUMENT ME! + */ + public void removeMenuListener(MenuListener listener) + { + listenerList.remove(MenuListener.class, listener); + } + + /** + * DOCUMENT ME! + */ + protected void fireMenuSelected() + { + EventListener[] ll = listenerList.getListeners(MenuListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuListener) ll[i]).menuSelected(new MenuEvent(this)); + } + + /** + * DOCUMENT ME! + */ + protected void fireMenuDeselected() + { + EventListener[] ll = listenerList.getListeners(MenuListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuListener) ll[i]).menuDeselected(new MenuEvent(this)); + } + + /** + * DOCUMENT ME! + */ + protected void fireMenuCanceled() + { + EventListener[] ll = listenerList.getListeners(MenuListener.class); + + for (int i = 0; i < ll.length; i++) + ((MenuListener) ll[i]).menuCanceled(new MenuEvent(this)); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private ChangeListener createMenuChangeListener() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param popup DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected JMenu.WinListener createWinListener(JPopupMenu popup) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param changed DOCUMENT ME! + */ + public void menuSelectionChanged(boolean changed) + { + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public MenuElement[] getSubElements() + { + return new MenuElement[] { popupMenu }; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component getComponent() + { + return this; + } + + /** + * DOCUMENT ME! + * + * @param keystroke DOCUMENT ME! + */ + public void setAccelerator(KeyStroke keystroke) + { + super.setAccelerator(keystroke); + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ + protected void processKeyEvent(KeyEvent event) + { + } + + /** + * DOCUMENT ME! + * + * @param time DOCUMENT ME! + */ + public void doClick(int time) + { + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected String paramString() + { + return "JMenu"; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJMenu(this); + + return accessibleContext; + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.1 $ + */ + protected class AccessibleJMenu extends AccessibleJMenuItem + implements AccessibleSelection + { + /** + * Creates a new AccessibleJMenu object. + * + * @param component DOCUMENT ME! + */ + protected AccessibleJMenu(JMenu component) + { + super(component); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getAccessibleChildrenCount() + { + return 0; + } + + /** + * DOCUMENT ME! + * + * @param value0 DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Accessible getAccessibleChild(int value0) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleSelection getAccessibleSelection() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param value0 DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Accessible getAccessibleSelection(int value0) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param value0 DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isAccessibleChildSelected(int value0) + { + return false; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.MENU; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getAccessibleSelectionCount() + { + return 0; + } + + /** + * DOCUMENT ME! + * + * @param value0 DOCUMENT ME! + */ + public void addAccessibleSelection(int value0) + { + } + + /** + * DOCUMENT ME! + * + * @param value0 DOCUMENT ME! + */ + public void removeAccessibleSelection(int value0) + { + } + + /** + * DOCUMENT ME! + */ + public void clearAccessibleSelection() + { + } + + /** + * DOCUMENT ME! + */ + public void selectAllAccessibleSelection() + { + } + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.1 $ + */ + protected class WinListener extends WindowAdapter implements Serializable + { + JPopupMenu popupMenu; + + /** + * Creates a new WinListener object. + * + * @param value0 DOCUMENT ME! + * @param value1 DOCUMENT ME! + */ + public WinListener(JMenu value0, JPopupMenu value1) + { + } + + /** + * DOCUMENT ME! + * + * @param value0 DOCUMENT ME! + */ + public void windowClosing(WindowEvent value0) + { + } + } +} diff --git a/libjava/javax/swing/JMenuBar.java b/libjava/javax/swing/JMenuBar.java index fec19e694bd..7ec52968a42 100644 --- a/libjava/javax/swing/JMenuBar.java +++ b/libjava/javax/swing/JMenuBar.java @@ -35,13 +35,392 @@ this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ - package javax.swing; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Point; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleSelection; +import javax.accessibility.AccessibleStateSet; +import javax.accessibility.AccessibleValue; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuKeyEvent; +import javax.swing.event.MenuKeyListener; +import javax.swing.plaf.MenuBarUI; +import javax.swing.plaf.MenuItemUI; + -public class JMenuBar extends JComponent +/** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.2.18.1 $ + */ +public class JMenuBar extends JComponent implements Accessible, MenuElement { - JMenuBar() - { - } + private transient SingleSelectionModel selectionModel; + private boolean paintBorder; + private Insets margin; + + /** + * Creates a new JMenuBar object. + */ + public JMenuBar() + { + selectionModel = new DefaultSingleSelectionModel(); + paintBorder = true; + updateUI(); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenu add(JMenu c) + { + c.setAlignmentX(Component.LEFT_ALIGNMENT); + super.add(c); + return c; + } + + /** + * DOCUMENT ME! + */ + public void addNotify() + { + // FIXME: Should register this menu bar with the keyboard manager + super.addNotify(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component getComponent() + { + return this; + } + + /** + * DOCUMENT ME! + * + * @param i DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component getComponentAtIndex(int i) + { + return getComponentAt(i); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getComponentIndex(Component c) + { + Component[] comps = getComponents(); + + int index = -1; + + for (int i = 0; i < comps.length; i++) + { + if (comps[i].equals(c)) + { + index = i; + break; + } + } + + return index; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenu getHelpMenu() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Insets getMargin() + { + if (margin == null) + return new Insets(0, 0, 0, 0); + else + return margin; + } + + /** + * DOCUMENT ME! + * + * @param index DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenu getMenu(int index) + { + if (getComponentAtIndex(index) instanceof JMenu) + return (JMenu) getComponentAtIndex(index); + else + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getMenuCount() + { + return getComponentCount(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public SingleSelectionModel getSelectionModel() + { + return selectionModel; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public MenuElement[] getSubElements() + { + MenuElement[] subElements = new MenuElement[getComponentCount()]; + + for (int i = 0; i < getComponentCount(); i++) + subElements[i] = (MenuElement) getMenu(i); + + return subElements; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public MenuBarUI getUI() + { + return (MenuBarUI) ui; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getUIClassID() + { + return "MenuBarUI"; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isBorderPainted() + { + return paintBorder; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isManagingFocus() + { + return true; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isSelected() + { + return false; + } + + /** + * DOCUMENT ME! + * + * @param isIncluded DOCUMENT ME! + */ + public void menuSelectionChanged(boolean isIncluded) + { + // Do nothing - needed for implementation of MenuElement interface + } + + /** + * DOCUMENT ME! + * + * @param g DOCUMENT ME! + */ + protected void paintBorder(Graphics g) + { + if (paintBorder) + getBorder().paintBorder(this, g, 0, 0, getSize(null).width, + getSize(null).height); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected String paramString() + { + return "JMenuBar"; + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ + public void processKeyEvent(KeyEvent e, MenuElement[] path, + MenuSelectionManager manager) + { + // Do nothing - needed for implementation of MenuElement interface + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ + public void processMouseEvent(MouseEvent event, MenuElement[] path, + MenuSelectionManager manager) + { + // Do nothing - needed for implementation of MenuElement interface + } + + /** + * DOCUMENT ME! + */ + public void removeNotify() + { + // Must unregister this menu bar with the current keyboard manager. + super.removeNotify(); + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + public void setBorderPainted(boolean b) + { + paintBorder = b; + } + + /** + * DOCUMENT ME! + * + * @param menu DOCUMENT ME! + */ + public void setHelpMenu(JMenu menu) + { + } + + /** + * DOCUMENT ME! + * + * @param m DOCUMENT ME! + */ + public void setMargin(Insets m) + { + this.margin = m; + } + + /** + * DOCUMENT ME! + * + * @param sel DOCUMENT ME! + */ + public void setSelected(Component sel) + { + } + + /** + * DOCUMENT ME! + * + * @param model DOCUMENT ME! + */ + public void setSelectionModel(SingleSelectionModel model) + { + } + + /** + * DOCUMENT ME! + * + * @param ui DOCUMENT ME! + */ + public void setUI(MenuBarUI ui) + { + super.setUI(ui); + } + + /** + * DOCUMENT ME! + */ + public void updateUI() + { + MenuBarUI ui = ((MenuBarUI) UIManager.getUI(this)); + setUI(ui); + invalidate(); + } } diff --git a/libjava/javax/swing/JMenuItem.java b/libjava/javax/swing/JMenuItem.java index db06bc670e8..2d525ce6f31 100644 --- a/libjava/javax/swing/JMenuItem.java +++ b/libjava/javax/swing/JMenuItem.java @@ -35,20 +35,22 @@ this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ - package javax.swing; import java.awt.Component; +import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; - +import java.util.EventListener; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; +import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.MenuDragMouseEvent; @@ -57,48 +59,79 @@ import javax.swing.event.MenuKeyEvent; import javax.swing.event.MenuKeyListener; import javax.swing.plaf.MenuItemUI; + +/** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.2.18.4 $ + */ public class JMenuItem extends AbstractButton implements Accessible, MenuElement { - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- private static final String uiClassID = "MenuItemUI"; private KeyStroke accelerator; - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- + /** + * Creates a new JMenuItem object. + */ public JMenuItem() { this(null, null); - } // JMenuItem() + } + /** + * Creates a new JMenuItem object. + * + * @param icon DOCUMENT ME! + */ public JMenuItem(Icon icon) { this(null, icon); - } // JMenuItem() + } + /** + * Creates a new JMenuItem object. + * + * @param text DOCUMENT ME! + */ public JMenuItem(String text) { this(text, null); - } // JMenuItem() + } + /** + * Creates a new JMenuItem object. + * + * @param action DOCUMENT ME! + */ public JMenuItem(Action action) { // TODO - } // JMenuItem() - + } + + /** + * Creates a new JMenuItem object. + * + * @param text DOCUMENT ME! + * @param icon DOCUMENT ME! + */ public JMenuItem(String text, Icon icon) { super(text, icon); - } // JMenuItem() - + } + + /** + * Creates a new JMenuItem object. + * + * @param text DOCUMENT ME! + * @param mnemonic DOCUMENT ME! + */ public JMenuItem(String text, int mnemonic) { super(text, null); setMnemonic(mnemonic); - } // JMenuItem() + } //------------------------------------------------------------- // Methods ---------------------------------------------------- @@ -107,60 +140,116 @@ public class JMenuItem extends AbstractButton implements Accessible, throws IOException, ClassNotFoundException { // TODO - } // readObject() - + } + + /** + * DOCUMENT ME! + * + * @param stream DOCUMENT ME! + * + * @throws IOException DOCUMENT ME! + */ private void writeObject(ObjectOutputStream stream) throws IOException { // TODO - } // writeObject() - + } + + /** + * DOCUMENT ME! + * + * @param text DOCUMENT ME! + * @param icon DOCUMENT ME! + */ protected void init(String text, Icon icon) { // TODO - } // init() + } + /** + * DOCUMENT ME! + * + * @param ui DOCUMENT ME! + */ public void setUI(MenuItemUI ui) { super.setUI(ui); - } // setUI() + } + /** + * DOCUMENT ME! + */ public void updateUI() { MenuItemUI mi = ((MenuItemUI) UIManager.getUI(this)); setUI(mi); invalidate(); - } // updateUI() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public String getUIClassID() { return uiClassID; - } // getUIClassID() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public boolean isArmed() { return getModel().isArmed(); - } // isArmed() + } + /** + * DOCUMENT ME! + * + * @param armed DOCUMENT ME! + */ public void setArmed(boolean armed) { getModel().setArmed(armed); - } // setArmed() + } + /** + * DOCUMENT ME! + * + * @param enabled DOCUMENT ME! + */ public void setEnabled(boolean enabled) { setEnabled(enabled); - } // setEnabled() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public KeyStroke getAccelerator() { return accelerator; - } // getAccelerator() + } + /** + * DOCUMENT ME! + * + * @param keystroke DOCUMENT ME! + */ public void setAccelerator(KeyStroke keystroke) { this.accelerator = keystroke; - } // setAccelerator() + } + /** + * DOCUMENT ME! + * + * @param action DOCUMENT ME! + */ protected void configurePropertiesFromAction(Action action) { super.configurePropertiesFromAction(action); @@ -169,147 +258,371 @@ public class JMenuItem extends AbstractButton implements Accessible, setAccelerator(null); else setAccelerator((KeyStroke) (action.getValue(Action.ACCELERATOR_KEY))); - - } // configurePropertiesFromAction() - + } + + /** + * DOCUMENT ME! + * + * @param action DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ protected PropertyChangeListener createActionPropertyChangeListener(Action action) { - return null; - } // createActionPropertyChangeListener() - + return new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent e) + { + Action act = (Action) (e.getSource()); + configurePropertiesFromAction(act); + } + }; + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ public void processMouseEvent(MouseEvent event, MenuElement[] path, MenuSelectionManager manager) { - // TODO - } // processMouseEvent() - + switch (event.getID()) + { + case MouseEvent.MOUSE_CLICKED: + doClick(); + break; + case MouseEvent.MOUSE_ENTERED: + if (event.getSource() instanceof JMenuItem) + { + JMenuItem item = (JMenuItem) event.getSource(); + ButtonModel model = item.getModel(); + + if (item.isRolloverEnabled()) + model.setRollover(true); + + if (model.isPressed() + && (event.getModifiers() & InputEvent.BUTTON1_MASK) != 0) + model.setArmed(true); + else + model.setArmed(false); + } + break; + case MouseEvent.MOUSE_EXITED: + if (event.getSource() instanceof JMenuItem) + { + JMenuItem item = (JMenuItem) event.getSource(); + ButtonModel model = item.getModel(); + if (item.isRolloverEnabled()) + model.setRollover(false); + model.setArmed(false); + } + break; + case MouseEvent.MOUSE_PRESSED: + if (event.getSource() instanceof JMenuItem) + { + if ((event.getModifiers() & InputEvent.BUTTON1_MASK) != 0) + { + model.setArmed(true); + model.setPressed(true); + } + } + break; + case MouseEvent.MOUSE_RELEASED: + if (event.getSource() instanceof JMenuItem) + { + JMenuItem item = (JMenuItem) event.getSource(); + ButtonModel model = item.getModel(); + if ((event.getModifiers() & InputEvent.BUTTON1_MASK) != 0) + { + model.setPressed(false); + model.setArmed(false); + manager.clearSelectedPath(); + } + } + break; + case MouseEvent.MOUSE_MOVED: + break; + case MouseEvent.MOUSE_DRAGGED: + MenuDragMouseEvent e = new MenuDragMouseEvent((Component) event + .getSource(), + event.getID(), + event.getWhen(), + event.getModifiers(), + event.getX(), + event.getY(), + event.getClickCount(), + event.isPopupTrigger(), + path, manager); + processMenuDragMouseEvent(e); + break; + } + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ public void processKeyEvent(KeyEvent event, MenuElement[] path, MenuSelectionManager manager) { // TODO - } // processKeyEvent() + } + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ public void processMenuDragMouseEvent(MenuDragMouseEvent event) { - } // processMenuDragMouseEvent() + switch (event.getID()) + { + case MouseEvent.MOUSE_ENTERED: + fireMenuDragMouseEntered(event); + break; + case MouseEvent.MOUSE_EXITED: + fireMenuDragMouseExited(event); + break; + case MouseEvent.MOUSE_DRAGGED: + fireMenuDragMouseDragged(event); + break; + case MouseEvent.MOUSE_RELEASED: + fireMenuDragMouseReleased(event); + break; + } + } + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ public void processMenuKeyEvent(MenuKeyEvent event) { // TODO - } // processMenuKeyEvent() + } + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ protected void fireMenuDragMouseEntered(MenuDragMouseEvent event) { - // TODO - } // fireMenuDragMouseEntered() + EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); + for (int i = 0; i < ll.length; i++) + ((MenuDragMouseListener) ll[i]).menuDragMouseEntered(event); + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ protected void fireMenuDragMouseExited(MenuDragMouseEvent event) { - // TODO - } // fireMenuDragMouseExited() + EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); + for (int i = 0; i < ll.length; i++) + ((MenuDragMouseListener) ll[i]).menuDragMouseExited(event); + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ protected void fireMenuDragMouseDragged(MenuDragMouseEvent event) { - // TODO - } // fireMenuDragMouseDragged() + EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); + for (int i = 0; i < ll.length; i++) + ((MenuDragMouseListener) ll[i]).menuDragMouseDragged(event); + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ protected void fireMenuDragMouseReleased(MenuDragMouseEvent event) { - // TODO - } // fireMenuDragMouseReleased() + EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); + for (int i = 0; i < ll.length; i++) + ((MenuDragMouseListener) ll[i]).menuDragMouseReleased(event); + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ protected void fireMenuKeyPressed(MenuKeyEvent event) { // TODO - } // fireMenuKeyPressed() + } + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ protected void fireMenuKeyReleased(MenuKeyEvent event) { // TODO - } // fireMenuKeyReleased() + } + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ protected void fireMenuKeyTyped(MenuKeyEvent event) { // TODO - } // fireMenuKeyTyped() + } + /** + * DOCUMENT ME! + * + * @param changed DOCUMENT ME! + */ public void menuSelectionChanged(boolean changed) { - // TODO - } // menuSelectionChanged() + if (changed) + model.setArmed(true); + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public MenuElement[] getSubElements() { - return null; // TODO - } // getSubElements() + return new MenuElement[0]; + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public Component getComponent() { - return null; // TODO - } // getComponent() + return this; + } + /** + * DOCUMENT ME! + * + * @param listener DOCUMENT ME! + */ public void addMenuDragMouseListener(MenuDragMouseListener listener) { - // TODO - } // addMenuDragMouseListener() + listenerList.add(MenuDragMouseListener.class, listener); + } + /** + * DOCUMENT ME! + * + * @param listener DOCUMENT ME! + */ public void removeMenuDragMouseListener(MenuDragMouseListener listener) { - } // removeMenuDragMouseListener() + listenerList.remove(MenuDragMouseListener.class, listener); + } + /** + * DOCUMENT ME! + * + * @param listener DOCUMENT ME! + */ public void addMenuKeyListener(MenuKeyListener listener) { - } // addMenuKeyListener() + listenerList.add(MenuKeyListener.class, listener); + } + /** + * DOCUMENT ME! + * + * @param listener DOCUMENT ME! + */ public void removeMenuKeyListener(MenuKeyListener listener) { - } // removeMenuKeyListener() + listenerList.remove(MenuKeyListener.class, listener); + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ protected String paramString() { return "JMenuItem"; - } // paramString() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public AccessibleContext getAccessibleContext() { if (accessibleContext == null) - { - accessibleContext = new AccessibleJMenuItem(this); - } + accessibleContext = new AccessibleJMenuItem(this); return accessibleContext; - } // getAccessibleContext() - - //------------------------------------------------------------- - // Classes ---------------------------------------------------- - //------------------------------------------------------------- + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.2.18.4 $ + */ protected class AccessibleJMenuItem extends AccessibleAbstractButton implements ChangeListener { - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- + /** + * Creates a new AccessibleJMenuItem object. + * + * @param component DOCUMENT ME! + */ AccessibleJMenuItem(JMenuItem component) { super(component); // TODO - } // AccessibleJMenuItem() + } - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ public void stateChanged(ChangeEvent event) { // TODO - } // stateChanged() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public AccessibleRole getAccessibleRole() { return AccessibleRole.MENU_ITEM; - } // getAccessibleRole() - } // AccessibleJMenuItem -} // JMenuItem + } + } +} diff --git a/libjava/javax/swing/JOptionPane.java b/libjava/javax/swing/JOptionPane.java index 7df8ebd5d16..ae7afbf3020 100644 --- a/libjava/javax/swing/JOptionPane.java +++ b/libjava/javax/swing/JOptionPane.java @@ -1,5 +1,5 @@ -/* JOptionPane.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. +/* JOptionPane.java + Copyright (C) 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -35,365 +35,1388 @@ this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ - package javax.swing; -import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dialog; import java.awt.Frame; - +import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.Icon; import javax.swing.plaf.OptionPaneUI; -public class JOptionPane extends JComponent -{ - public static final int DEFAULT_OPTION = 0; - public static final int YES_NO_OPTION = 1; - public static final int YES_NO_CANCEL_OPTION = 2; - public static final int OK_CANCEL_OPTION = 3; - public static final int YES_OPTION = 4; - public static final int NO_OPTION = 5; - public static final int CANCEL_OPTION = 6; - public static final int OK_OPTION = 7; - public static final int CLOSED_OPTION = 8; - - public static final int ERROR_MESSAGE = 0; - public static final int INFORMATION_MESSAGE = 1; - public static final int WARNING_MESSAGE = 2; - public static final int QUESTION_MESSAGE = 3; - public static final int PLAIN_MESSAGE = 4; - - final static String VALUE_PROPERTY = "value_prop"; - final static String INPUT_VALUE_PROPERTY = "input_value_prop"; - - final static String UNINITIALIZED_VALUE = "uninit"; - - // Ronald: shouldnt by public ? - public Object msg; - public int mtype; - public int otype; - public Icon icon; - public Object []args; - public Object init; - - public JDialog dialog; - - /***************************************************************************** - * - * - * joptionpanels - * - * - ***********************************/ - JOptionPane() - { - this("mess"); - } - - JOptionPane(Object m) - { - this(m, PLAIN_MESSAGE); - } - - JOptionPane(Object m, - int mtype) +/** + * This class creates different types of JDialogs and JInternalFrames that can + * ask users for input or pass on information. JOptionPane can be used by + * calling one of the show static methods or by creating an instance of + * JOptionPane and calling createDialog or createInternalFrame. + */ +public class JOptionPane extends JComponent implements Accessible +{ + /** + * DOCUMENT ME! + */ + protected class AccessibleJOptionPane extends JComponent.AccessibleJComponent + { + /** + * Creates a new AccessibleJOptionPane object. + */ + protected AccessibleJOptionPane() { - this(m, mtype, DEFAULT_OPTION); + super(JOptionPane.this); } - JOptionPane(Object m, - int mtype, - int otype) - { - this(m, mtype, otype, null); - } - - JOptionPane(Object m, - int mtype, - int otype, - Icon icon) + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() { - this(m, mtype, otype, icon, null); + return null; } + } - JOptionPane(Object m, - int mtype, - int otype, - Icon icon, - Object []args) - { - this(m, mtype, otype, icon, args, null); - } + /** The value returned when cancel option is selected. */ + public static final int CANCEL_OPTION = 2; - JOptionPane(Object msg, - int mtype, - int otype, - Icon icon, - Object []args, - Object init) - { - // this(m, mtype, otype, icon, args, init); - this.msg = msg; - this.mtype = mtype; - this.otype = otype; - this.icon = icon; - this.args = args; - this.init = init; - - updateUI(); - } + /** The value returned when the dialog is closed without a selection. */ + public static final int CLOSED_OPTION = -1; + /** An option used in confirmation dialog methods. */ + public static final int DEFAULT_OPTION = -1; - /***************************************************************************** - * - * - * - * - * - ***********************************/ + /** The value returned when the no option is selected. */ + public static final int NO_OPTION = 1; - Object val; - public void setValue(Object v) - { val = v; } - public Object getValue() - { return val; } + /** An option used in confirmation dialog methods. */ + public static final int OK_CANCEL_OPTION = 2; - public String getUIClassID() - { return "OptionPaneUI"; } + /** The value returned when the ok option is selected. */ + public static final int OK_OPTION = 0; + /** An option used in confirmation dialog methods. */ + public static final int YES_NO_CANCEL_OPTION = 1; - public void setUI(OptionPaneUI ui) { - super.setUI(ui); - } - - public OptionPaneUI getUI() { - return (OptionPaneUI)ui; - } - - public void updateUI() { - setUI((OptionPaneUI)UIManager.getUI(this)); - } + /** An option used in confirmation dialog methods. */ + public static final int YES_NO_OPTION = 0; + /** The value returned when the yes option is selected. */ + public static final int YES_OPTION = 0; - public AccessibleContext getAccessibleContext() - { - return null; - } - - protected String paramString() - { - return "JOptionPane"; - } - - public static void showMessageDialog(Component frame, - String msg, - String title, - int bla) - { - DoShowOptionDialog(frame, - msg, - title, - bla, - 0, - null, - null, - null); - } + /** Identifier for the error message type. */ + public static final int ERROR_MESSAGE = 0; - public static void showMessageDialog(Component frame, - String msg, - String title, - int bla, - Icon icon) - { - DoShowOptionDialog(frame, - msg, - title, - bla, - 0, - icon, - null, - null); - } + /** Identifier for the information message type. */ + public static final int INFORMATION_MESSAGE = 1; - public static void showMessageDialog(Component frame, - String msg) - { - showMessageDialog(frame, - msg, - null); - } - - - public static void showMessageDialog(Component frame, - String msg, - Icon icon) - { - //System.out.println("++++++++++++++++++creating message dialog:"+msg + ", frame="+frame); - DoShowOptionDialog(frame, - msg, - "Message", - DEFAULT_OPTION, - PLAIN_MESSAGE, - icon, - null, - null); - } + /** Identifier for the plain message type. */ + public static final int PLAIN_MESSAGE = -1; - public static int showConfirmDialog(JFrame frame, - String yes, - String no, - int bla) - { - return 0; - } + /** Identifier for the question message type. */ + public static final int QUESTION_MESSAGE = 3; - public static String showInputDialog(JFrame frame, - String msg, - String title, - int opt_type, - int msg_type, - Icon icon, - Object[] opts, - Object init) - { - return (String) DoShowOptionDialog(frame, - msg, - title, - opt_type, - msg_type, - icon, - opts, - init); - } + /** Identifier for the warning message type. */ + public static final int WARNING_MESSAGE = 2; - public static Object showInputDialog(JFrame frame, - String msg, - String title, - int opt_type, - Icon icon, - Object[] opts, - Object init) - { - return DoShowOptionDialog(frame, - msg, - title, - opt_type, - 0, //msg_type, - icon, - opts, - init); - } + /** + * The identifier for the propertyChangeEvent when the icon property + * changes. + */ + public static final String ICON_PROPERTY = "icon"; + /** + * The identifier for the propertyChangeEvent when the initialSelectionValue + * property changes. + */ + public static final String INITIAL_SELECTION_VALUE_PROPERTY = "initialSelectionValue"; - // everybody comes here eventually - public static int showOptionDialog(Component frame, - String msg, - String title, - int opt_type, - int msg_type, - Icon icon, - Object[] opts, - Object init) - { - Integer a = (Integer) DoShowOptionDialog(frame, - msg, - title, - opt_type, - msg_type, - icon, - opts, - init); - if (a == null) - return -1; - return a.intValue(); - } - - public static Object DoShowOptionDialog(Component frame, - String msg, - String title, - int opt_type, - int msg_type, - Icon icon, - Object[] opts, - Object init) - { - - JOptionPane p = new JOptionPane(msg, - msg_type, - opt_type, - icon, - opts, - init); - System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ " + p.msg); - - - JDialog a; - - if (frame == null) - { - a = new JDialog((Frame)frame, - title, - true); - } - else if (frame instanceof Dialog) - { - a = new JDialog((Dialog) frame, - title, - true); - } - else if (frame instanceof Frame) - { - a = new JDialog((Frame) frame, - title, - true); - } - else - { - System.out.println("HUUUUHHH, not a frame or dialog !"); - - a = new JDialog((Frame)null, - title, - true); - } - - p.dialog = a; - - a.getContentPane().setLayout(new BorderLayout()); - a.getContentPane().add(p, - BorderLayout.CENTER); - // package the deal - a.pack(); - - a.setVisible(true); - - Object s = p.getValue(); - - System.out.println("RESULT FROM DIALOG = " + s); - - if (s == null) - return null; - - return s; - } + /** + * The identifier for the propertyChangeEvent when the initialValue property + * changes. + */ + public static final String INITIAL_VALUE_PROPERTY = "initialValue"; -} + /** + * The identifier for the propertyChangeEvent when the inputValue property + * changes. + */ + public static final String INPUT_VALUE_PROPERTY = "inputValue"; + + /** + * The identifier for the propertyChangeEvent when the message property + * changes. + */ + public static final String MESSAGE_PROPERTY = "message"; + + /** + * The identifier for the propertyChangeEvent when the messageType property + * changes. + */ + public static final String MESSAGE_TYPE_PROPERTY = "messageType"; + + /** + * The identifier for the propertyChangeEvent when the optionType property + * changes. + */ + public static final String OPTION_TYPE_PROPERTY = "optionType"; + + /** + * The identifier for the propertyChangeEvent when the options property + * changes. + */ + public static final String OPTIONS_PROPERTY = "options"; + + /** + * The identifier for the propertyChangeEvent when the selectionValues + * property changes. + */ + public static final String SELECTION_VALUES_PROPERTY = "selectionValues"; + + /** + * The identifier for the propertyChangeEvent when the value property + * changes. + */ + public static final String VALUE_PROPERTY = "value"; + + /** + * The identifier for the propertyChangeEvent when the wantsInput property + * changes. + */ + public static final String WANTS_INPUT_PROPERTY = "wantsInput"; + + /** The value returned when the inputValue is uninitialized. */ + public static Object UNINITIALIZED_VALUE = "uninitializedValue"; + + /** The icon displayed in the dialog/internal frame. */ + protected Icon icon; + + /** The initial selected value in the input component. */ + protected Object initialSelectionValue; + + /** The object that is initially selected for options. */ + protected Object initialValue; + + /** The value the user inputs. */ + protected Object inputValue = UNINITIALIZED_VALUE; + + /** The message displayed in the dialog/internal frame. */ + protected Object message = "JOptionPane message"; + + /** The type of message displayed. */ + protected int messageType = PLAIN_MESSAGE; + + /** + * The options (usually buttons) aligned at the bottom for the user to + * select. + */ + protected Object[] options; + + /** The type of options to display. */ + protected int optionType = DEFAULT_OPTION; + + /** The input values the user can select. */ + protected Object[] selectionValues; + + /** The value returned by selecting an option. */ + protected Object value = UNINITIALIZED_VALUE; + + /** Whether the Dialog/InternalFrame needs input. */ + protected boolean wantsInput; + + /** The common frame used when no parent is provided. */ + private static Frame privFrame = SwingUtilities.getOwnerFrame(); + + /** + * Creates a new JOptionPane object using a message of "JOptionPane + * message", using the PLAIN_MESSAGE type and DEFAULT_OPTION. + */ + public JOptionPane() + { + this(this.message, PLAIN_MESSAGE, DEFAULT_OPTION, null, null, null); + } + /** + * Creates a new JOptionPane object using the given message using the + * PLAIN_MESSAGE type and DEFAULT_OPTION. + * + * @param message The message to display. + */ + public JOptionPane(Object message) + { + this(message, PLAIN_MESSAGE, DEFAULT_OPTION, null, null, null); + } + /** + * Creates a new JOptionPane object using the given message and messageType + * and DEFAULT_OPTION. + * + * @param message The message to display. + * @param messageType The type of message. + */ + public JOptionPane(Object message, int messageType) + { + this(message, messageType, DEFAULT_OPTION, null, null, null); + } + /** + * Creates a new JOptionPane object using the given message, messageType and + * optionType. + * + * @param message The message to display. + * @param messageType The type of message. + * @param optionType The type of options. + */ + public JOptionPane(Object message, int messageType, int optionType) + { + this(message, messageType, optionType, null, null, null); + } + /** + * Creates a new JOptionPane object using the given message, messageType, + * optionType and icon. + * + * @param message The message to display. + * @param messageType The type of message. + * @param optionType The type of options. + * @param icon The icon to display. + */ + public JOptionPane(Object message, int messageType, int optionType, Icon icon) + { + this(message, messageType, optionType, icon, null, null); + } + /** + * Creates a new JOptionPane object using the given message, messageType, + * optionType, icon and options. + * + * @param message The message to display. + * @param messageType The type of message. + * @param optionType The type of options. + * @param icon The icon to display. + * @param options The options given. + */ + public JOptionPane(Object message, int messageType, int optionType, + Icon icon, Object[] options) + { + this(message, messageType, optionType, icon, options, null); + } + /** + * Creates a new JOptionPane object using the given message, messageType, + * optionType, icon, options and initialValue. The initialValue will be + * focused initially. + * + * @param message The message to display. + * @param messageType The type of message. + * @param optionType The type of options. + * @param icon The icon to display. + * @param options The options given. + * @param initialValue The component to focus on initially. + * + * @throws IllegalArgumentException If the messageType or optionType are not + * legal values. + */ + public JOptionPane(Object message, int messageType, int optionType, + Icon icon, Object[] options, Object initialValue) + { + this.message = message; + if (! validMessageType(messageType)) + throw new IllegalArgumentException("Message Type not legal value."); + this.messageType = messageType; + if (! validOptionType(optionType)) + throw new IllegalArgumentException("Option Type not legal value."); + this.optionType = optionType; + this.icon = icon; + this.options = options; + this.initialValue = initialValue; + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + updateUI(); + invalidate(); + repaint(); + } + /** + * This method creates a new JDialog that is either centered around the + * parent's frame or centered on the screen (if the parent is null). The + * JDialog will not be resizable and will be modal. Once the JDialog is + * disposed, the inputValue and value properties will be set by the + * optionPane. + * + * @param parentComponent The parent of the Dialog. + * @param title The title in the bar of the JDialog. + * + * @return A new JDialog based on the JOptionPane configuration. + */ + public JDialog createDialog(Component parentComponent, String title) + { + Frame toUse = getFrameForComponent(parentComponent); + if (toUse == null) + toUse = getRootFrame(); + JDialog dialog = new JDialog(toUse, title); + inputValue = UNINITIALIZED_VALUE; + value = UNINITIALIZED_VALUE; + // FIXME: This dialog should be centered on the parent + // or at the center of the screen (if the parent is null) + // Need getGraphicsConfiguration to return non-null in + // order for that to work so we know how large the + // screen is. + dialog.getContentPane().add(this); + dialog.setModal(true); + dialog.setResizable(false); + return dialog; + } + /** + * This method creates a new JInternalFrame that is in the JDesktopPane + * which contains the parentComponent given. If no suitable JDesktopPane + * can be found from the parentComponent given, a RuntimeException will be + * thrown. + * + * @param parentComponent The parent to find a JDesktopPane from. + * @param title The title of the JInternalFrame. + * + * @return A new JInternalFrame based on the JOptionPane configuration. + * + * @throws RuntimeException If no suitable JDesktopPane is found. + */ + public JInternalFrame createInternalFrame(Component parentComponent, + String title) + throws RuntimeException + { + // FIXME: implement. + return null; + } + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJOptionPane(); + return accessibleContext; + } + /** + * This method returns the JDesktopPane for the given parentComponent or + * null if none can be found. + * + * @param parentComponent The component to look in. + * + * @return The JDesktopPane for the given component or null if none can be + * found. + */ + public static JDesktopPane getDesktopPaneForComponent(Component parentComponent) + { + if (parentComponent == null) + return null; + if (parentComponent instanceof JDesktopPane) + return (JDesktopPane) parentComponent; + JDesktopPane parent = null; + while (parentComponent.getParent() != null) + { + parentComponent = parentComponent.getParent(); + if (parentComponent instanceof JDesktopPane) + { + parent = (JDesktopPane) parentComponent; + break; + } + } + return parent; + } + /** + * This method returns the Frame for the given parentComponent or null if + * none can be found. + * + * @param parentComponent The component to look in. + * + * @return The Frame for the given component or null if none can be found. + */ + public static Frame getFrameForComponent(Component parentComponent) + { + if (parentComponent == null) + return null; + if (parentComponent instanceof Frame) + return (Frame) parentComponent; + Frame parent = null; + while (parentComponent.getParent() != null) + { + parentComponent = parentComponent.getParent(); + if (parentComponent instanceof Frame) + { + parent = (Frame) parentComponent; + break; + } + } + return parent; + } + /** + * This method returns the icon displayed. + * + * @return The icon displayed. + */ + public Icon getIcon() + { + return icon; + } + + /** + * This method returns the value initially selected from the list of values + * the user can input. + * + * @return The initial selection value. + */ + public Object getInitialSelectionValue() + { + return initialSelectionValue; + } + + /** + * This method returns the value that is focused from the list of options. + * + * @return The initial value from options. + */ + public Object getInitialValue() + { + return initialValue; + } + + /** + * This method returns the value that the user input. + * + * @return The user's input value. + */ + public Object getInputValue() + { + return inputValue; + } + + /** + * This method returns the maximum characters per line. By default, this is + * Integer.MAX_VALUE. + * + * @return The maximum characters per line. + */ + public int getMaxCharactersPerLineCount() + { + return Integer.MAX_VALUE; + } + + /** + * This method returns the message displayed. + * + * @return The message displayed. + */ + public Object getMessage() + { + return message; + } + + /** + * This method returns the message type. + * + * @return The message type. + */ + public int getMessageType() + { + return messageType; + } + + /** + * This method returns the options. + * + * @return The options. + */ + public Object[] getOptions() + { + return options; + } + + /** + * This method returns the option type. + * + * @return The option type. + */ + public int getOptionType() + { + return optionType; + } + + /** + * This method returns the Frame used by JOptionPane dialog's that have no + * parent. + * + * @return The Frame used by dialogs that have no parent. + */ + public static Frame getRootFrame() + { + return privFrame; + } + + /** + * This method returns the selection values. + * + * @return The selection values. + */ + public Object[] getSelectionValues() + { + return selectionValues; + } + + /** + * This method returns the UI used by the JOptionPane. + * + * @return The UI used by the JOptionPane. + */ + public OptionPaneUI getUI() + { + return (OptionPaneUI) ui; + } + + /** + * This method returns an identifier to determine which UI class will act as + * the UI. + * + * @return The UI identifier. + */ + public String getUIClassID() + { + return "OptionPaneUI"; + } + + /** + * This method returns the value that the user selected out of options. + * + * @return The value that the user selected out of options. + */ + public Object getValue() + { + return value; + } + + /** + * This method returns whether this JOptionPane wants input. + * + * @return Whether this JOptionPane wants input. + */ + public boolean getWantsInput() + { + return wantsInput; + } + + /** + * This method returns a String that describes this JOptionPane. + * + * @return A String that describes this JOptionPane. + */ + protected String paramString() + { + return "JOptionPane"; + } + + /** + * This method requests focus for the initial value. + */ + public void selectInitialValue() + { + if (ui != null) + ((OptionPaneUI) ui).selectInitialValue(this); + } + + /** + * This method changes the icon property. + * + * @param newIcon The new icon to use. + */ + public void setIcon(Icon newIcon) + { + if (icon != newIcon) + { + Icon old = icon; + icon = newIcon; + firePropertyChange(ICON_PROPERTY, old, icon); + } + } + + /** + * This method changes the initial selection property. + * + * @param newValue The new initial selection. + */ + public void setInitialSelectionValue(Object newValue) + { + if (initialSelectionValue != newValue) + { + Object old = initialSelectionValue; + initialSelectionValue = newValue; + firePropertyChange(INITIAL_SELECTION_VALUE_PROPERTY, old, + initialSelectionValue); + } + } + + /** + * This method changes the initial value property. + * + * @param newValue The new initial value. + */ + public void setInitialValue(Object newValue) + { + if (initialValue != newValue) + { + Object old = initialValue; + initialValue = newValue; + firePropertyChange(INITIAL_VALUE_PROPERTY, old, initialValue); + } + } + + /** + * This method changes the inputValue property. + * + * @param newValue The new inputValue. + */ + public void setInputValue(Object newValue) + { + if (inputValue != newValue) + { + Object old = inputValue; + inputValue = newValue; + firePropertyChange(INPUT_VALUE_PROPERTY, old, inputValue); + } + } + + /** + * This method changes the message property. + * + * @param newMessage The new message. + */ + public void setMessage(Object newMessage) + { + if (message != newMessage) + { + Object old = message; + message = newMessage; + firePropertyChange(MESSAGE_PROPERTY, old, message); + } + } + + /** + * This method changes the messageType property. + * + * @param newType The new messageType. + * + * @throws IllegalArgumentException If the messageType is not valid. + */ + public void setMessageType(int newType) + { + if (! validMessageType(newType)) + throw new IllegalArgumentException("Message Type not legal value."); + if (newType != messageType) + { + int old = messageType; + messageType = newType; + firePropertyChange(MESSAGE_TYPE_PROPERTY, old, messageType); + } + } + + /** + * This method changes the options property. + * + * @param newOptions The new options. + */ + public void setOptions(Object[] newOptions) + { + if (options != newOptions) + { + Object[] old = options; + options = newOptions; + firePropertyChange(OPTIONS_PROPERTY, old, options); + } + } + + /** + * This method changes the optionType property. + * + * @param newType The new optionType. + * + * @throws IllegalArgumentException If the optionType is not valid. + */ + public void setOptionType(int newType) + { + if (! validOptionType(newType)) + throw new IllegalArgumentException("Option Type not legal value."); + if (newType != optionType) + { + int old = optionType; + optionType = newType; + firePropertyChange(OPTION_TYPE_PROPERTY, old, optionType); + } + } + + /** + * This method changes the Frame used for JOptionPane dialogs that have no + * parent. + * + * @param newRootFrame The Frame to use for dialogs that have no parent. + */ + public static void setRootFrame(Frame newRootFrame) + { + privFrame = newRootFrame; + } + + /** + * This method changes the selectionValues property. + * + * @param newValues The new selectionValues. + */ + public void setSelectionValues(Object[] newValues) + { + if (newValues != selectionValues) + { + if (newValues != null) + wantsInput = true; + Object[] old = selectionValues; + selectionValues = newValues; + firePropertyChange(SELECTION_VALUES_PROPERTY, old, selectionValues); + } + } + + /** + * This method sets the UI used with the JOptionPane. + * + * @param ui The UI used with the JOptionPane. + */ + public void setUI(OptionPaneUI ui) + { + super.setUI(ui); + } + + /** + * This method sets the value has been selected out of options. + * + * @param newValue The value that has been selected out of options. + */ + public void setValue(Object newValue) + { + if (value != newValue) + { + Object old = value; + value = newValue; + firePropertyChange(VALUE_PROPERTY, old, value); + } + } + + /** + * This method changes the wantsInput property. + * + * @param newValue Whether this JOptionPane requires input. + */ + public void setWantsInput(boolean newValue) + { + if (wantsInput != newValue) + { + boolean old = wantsInput; + wantsInput = newValue; + firePropertyChange(WANTS_INPUT_PROPERTY, old, wantsInput); + } + } + + /** + * This method shows a confirmation dialog with the title "Select an Option" + * and displays the given message. The parent frame will be the same as the + * parent frame of the given parentComponent. This method returns the + * option chosen by the user. + * + * @param parentComponent The parentComponent to find a frame in. + * @param message The message to display. + * + * @return The option that was selected. + */ + public static int showConfirmDialog(Component parentComponent, Object message) + { + JOptionPane pane = new JOptionPane(message); + JDialog dialog = pane.createDialog(parentComponent, "Select an Option"); + dialog.pack(); + dialog.show(); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method shows a confirmation dialog with the given message, + * optionType and title. The frame that owns the dialog will be the same + * frame that holds the given parentComponent. This method returns the + * option that was chosen. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param optionType The optionType. + * + * @return The option that was chosen. + */ + public static int showConfirmDialog(Component parentComponent, + Object message, String title, + int optionType) + { + JOptionPane pane = new JOptionPane(message, PLAIN_MESSAGE, optionType); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method shows a confirmation dialog with the given message, title, + * messageType and optionType. The frame owner will be the same frame as + * the one that holds the given parentComponent. This method returns the + * option selected by the user. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param optionType The optionType. + * @param messageType The messageType. + * + * @return The selected option. + */ + public static int showConfirmDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType) + { + JOptionPane pane = new JOptionPane(message, messageType, optionType); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method shows a confirmation dialog with the given message, title, + * optionType, messageType and icon. The frame owner will be the same as + * the one that holds the given parentComponent. This method returns the + * option selected by the user. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param optionType The optionType. + * @param messageType The messsageType. + * @param icon The icon displayed. + * + * @return The selected option. + */ + public static int showConfirmDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType, + Icon icon) + { + JOptionPane pane = new JOptionPane(message, messageType, optionType, icon); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method will show a QUESTION_MESSAGE input dialog with the given + * message. No selectionValues is set so the Look and Feel will usually + * give the user a TextField to fill out. The frame owner will be the same + * frame that holds the given parentComponent. This method will return the + * value entered by the user. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * + * @return The value entered by the user. + */ + public static String showInputDialog(Component parentComponent, + Object message) + { + JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE); + pane.setWantsInput(true); + JDialog dialog = pane.createDialog(parentComponent, null); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * This method will show a QUESTION_MESSAGE type input dialog with the given + * message and initialSelectionValue. Since there is no selectionValues + * set, the Look and Feel will usually give a TextField to fill out. The + * frame owner will be the same as the one that holds the given + * parentComponent. This method will return the value entered by the user. + * + * @param parentComponent The component to find a frame in. + * @param message The message to display. + * @param initialSelectionValue The initially selected value. + * + * @return The value the user input. + */ + public static String showInputDialog(Component parentComponent, + Object message, + Object initialSelectionValue) + { + JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE); + pane.setInitialSelectionValue(initialSelectionValue); + pane.setWantsInput(true); + JDialog dialog = pane.createDialog(parentComponent, null); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * This method displays a new input dialog with the given message, title and + * messageType. Since no selectionValues value is given, the Look and Feel + * will usually give the user a TextField to input data to. This method + * returns the value the user inputs. + * + * @param parentComponent The component to find a frame in. + * @param message The message to display. + * @param title The title of the dialog. + * @param messageType The messageType. + * + * @return The value the user input. + */ + public static String showInputDialog(Component parentComponent, + Object message, String title, + int messageType) + { + JOptionPane pane = new JOptionPane(message, messageType); + pane.setWantsInput(true); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * This method shows an input dialog with the given message, title, + * messageType, icon, selectionValues, and initialSelectionValue. This + * method returns the value that the user selects. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param messageType The messageType. + * @param icon The icon displayed. + * @param selectionValues The list of values to select from. + * @param initialSelectionValue The initially selected value. + * + * @return The user selected value. + */ + public static Object showInputDialog(Component parentComponent, + Object message, String title, + int messageType, Icon icon, + Object[] selectionValues, + Object initialSelectionValue) + { + JOptionPane pane = new JOptionPane(message, messageType); + pane.setWantsInput(true); + pane.setIcon(icon); + pane.setSelectionValues(selectionValues); + pane.setInitialSelectionValue(initialSelectionValue); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * This method shows a QUESTION_MESSAGE type input dialog. Since no + * selectionValues is set, the Look and Feel will usually give the user a + * TextField to input data to. This method returns the value the user + * inputs. + * + * @param message The message to display. + * + * @return The user selected value. + */ + public static String showInputDialog(Object message) + { + JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE); + pane.setWantsInput(true); + JDialog dialog = pane.createDialog(null, null); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * This method shows a QUESTION_MESSAGE type input dialog. Since no + * selectionValues is set, the Look and Feel will usually give the user a + * TextField to input data to. The input component will be initialized with + * the initialSelectionValue. This method returns the value the user + * inputs. + * + * @param message The message to display. + * @param initialSelectionValue The initialSelectionValue. + * + * @return The user selected value. + */ + public static String showInputDialog(Object message, + Object initialSelectionValue) + { + JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE); + pane.setWantsInput(true); + pane.setInitialSelectionValue(initialSelectionValue); + JDialog dialog = pane.createDialog(null, null); + dialog.pack(); + dialog.show(); + + return (String) pane.getInputValue(); + } + + /** + * DOCUMENT ME! + * + * @param parentComponent DOCUMENT ME! + * @param message DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static int showInternalConfirmDialog(Component parentComponent, + Object message) + { + // FIXME: implement + return 0; + } + + /** + * DOCUMENT ME! + * + * @param parentComponent DOCUMENT ME! + * @param message DOCUMENT ME! + * @param title DOCUMENT ME! + * @param optionType DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static int showInternalConfirmDialog(Component parentComponent, + Object message, String title, + int optionType) + { + // FIXME: implement + return 0; + } + + /** + * DOCUMENT ME! + * + * @param parentComponent DOCUMENT ME! + * @param message DOCUMENT ME! + * @param title DOCUMENT ME! + * @param optionType DOCUMENT ME! + * @param messageType DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static int showInternalConfirmDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType) + { + // FIXME: implement + return 0; + } + + /** + * DOCUMENT ME! + * + * @param parentComponent DOCUMENT ME! + * @param message DOCUMENT ME! + * @param title DOCUMENT ME! + * @param optionType DOCUMENT ME! + * @param messageType DOCUMENT ME! + * @param icon DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static int showInternalConfirmDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType, + Icon icon) + { + // FIXME: implement + return 0; + } + + /** + * DOCUMENT ME! + * + * @param parentComponent DOCUMENT ME! + * @param message DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static String showInternalInputDialog(Component parentComponent, + Object message) + { + // FIXME: implement + return null; + } + + /** + * DOCUMENT ME! + * + * @param parentComponent DOCUMENT ME! + * @param message DOCUMENT ME! + * @param title DOCUMENT ME! + * @param messageType DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static String showInternalInputDialog(Component parentComponent, + Object message, String title, + int messageType) + { + // FIXME: implement + return null; + } + + /** + * DOCUMENT ME! + * + * @param parentComponent DOCUMENT ME! + * @param message DOCUMENT ME! + * @param title DOCUMENT ME! + * @param messageType DOCUMENT ME! + * @param icon DOCUMENT ME! + * @param selectionValues DOCUMENT ME! + * @param initialSelectionValue DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static Object showInternalInputDialog(Component parentComponent, + Object message, String title, + int messageType, Icon icon, + Object[] selectionValues, + Object initialSelectionValue) + { + // FIXME: implement + return null; + } + + /** + * DOCUMENT ME! + * + * @param parentComponent DOCUMENT ME! + * @param message DOCUMENT ME! + */ + public static void showInternalMessageDialog(Component parentComponent, + Object message) + { + // FIXME: implement + } + + /** + * DOCUMENT ME! + * + * @param parentComponent DOCUMENT ME! + * @param message DOCUMENT ME! + * @param title DOCUMENT ME! + * @param messageType DOCUMENT ME! + */ + public static void showInternalMessageDialog(Component parentComponent, + Object message, String title, + int messageType) + { + // FIXME: implement + } + + /** + * DOCUMENT ME! + * + * @param parentComponent DOCUMENT ME! + * @param message DOCUMENT ME! + * @param title DOCUMENT ME! + * @param messageType DOCUMENT ME! + * @param icon DOCUMENT ME! + */ + public static void showInternalMessageDialog(Component parentComponent, + Object message, String title, + int messageType, Icon icon) + { + // FIXME: implement + } + + /** + * DOCUMENT ME! + * + * @param parentComponent DOCUMENT ME! + * @param message DOCUMENT ME! + * @param title DOCUMENT ME! + * @param optionType DOCUMENT ME! + * @param messageType DOCUMENT ME! + * @param icon DOCUMENT ME! + * @param options DOCUMENT ME! + * @param initialValue DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static int showInternalOptionDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType, + Icon icon, Object[] options, + Object initialValue) + { + // FIXME: implement + return 0; + } + + /** + * This method shows an INFORMATION_MESSAGE type message dialog. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + */ + public static void showMessageDialog(Component parentComponent, + Object message) + { + JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE); + JDialog dialog = pane.createDialog(parentComponent, null); + dialog.pack(); + dialog.show(); + } + + /** + * This method shows a message dialog with the given message, title and + * messageType. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param messageType The messageType. + */ + public static void showMessageDialog(Component parentComponent, + Object message, String title, + int messageType) + { + JOptionPane pane = new JOptionPane(message, messageType); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + } + + /** + * This method shows a message dialog with the given message, title, + * messageType and icon. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param messageType The messageType. + * @param icon The icon displayed. + */ + public static void showMessageDialog(Component parentComponent, + Object message, String title, + int messageType, Icon icon) + { + JOptionPane pane = new JOptionPane(message, messageType); + pane.setIcon(icon); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + } + + /** + * This method shows an option dialog with the given message, title, + * optionType, messageType, icon, options and initialValue. This method + * returns the option that was selected. + * + * @param parentComponent The component to find a frame in. + * @param message The message displayed. + * @param title The title of the dialog. + * @param optionType The optionType. + * @param messageType The messageType. + * @param icon The icon displayed. + * @param options The options to choose from. + * @param initialValue The initial value. + * + * @return The selected option. + */ + public static int showOptionDialog(Component parentComponent, + Object message, String title, + int optionType, int messageType, + Icon icon, Object[] options, + Object initialValue) + { + JOptionPane pane = new JOptionPane(message, messageType, optionType, icon, + options, initialValue); + JDialog dialog = pane.createDialog(parentComponent, title); + dialog.pack(); + dialog.show(); + + return ((Integer) pane.getValue()).intValue(); + } + + /** + * This method resets the UI to the Look and Feel default. + */ + public void updateUI() + { + setUI((OptionPaneUI) UIManager.getUI(this)); + invalidate(); + } + + /** + * This method returns true if the key is a valid messageType. + * + * @param key The key to check. + * + * @return True if key is valid. + */ + private boolean validMessageType(int key) + { + switch (key) + { + case ERROR_MESSAGE: + case INFORMATION_MESSAGE: + case PLAIN_MESSAGE: + case QUESTION_MESSAGE: + case WARNING_MESSAGE: + return true; + } + return false; + } + + /** + * This method returns true if the key is a valid optionType. + * + * @param key The key to check. + * + * @return True if key is valid. + */ + private boolean validOptionType(int key) + { + switch (key) + { + case DEFAULT_OPTION: + case OK_CANCEL_OPTION: + case YES_NO_CANCEL_OPTION: + case YES_NO_OPTION: + return true; + } + return false; + } +} diff --git a/libjava/javax/swing/JPopupMenu.java b/libjava/javax/swing/JPopupMenu.java index 1a7c7c680c2..7aa54fb8d1f 100644 --- a/libjava/javax/swing/JPopupMenu.java +++ b/libjava/javax/swing/JPopupMenu.java @@ -1,4 +1,4 @@ -/* JPopupMenu.java -- +/* JPopupMenu.java Copyright (C) 2002, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,639 +37,975 @@ exception statement from your version. */ package javax.swing; +import java.awt.BorderLayout; import java.awt.Component; +import java.awt.Container; import java.awt.Dimension; +import java.awt.Frame; import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Window; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.util.EventListener; +import java.util.Vector; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; +import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import javax.swing.plaf.PopupMenuUI; + /** - * JPopupMenu - * @author Andrew Selkirk - * @version 1.0 + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.3 $ */ public class JPopupMenu extends JComponent implements Accessible, MenuElement { - - //------------------------------------------------------------- - // Classes ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * Separator - */ - public static class Separator extends JSeparator { - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor Separator - */ - public Separator() { - // TODO - } // Separator() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * getUIClassID - * @returns String - */ - public String getUIClassID() { - return null; // TODO - } // getUIClassID() - - - } // Separator - - /** - * AccessibleJPopupMenu - */ - protected class AccessibleJPopupMenu extends AccessibleJComponent { - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor AccessibleJPopupMenu - * @param component TODO - */ - protected AccessibleJPopupMenu(JPopupMenu component) { - super(component); - // TODO - } // AccessibleJPopupMenu() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * getAccessibleRole - * @returns AccessibleRole - */ - public AccessibleRole getAccessibleRole() { - return AccessibleRole.POPUP_MENU; - } // getAccessibleRole() - - - } // AccessibleJPopupMenu - - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * uiClassID - */ - private static final String uiClassID = "PopupMenuUI"; - - /** - * invoker - */ - transient Component invoker; - - /** - * desiredLocationX - */ - private int desiredLocationX; - - /** - * desiredLocationY - */ - private int desiredLocationY; - - /** - * label - */ - private String label; - - /** - * paintBorder - */ - private boolean paintBorder; - - /** - * margin - */ - private Insets margin; - - /** - * defaultLWPopupEnabledKey - */ - private static final Object defaultLWPopupEnabledKey = null; // TODO - - /** - * lightWeightPopupEnabled - */ - private boolean lightWeightPopupEnabled; - - /** - * selectionModel - */ - private SingleSelectionModel selectionModel; - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor JPopupMenu - */ - public JPopupMenu() { - // TODO - } // JPopupMenu() - - /** - * Constructor JPopupMenu - * @param label TODO - */ - public JPopupMenu(String label) { - // TODO - } // JPopupMenu() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * readObject - * @param stream TODO - * @exception IOException TODO - * @exception ClassNotFoundException TODO - */ - private void readObject(ObjectInputStream stream) - throws IOException, ClassNotFoundException { - // TODO - } // readObject() - - /** - * writeObject - * @param stream TODO - * @exception IOException TODO - */ - private void writeObject(ObjectOutputStream stream) throws IOException { - // TODO - } // writeObject() - - /** - * add - * @param item TODO - * @returns JMenuItem - */ - public JMenuItem add(JMenuItem item) { - return null; // TODO - } // add() - - /** - * add - * @param text TODO - * @returns JMenuItem - */ - public JMenuItem add(String text) { - return null; // TODO - } // add() - - /** - * add - * @param action TODO - * @returns JMenuItem - */ - public JMenuItem add(Action action) { - return null; // TODO - } // add() - - /** - * remove - * @param index TODO - */ - public void remove(int index) { - // TODO - } // remove() - - /** - * insert - * @param action TODO - * @param index TODO - */ - public void insert(Action action, int index) { - // TODO - } // insert() - - /** - * insert - * @param component TODO - * @param index TODO - */ - public void insert(Component component, int index) { - // TODO - } // insert() - - /** - * paintBorder - * @param graphics TODO - */ - protected void paintBorder(Graphics graphics) { - // TODO - } // paintBorder() - - /** - * getDefaultLightWeightPopupEnabled - * @returns boolean - */ - public static boolean getDefaultLightWeightPopupEnabled() { - return false; // TODO - } // getDefaultLightWeightPopupEnabled() - - /** - * setDefaultLightWeightPopupEnabled - * @param enabled TODO - */ - public static void setDefaultLightWeightPopupEnabled(boolean enabled) { - // TODO - } // setDefaultLightWeightPopupEnabled() - - /** - * getUI - * @returns PopupMenuUI - */ - public PopupMenuUI getUI() { - return (PopupMenuUI) ui; - } // getUI() - - /** - * setUI - * @param ui TODO - */ - public void setUI(PopupMenuUI ui) { - super.setUI(ui); - // TODO - } // setUI() - - /** - * updateUI - */ - public void updateUI() { - setUI((PopupMenuUI) UIManager.get(this)); - invalidate(); - } // updateUI() - - /** - * getUIClassID - * @returns String - */ - public String getUIClassID() { - return uiClassID; - } // getUIClassID() - - /** - * getSelectionModel - * @returns SingleSelectionModel - */ - public SingleSelectionModel getSelectionModel() { - return null; // TODO - } // getSelectionModel() - - /** - * setSelectionModel - * @param model TODO - */ - public void setSelectionModel(SingleSelectionModel model) { - // TODO - } // setSelectionModel() - - /** - * createActionComponent - * @param action TODO - * @returns JMenuItem - */ - protected JMenuItem createActionComponent(Action action) { - return null; // TODO - } // createActionComponent() - - /** - * createActionChangeListener - * @param item TODO - * @returns PropertyChangeListener - */ - protected PropertyChangeListener createActionChangeListener(JMenuItem item) { - return null; // TODO - } // createActionChangeListener() - - /** - * isLightWeightPopupEnabled - * @returns boolean - */ - public boolean isLightWeightPopupEnabled() { - return false; // TODO - } // isLightWeightPopupEnabled() - - /** - * setLightWeightPopupEnabled - * @param enabled TODO - */ - public void setLightWeightPopupEnabled(boolean enabled) { - // TODO - } // setLightWeightPopupEnabled() - - /** - * getLabel - * @returns String - */ - public String getLabel() { - return null; // TODO - } // getLabel() - - /** - * setLabel - * @param label TODO - */ - public void setLabel(String label) { - // TODO - } // setLabel() - - /** - * addSeparator - */ - public void addSeparator() { - // TODO - } // addSeparator() - - /** - * addPopupMenuListener - * @param listener TODO - */ - public void addPopupMenuListener(PopupMenuListener listener) { - // TODO - } // addPopupMenuListener() - - /** - * removePopupMenuListener - * @param listener TODO - */ - public void removePopupMenuListener(PopupMenuListener listener) { - // TODO - } // removePopupMenuListener() - - /** - * firePopupMenuWillBecomeVisible - */ - protected void firePopupMenuWillBecomeVisible() { - // TODO - } // firePopupMenuWillBecomeVisible() - - /** - * firePopupMenuWillBecomeInvisible - */ - protected void firePopupMenuWillBecomeInvisible() { - // TODO - } // firePopupMenuWillBecomeInvisible() - - /** - * firePopupMenuCanceled - */ - protected void firePopupMenuCanceled() { - // TODO - } // firePopupMenuCanceled() - - /** - * pack - */ - public void pack() { - // TODO - } // pack() - - /** - * isVisible - * @returns boolean - */ - public boolean isVisible() { - return false; // TODO - } // isVisible() - - /** - * setVisible - * @param visible TODO - */ - public void setVisible(boolean visible) { - // TODO - } // setVisible() - - /** - * setLocation - * @param x TODO - * @param y TODO - */ - public void setLocation(int x, int y) { - // TODO - } // setLocation() - - /** - * isPopupMenu - * @returns boolean - */ - private boolean isPopupMenu() { - return false; // TODO - } // isPopupMenu() - - /** - * getInvoker - * @returns Component - */ - public Component getInvoker() { - return null; // TODO - } // getInvoker() - - /** - * setInvoker - * @param component TODO - */ - public void setInvoker(Component component) { - // TODO - } // setInvoker() - - /** - * show - * @param component TODO - * @param x TODO - * @param y TODO - */ - public void show(Component component, int x, int y) { - // TODO - } // show() - - /** - * getRootPopupMenu - * @returns JPopupMenu - */ - JPopupMenu getRootPopupMenu() { - return null; // TODO - } // getRootPopupMenu() - - /** - * getComponentAtIndex - * @param index TODO - * @returns Component - */ - public Component getComponentAtIndex(int index) { - return null; // TODO - } // getComponentAtIndex() - - /** - * getComponentIndex - * @param component TODO - * @returns int - */ - public int getComponentIndex(Component component) { - return 0; // TODO - } // getComponentIndex() - - /** - * setPopupSize - * @param size TODO - */ - public void setPopupSize(Dimension size) { - // TODO - } // setPopupSize() - - /** - * setPopupSize - * @param x TODO - * @param y TODO - */ - public void setPopupSize(int x, int y) { - // TODO - } // setPopupSize() - - /** - * setSelected - * @param selected TODO - */ - public void setSelected(Component selected) { - // TODO - } // setSelected() - - /** - * isBorderPainted - * @returns boolean - */ - public boolean isBorderPainted() { - return false; // TODO - } // isBorderPainted() - - /** - * setBorderPainted - * @param painted TODO - */ - public void setBorderPainted(boolean painted) { - // TODO - } // setBorderPainted() - - /** - * getMargin - * @returns Insets - */ - public Insets getMargin() { - return null; // TODO - } // getMargin() - - /** - * paramString - * @returns String - */ - protected String paramString() { - return null; // TODO - } // paramString() - - /** - * processMouseEvent - * @param event TODO - * @param path TODO - * @param manager TODO - */ - public void processMouseEvent(MouseEvent event, MenuElement[] path, - MenuSelectionManager manager) { - // TODO - } // processMouseEvent() - - /** - * processKeyEvent - * @param event TODO - * @param path TODO - * @param manager TODO - */ - public void processKeyEvent(KeyEvent event, MenuElement[] path, - MenuSelectionManager manager) { - // TODO - } // processKeyEvent() - - /** - * menuSelectionChanged - * @param changed TODO - */ - public void menuSelectionChanged(boolean changed) { - // TODO - } // menuSelectionChanged() - - /** - * getSubElements - * @returns MenuElement[] - */ - public MenuElement[] getSubElements() { - return null; // TODO - } // getSubElements() - - /** - * getComponent - * @returns Component - */ - public Component getComponent() { - return null; // TODO - } // getComponent() - - /** - * isPopupTrigger - * @param event TODO - * @returns boolean - */ - public boolean isPopupTrigger(MouseEvent event) { - return false; // TODO - } // isPopupTrigger() - - /** - * getAccessibleContext - * @returns AccessibleContext - */ - public AccessibleContext getAccessibleContext() { - if (accessibleContext == null) { - accessibleContext = new AccessibleJPopupMenu(this); - } // if - return accessibleContext; - } // getAccessibleContext() - - -} // JPopupMenu + private static final String uiClassID = "PopupMenuUI"; + private static final Object defaultLWPopupEnabledKey = null; + private static boolean defaultLWPopupEnabled = true; + transient Component invoker; + private int locationX; + private int locationY; + private String label; + private boolean paintBorder; + private Insets margin; + private boolean lightWeightPopupEnabled; + private SingleSelectionModel selectionModel; + private transient Popup popup; + private Point location; + + /** + * Creates a new JPopupMenu object. + */ + public JPopupMenu() + { + updateUI(); + + lightWeightPopupEnabled = defaultLWPopupEnabled; + selectionModel = new DefaultSingleSelectionModel(); + } + + /** + * Creates a new JPopupMenu object. + * + * @param label DOCUMENT ME! + */ + public JPopupMenu(String label) + { + this.label = label; + } + + /** + * DOCUMENT ME! + * + * @param stream DOCUMENT ME! + * + * @throws IOException DOCUMENT ME! + * @throws ClassNotFoundException DOCUMENT ME! + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + } + + /** + * DOCUMENT ME! + * + * @param stream DOCUMENT ME! + * + * @throws IOException DOCUMENT ME! + */ + private void writeObject(ObjectOutputStream stream) throws IOException + { + } + + /** + * DOCUMENT ME! + * + * @param item DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenuItem add(JMenuItem item) + { + this.insert(item, -1); + return item; + } + + /** + * DOCUMENT ME! + * + * @param text DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenuItem add(String text) + { + JMenuItem item = new JMenuItem(text); + return add(item); + } + + /** + * DOCUMENT ME! + * + * @param action DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JMenuItem add(Action action) + { + JMenuItem item = new JMenuItem(action); + return add(item); + } + + /** + * DOCUMENT ME! + * + * @param index DOCUMENT ME! + */ + public void remove(int index) + { + super.remove(index); + + GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = 100.0; + constraints.weighty = 100.0; + + Component[] items = getComponents(); + for (int i = index; i < items.length; i++) + { + constraints.gridy = i; + super.add(items[i], constraints, i); + } + } + + /** + * DOCUMENT ME! + * + * @param action DOCUMENT ME! + * @param index DOCUMENT ME! + */ + public void insert(Action action, int index) + { + JMenuItem item = new JMenuItem(action); + this.insert(item, index); + } + + /** + * DOCUMENT ME! + * + * @param component DOCUMENT ME! + * @param index DOCUMENT ME! + */ + public void insert(Component component, int index) + { + GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = 100.0; + constraints.weighty = 100.0; + + if (index == -1) + index = getComponents().length; + + constraints.gridy = index; + super.add(component, constraints, index); + + // need to change constraints for the components that were moved by 1 + // due to the insertion + if (index != -1) + { + Component[] items = getComponents(); + + for (int i = index + 1; i < items.length; i++) + { + constraints.gridy = i; + super.add(items[i], constraints, i); + } + } + } + + /** + * DOCUMENT ME! + * + * @param graphics DOCUMENT ME! + */ + protected void paintBorder(Graphics graphics) + { + if (paintBorder) + getBorder().paintBorder(this, graphics, 0, 0, getSize(null).width, + getSize(null).height); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static boolean getDefaultLightWeightPopupEnabled() + { + return defaultLWPopupEnabled; + } + + /** + * DOCUMENT ME! + * + * @param enabled DOCUMENT ME! + */ + public static void setDefaultLightWeightPopupEnabled(boolean enabled) + { + defaultLWPopupEnabled = enabled; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public PopupMenuUI getUI() + { + return (PopupMenuUI) ui; + } + + /** + * DOCUMENT ME! + * + * @param ui DOCUMENT ME! + */ + public void setUI(PopupMenuUI ui) + { + super.setUI(ui); + } + + /** + * DOCUMENT ME! + */ + public void updateUI() + { + setUI((PopupMenuUI) UIManager.getUI(this)); + invalidate(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getUIClassID() + { + return "PopupMenuUI"; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public SingleSelectionModel getSelectionModel() + { + return selectionModel; + } + + /** + * DOCUMENT ME! + * + * @param model DOCUMENT ME! + */ + public void setSelectionModel(SingleSelectionModel model) + { + if (selectionModel != model) + { + SingleSelectionModel oldModel = this.selectionModel; + } + } + + /** + * DOCUMENT ME! + * + * @param action DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected JMenuItem createActionComponent(Action action) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param item DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected PropertyChangeListener createActionChangeListener(JMenuItem item) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isLightWeightPopupEnabled() + { + return lightWeightPopupEnabled; + } + + /** + * DOCUMENT ME! + * + * @param enabled DOCUMENT ME! + */ + public void setLightWeightPopupEnabled(boolean enabled) + { + lightWeightPopupEnabled = enabled; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getLabel() + { + return label; + } + + /** + * DOCUMENT ME! + * + * @param label DOCUMENT ME! + */ + public void setLabel(String label) + { + this.label = label; + } + + /** + * DOCUMENT ME! + */ + public void addSeparator() + { + } + + /** + * DOCUMENT ME! + * + * @param listener DOCUMENT ME! + */ + public void addPopupMenuListener(PopupMenuListener listener) + { + listenerList.add(PopupMenuListener.class, listener); + } + + /** + * DOCUMENT ME! + * + * @param listener DOCUMENT ME! + */ + public void removePopupMenuListener(PopupMenuListener listener) + { + listenerList.remove(PopupMenuListener.class, listener); + } + + /** + * DOCUMENT ME! + */ + protected void firePopupMenuWillBecomeVisible() + { + EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); + + for (int i = 0; i < ll.length; i++) + ((PopupMenuListener) ll[i]).popupMenuWillBecomeVisible(new PopupMenuEvent(this)); + } + + /** + * DOCUMENT ME! + */ + protected void firePopupMenuWillBecomeInvisible() + { + EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); + + for (int i = 0; i < ll.length; i++) + ((PopupMenuListener) ll[i]).popupMenuWillBecomeInvisible(new PopupMenuEvent(this)); + } + + /** + * DOCUMENT ME! + */ + protected void firePopupMenuCanceled() + { + EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); + + for (int i = 0; i < ll.length; i++) + ((PopupMenuListener) ll[i]).popupMenuCanceled(new PopupMenuEvent(this)); + } + + /** + * DOCUMENT ME! + */ + public void pack() + { + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isVisible() + { + return super.visible; + } + + /** + * DOCUMENT ME! + * + * @param visible DOCUMENT ME! + */ + public void setVisible(boolean visible) + { + super.visible = visible; + + firePopupMenuWillBecomeVisible(); + + if (visible) + { + Container rootContainer = (Container) SwingUtilities.getRoot(invoker); + + boolean fit = true; + Dimension size; + + // Determine the size of the popup menu + if (this.getSize().width == 0 && this.getSize().width == 0) + size = this.getPreferredSize(); + else + size = this.getSize(); + + if ((size.width > (rootContainer.getWidth() - locationX)) + || (size.height > (rootContainer.getHeight() - locationY))) + fit = false; + + if (lightWeightPopupEnabled && fit) + popup = new LightWeightPopup(this); + else + { + if (fit) + popup = new MediumWeightPopup(this); + else + popup = new HeavyWeightPopup(this); + } + + if (popup instanceof LightWeightPopup + || popup instanceof MediumWeightPopup) + { + JLayeredPane layeredPane; + layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); + Point lp = layeredPane.getLocationOnScreen(); + Point r = SwingUtilities.getRoot(invoker).getLocationOnScreen(); + int px = locationX - (lp.x - r.x); + int py = locationY - (lp.y - r.y); + popup.show(px, py, size.width, size.height); + } + else + popup.show(locationX, locationY, size.width, size.height); + } + else + { + firePopupMenuWillBecomeInvisible(); + popup.hide(); + } + } + + /** + * DOCUMENT ME! + * + * @param x DOCUMENT ME! + * @param y DOCUMENT ME! + */ + public void setLocation(int x, int y) + { + locationX = x; + locationY = y; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private boolean isPopupMenu() + { + return true; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component getInvoker() + { + return invoker; + } + + /** + * DOCUMENT ME! + * + * @param component DOCUMENT ME! + */ + public void setInvoker(Component component) + { + invoker = component; + } + + /** + * DOCUMENT ME! + * + * @param component DOCUMENT ME! + * @param x DOCUMENT ME! + * @param y DOCUMENT ME! + */ + public void show(Component component, int x, int y) + { + setInvoker(component); + + Point rootOnScreen; + rootOnScreen = SwingUtilities.getRoot(invoker).getLocationOnScreen(); + Point invokerOnScreen = invoker.getLocationOnScreen(); + + int popupX = (invokerOnScreen.x - rootOnScreen.x) + x; + int popupY = (invokerOnScreen.y - rootOnScreen.y) + y; + + setLocation(popupX , popupY); + setVisible(true); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + JPopupMenu getRootPopupMenu() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param index DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component getComponentAtIndex(int index) + { + return getComponent(index); + } + + /** + * DOCUMENT ME! + * + * @param component DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getComponentIndex(Component component) + { + Component[] items = getComponents(); + + for (int i = 0; i < items.length; i++) + { + if (items[i].equals(component)) + return i; + } + + return -1; + } + + /** + * DOCUMENT ME! + * + * @param size DOCUMENT ME! + */ + public void setPopupSize(Dimension size) + { + super.setSize(size); + } + + /** + * DOCUMENT ME! + * + * @param x DOCUMENT ME! + * @param y DOCUMENT ME! + */ + public void setPopupSize(int x, int y) + { + super.setSize(x, y); + } + + /** + * DOCUMENT ME! + * + * @param selected DOCUMENT ME! + */ + public void setSelected(Component selected) + { + int index = getComponentIndex(selected); + selectionModel.setSelectedIndex(index); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isBorderPainted() + { + return paintBorder; + } + + /** + * DOCUMENT ME! + * + * @param painted DOCUMENT ME! + */ + public void setBorderPainted(boolean painted) + { + paintBorder = painted; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Insets getMargin() + { + return margin; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected String paramString() + { + return "JPopupMenu"; + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ + public void processMouseEvent(MouseEvent event, MenuElement[] path, + MenuSelectionManager manager) + { + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ + public void processKeyEvent(KeyEvent event, MenuElement[] path, + MenuSelectionManager manager) + { + } + + /** + * DOCUMENT ME! + * + * @param changed DOCUMENT ME! + */ + public void menuSelectionChanged(boolean changed) + { + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public MenuElement[] getSubElements() + { + Component[] items = getComponents(); + MenuElement[] subElements = new MenuElement[items.length]; + + for (int i = 0; i < items.length; i++) + subElements[i] = (MenuElement) items[i]; + + return subElements; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component getComponent() + { + return this; + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isPopupTrigger(MouseEvent event) + { + return ((PopupMenuUI)getUI()).isPopupTrigger(event); + + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJPopupMenu(this); + + return accessibleContext; + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.3 $ + */ + private interface Popup + { + /** + * DOCUMENT ME! + * + * @param x DOCUMENT ME! + * @param y DOCUMENT ME! + * @param width DOCUMENT ME! + * @param height DOCUMENT ME! + */ + void show(int x, int y, int width, int height); + + /** + * DOCUMENT ME! + */ + void hide(); + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.3 $ + */ + private class LightWeightPopup extends JPanel implements Popup + { + /** + * Creates a new LightWeightPopup object. + * + * @param c DOCUMENT ME! + */ + public LightWeightPopup(Container c) + { + this.add(c); + } + + /** + * DOCUMENT ME! + * + * @param x DOCUMENT ME! + * @param y DOCUMENT ME! + * @param width DOCUMENT ME! + * @param height DOCUMENT ME! + */ + public void show(int x, int y, int width, int height) + { + JLayeredPane layeredPane; + layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); + this.setBounds(x, y, width, height); + layeredPane.add(this, JLayeredPane.POPUP_LAYER, 0); + } + + /** + * DOCUMENT ME! + */ + public void hide() + { + JLayeredPane layeredPane; + layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); + int index = layeredPane.getIndexOf(this); + layeredPane.remove(index); + } + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.3 $ + */ + private class MediumWeightPopup extends Panel implements Popup + { + + /** + * Creates a new MediumWeightPopup object. + * + * @param c DOCUMENT ME! + */ + public MediumWeightPopup(Container c) + { + this.add(c); + } + + /** + * DOCUMENT ME! + * + * @param x DOCUMENT ME! + * @param y DOCUMENT ME! + * @param width DOCUMENT ME! + * @param heigth DOCUMENT ME! + */ + public void show(int x, int y, int width, int heigth) + { + JLayeredPane layeredPane; + layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); + layeredPane.add(this, JLayeredPane.POPUP_LAYER, 0); + this.setBounds(x, y, width, height); + } + + /** + * DOCUMENT ME! + */ + public void hide() + { + JLayeredPane layeredPane; + layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); + int index = layeredPane.getIndexOf(this); + layeredPane.remove(index); + } + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.3 $ + */ + private class HeavyWeightPopup extends JWindow implements Popup + { + /** + * Creates a new HeavyWeightPopup object. + * + * @param c DOCUMENT ME! + */ + public HeavyWeightPopup(Container c) + { + this.setContentPane(c); + } + + /** + * DOCUMENT ME! + * + * @param x DOCUMENT ME! + * @param y DOCUMENT ME! + * @param width DOCUMENT ME! + * @param height DOCUMENT ME! + */ + public void show(int x, int y, int width, int height) + { + this.setBounds(x, y, width, height); + this.show(); + } + + /** + * DOCUMENT ME! + */ + public void hide() + { + this.hide(); + } + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.3 $ + */ + public static class Separator extends JSeparator + { + /** + * Creates a new Separator object. + */ + public Separator() + { + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getUIClassID() + { + return null; + } + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.3 $ + */ + protected class AccessibleJPopupMenu extends AccessibleJComponent + { + /** + * Creates a new AccessibleJPopupMenu object. + * + * @param component DOCUMENT ME! + */ + protected AccessibleJPopupMenu(JPopupMenu component) + { + super(component); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return AccessibleRole.POPUP_MENU; + } + } +} diff --git a/libjava/javax/swing/JRadioButtonMenuItem.java b/libjava/javax/swing/JRadioButtonMenuItem.java index cbaf7633d10..7cbb9a684b5 100644 --- a/libjava/javax/swing/JRadioButtonMenuItem.java +++ b/libjava/javax/swing/JRadioButtonMenuItem.java @@ -39,118 +39,188 @@ package javax.swing; import java.io.IOException; import java.io.ObjectOutputStream; - import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; +/** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.4 $ + */ public class JRadioButtonMenuItem extends JMenuItem implements Accessible { - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- private static final String uiClassID = "RadioButtonMenuItemUI"; - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- + /** + * Creates a new JRadioButtonMenuItem object. + */ public JRadioButtonMenuItem() { this(null, null); - } // JRadioButtonMenuItem() + } + /** + * Creates a new JRadioButtonMenuItem object. + * + * @param icon DOCUMENT ME! + */ public JRadioButtonMenuItem(Icon icon) { this(null, icon); - } // JRadioButtonMenuItem() + } + /** + * Creates a new JRadioButtonMenuItem object. + * + * @param text DOCUMENT ME! + */ public JRadioButtonMenuItem(String text) { this(text, null); - } // JRadioButtonMenuItem() + } + /** + * Creates a new JRadioButtonMenuItem object. + * + * @param action DOCUMENT ME! + */ public JRadioButtonMenuItem(Action action) { this(); setAction(action); - } // JRadioButtonMenuItem() - + } + + /** + * Creates a new JRadioButtonMenuItem object. + * + * @param text DOCUMENT ME! + * @param icon DOCUMENT ME! + */ public JRadioButtonMenuItem(String text, Icon icon) { this(text, icon, false); - } // JRadioButtonMenuItem() - + } + + /** + * Creates a new JRadioButtonMenuItem object. + * + * @param text DOCUMENT ME! + * @param selected DOCUMENT ME! + */ public JRadioButtonMenuItem(String text, boolean selected) { this(text, null, selected); - } // JRadioButtonMenuItem() - + } + + /** + * Creates a new JRadioButtonMenuItem object. + * + * @param icon DOCUMENT ME! + * @param selected DOCUMENT ME! + */ public JRadioButtonMenuItem(Icon icon, boolean selected) { this(null, icon, selected); - } // JRadioButtonMenuItem() - + } + + /** + * Creates a new JRadioButtonMenuItem object. + * + * @param text DOCUMENT ME! + * @param icon DOCUMENT ME! + * @param selected DOCUMENT ME! + */ public JRadioButtonMenuItem(String text, Icon icon, boolean selected) { - super(text, icon); - setModel(new JToggleButton.ToggleButtonModel()); + super(text, icon); + setModel(new JToggleButton.ToggleButtonModel()); model.setSelected(selected); - } // JRadioButtonMenuItem() - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- + } + + /** + * DOCUMENT ME! + * + * @param stream DOCUMENT ME! + * + * @throws IOException DOCUMENT ME! + */ private void writeObject(ObjectOutputStream stream) throws IOException { // TODO - } // writeObject() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public String getUIClassID() { return uiClassID; - } // getUIClassID() + } + /** + * DOCUMENT ME! + */ public void requestFocus() { // TODO - } // requestFocus() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ protected String paramString() { return "JRadioButtonMenuItem"; - } // paramString() + } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public AccessibleContext getAccessibleContext() { if (accessibleContext == null) - { - accessibleContext = new AccessibleJRadioButtonMenuItem(this); - } - return accessibleContext; - } // getAccessibleContext() + accessibleContext = new AccessibleJRadioButtonMenuItem(this); - //------------------------------------------------------------- - // Classes ---------------------------------------------------- - //------------------------------------------------------------- + return accessibleContext; + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.3.8.4 $ + */ protected class AccessibleJRadioButtonMenuItem extends AccessibleJMenuItem { - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- + /** + * Creates a new AccessibleJRadioButtonMenuItem object. + * + * @param component DOCUMENT ME! + */ protected AccessibleJRadioButtonMenuItem(JRadioButtonMenuItem component) { super(component); // TODO - } // AccessibleJRadioButtonMenuItem() + } - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public AccessibleRole getAccessibleRole() { return AccessibleRole.RADIO_BUTTON; - } // getAccessibleRole() - } // AccessibleJRadioButtonMenuItem -} // JRadioButtonMenuItem + } + } +} diff --git a/libjava/javax/swing/JRootPane.java b/libjava/javax/swing/JRootPane.java index 4d869d41517..99907d09990 100644 --- a/libjava/javax/swing/JRootPane.java +++ b/libjava/javax/swing/JRootPane.java @@ -43,6 +43,8 @@ import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.LayoutManager; +import java.awt.LayoutManager2; +import javax.swing.plaf.RootPaneUI; /** * This class is where JComponents are added to. @@ -64,42 +66,164 @@ public class JRootPane extends JComponent static protected class AccessibleJRootPane { } - - //A custom layout manager - static protected class RootLayout extends BorderLayout + + // Custom Layout Manager for JRootPane. It positions contentPane and + // menuBar withing its layeredPane. + protected class RootLayout extends Object implements LayoutManager2 { - public Dimension preferredLayoutSize ( Container c ) - { - Dimension p = super.preferredLayoutSize(c); - return p; - } - } - - /***********************************************************/ + public void addLayoutComponent(Component comp, Object constraints) + { + } - - //The glass pane that overlays the menu bar and content pane, so it can intercept mouse movements and such. - protected Component glassPane; - - //The layered pane that manages the menu bar and content pane. - protected JLayeredPane layeredPane; - - // The menu bar. - protected JMenuBar menuBar; - - protected Container contentPane; + public void addLayoutComponent(String name, Component comp) + { + } + + public float getLayoutAlignmentX(Container target) + { + return target.getAlignmentX(); + } + + public float getLayoutAlignmentY(Container target) + { + return target.getAlignmentY(); + } + + public void invalidateLayout(Container target) + { + } + + public void layoutContainer(Container c) + { + Dimension menuBarSize; + Dimension containerSize = c.getSize(null); + Dimension contentPaneSize = contentPane.getPreferredSize(); + + /* + if size of top-level window wasn't set then just set + contentPane and menuBar to its preferred sizes. + Otherwise, if the size of top-level window was specified then + set menuBar to its preferred size and make content pane + to fit into the remaining space + + + +-------------------------------+ + | JLayeredPane | + | +--------------------------+ | + | | menuBar | | + | +--------------------------+ | + | +--------------------------+ | + | |contentPane | | + | | | | + | | | | + | | | | + | +--------------------------+ | + +-------------------------------+ + + */ + if (containerSize.width == 0 && containerSize.height == 0) + { + if (menuBar != null) + { + int maxWidth; + menuBarSize = menuBar.getPreferredSize(); + maxWidth = Math.max(menuBarSize.width, contentPaneSize.width); + menuBar.setBounds(0, 0, maxWidth, menuBarSize.height); + contentPane.setBounds(0, menuBarSize.height, maxWidth, + contentPaneSize.height); + layeredPane.setSize(maxWidth, + menuBarSize.height + contentPaneSize.height); + } + else + { + contentPane.setBounds(0, 0, contentPaneSize.width, + contentPaneSize.height); + layeredPane.setSize(contentPaneSize.width, contentPaneSize.height); + } + } + else + { + if (menuBar != null) + { + menuBarSize = menuBar.getPreferredSize(); + if (menuBarSize.height > containerSize.height) + menuBarSize.height = containerSize.height; + menuBar.setBounds(0, 0, containerSize.width, menuBarSize.height); + int remainingHeight = containerSize.height - menuBarSize.height; + contentPane.setBounds(0, menuBarSize.height, + containerSize.width, + (containerSize.height - menuBarSize.height)); + } + else + contentPane.setBounds(0, 0, containerSize.width, + containerSize.height); + + layeredPane.setSize(containerSize.width, containerSize.height); + } + } + + public Dimension maximumLayoutSize(Container target) + { + return preferredLayoutSize(target); + } - /********************************************************/ + public Dimension minimumLayoutSize(Container target) + { + return preferredLayoutSize(target); + } - public String getUIClassID() - { return "RootPaneUI"; } + public Dimension preferredLayoutSize(Container c) + { + Dimension menuBarSize; + Dimension prefSize; + Dimension containerSize = c.getSize(); + Dimension contentPaneSize = contentPane.getPreferredSize(); + + if (containerSize.width == 0 && containerSize.height == 0) + { + if (menuBar != null) + { + int maxWidth; + menuBarSize = menuBar.getPreferredSize(); + maxWidth = Math.max(menuBarSize.width, contentPaneSize.width); + prefSize = new Dimension(maxWidth, + contentPaneSize.height + + menuBarSize.height); + } + else + prefSize = contentPaneSize; + } + else + prefSize = c.getSize(); + + return prefSize; + } + + public void removeLayoutComponent(Component comp) + { + } + } + + protected Component glassPane; + protected JLayeredPane layeredPane; + protected JMenuBar menuBar; + protected Container contentPane; + void setJMenuBar(JMenuBar m) - { menuBar = m; } + { + menuBar = m; + getLayeredPane().add(menuBar, JLayeredPane.FRAME_CONTENT_LAYER); + } JMenuBar getJMenuBar() { return menuBar; } + + public boolean isValidateRoot() + { + return true; + } public Container getContentPane() @@ -122,7 +246,6 @@ public class JRootPane extends JComponent int index) { super.addImpl(comp, constraints, index); - //System.out.println("don't do that !"); } public Component getGlassPane() @@ -159,16 +282,12 @@ public class JRootPane extends JComponent } - /********************************************************/ - JRootPane() { setLayout(createRootLayout()); - setBackground(UIManager.getColor("control")); getGlassPane(); getLayeredPane(); getContentPane(); - setDoubleBuffered(true); updateUI(); } @@ -182,9 +301,6 @@ public class JRootPane extends JComponent JPanel p = new JPanel(); p.setName(this.getName()+".contentPane"); p.setLayout(new BorderLayout()); - // p.setVisible(true); - - System.out.println("Created ContentPane: " + p); return p; } @@ -194,14 +310,34 @@ public class JRootPane extends JComponent p.setName(this.getName()+".glassPane"); p.setLayout(new BorderLayout()); p.setVisible(false); - - System.out.println("created the glasspane: "+p); return p; } JLayeredPane createLayeredPane() { JLayeredPane l = new JLayeredPane(); + l.setLayout(null); return l; } + + + public RootPaneUI getUI() + { + return (RootPaneUI) ui; + } + + public void setUI(RootPaneUI ui) + { + super.setUI(ui); + } + + public void updateUI() + { + setUI((RootPaneUI) UIManager.getUI(this)); + } + + public String getUIClassID() + { + return "RootPaneUI"; + } } diff --git a/libjava/javax/swing/JScrollBar.java b/libjava/javax/swing/JScrollBar.java index 5636cf3fadf..b8404b3a940 100644 --- a/libjava/javax/swing/JScrollBar.java +++ b/libjava/javax/swing/JScrollBar.java @@ -169,7 +169,7 @@ public class JScrollBar extends JComponent implements Adjustable, Accessible protected BoundedRangeModel model; /** The orientation of the scroll bar. */ - protected int orientation = SwingConstants.HORIZONTAL; + protected int orientation = SwingConstants.VERTICAL; /** How much the thumb moves when moving in a unit. */ protected int unitIncrement = 1; @@ -186,7 +186,7 @@ public class JScrollBar extends JComponent implements Adjustable, Accessible */ public JScrollBar() { - this(SwingConstants.HORIZONTAL, 0, 10, 0, 100); + this(SwingConstants.VERTICAL, 0, 10, 0, 100); } /** diff --git a/libjava/javax/swing/JScrollPane.java b/libjava/javax/swing/JScrollPane.java index b5c0da0542f..1a2021e3332 100644 --- a/libjava/javax/swing/JScrollPane.java +++ b/libjava/javax/swing/JScrollPane.java @@ -40,6 +40,8 @@ package javax.swing; import java.awt.Component; import java.awt.ComponentOrientation; +import java.awt.Dimension; +import java.awt.LayoutManager; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.Point; @@ -50,6 +52,7 @@ import javax.swing.border.Border; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.ScrollPaneUI; +import javax.swing.plaf.UIResource; /** * <table> @@ -430,7 +433,11 @@ public class JScrollPane { JViewport old = viewport; removeNonNull(old); + if (old != null) + old.removeChangeListener(scrollListener); viewport = v; + if (v != null) + v.addChangeListener(scrollListener); addNonNull(v); revalidate(); repaint(); @@ -467,29 +474,64 @@ public class JScrollPane ChangeListener createScrollListener() { - return new ChangeListener() { + return new ChangeListener() + { + public void stateChanged(ChangeEvent event) { - int xpos = 0; - int ypos = 0; JScrollBar vsb = JScrollPane.this.getVerticalScrollBar(); JScrollBar hsb = JScrollPane.this.getHorizontalScrollBar(); - - if (vsb != null) + JViewport vp = JScrollPane.this.getViewport(); + + if (vp != null && event.getSource() == vp) { - BoundedRangeModel vmod = vsb.getModel(); - if (vmod != null) - ypos = vmod.getValue(); + // if the viewport changed, we should update the VSB / HSB + // models according to the new vertical and horizontal sizes + Rectangle vr = vp.getViewRect(); + Dimension vs = vp.getViewSize(); + // System.err.println("got change from viewport, vr=" + vr + ", vs=" + vs); + if (vsb != null + && (vsb.getMinimum() != 0 + || vsb.getMaximum() != vs.height + || vsb.getValue() != vr.y + || vsb.getVisibleAmount() != vr.height)) + { + // System.err.println("setting vsb to " + // + "pos=" + vr.y + // + ", ext=" + vr.height + // + ", min=0" + // + ", max=" + vs.height); + vsb.setValue(vr.y, vr.height, 0, vs.height); + } + + if (hsb != null + && (hsb.getMinimum() != 0 + || hsb.getMaximum() != vs.width + || hsb.getValue() != vr.width + || hsb.getVisibleAmount() != vr.height)) + hsb.setValue(vr.x, vr.width, 0, vs.width); } - - if (hsb != null) + else { - BoundedRangeModel hmod = hsb.getModel(); - if (hmod != null) - xpos = hmod.getValue(); + // otherwise we got a change update from either the VSB or + // HSB model, and we need to update the viewport position to + // match. + + int xpos = 0; + int ypos = 0; + + if (vsb != null) + ypos = vsb.getValue(); + + if (hsb != null) + xpos = hsb.getValue(); + + Point pt = new Point(xpos, ypos); + + if (vp != null + && vp.getViewPosition() != pt) + vp.setViewPosition(pt); } - if (JScrollPane.this.viewport != null) - JScrollPane.this.viewport.setViewPosition(new Point(xpos, ypos)); } }; } @@ -528,12 +570,12 @@ public class JScrollPane public JScrollBar createHorizontalScrollBar() { - return new JScrollBar(SwingConstants.HORIZONTAL); + return new ScrollBar(SwingConstants.HORIZONTAL); } public JScrollBar createVerticalScrollBar() { - return new JScrollBar(SwingConstants.VERTICAL); + return new ScrollBar(SwingConstants.VERTICAL); } public JViewport createViewport() @@ -553,7 +595,7 @@ public class JScrollPane setUI(b); } - /* + class ScrollBar extends JScrollBar implements UIResource @@ -561,17 +603,37 @@ public class JScrollPane public ScrollBar(int orientation) { super(orientation); - Component view = this.JScrollPane.getViewportView(); - if (view == null) - return; - if (! view instanceof Scrollable) + } + + public int getBlockIncrement(int direction) + { + Component view = JScrollPane.this.getViewport().getView(); + if (view == null || (! (view instanceof Scrollable))) + return super.getBlockIncrement(direction); + else { Scrollable s = (Scrollable) view; - s. + return s.getScrollableBlockIncrement(JScrollPane.this.getViewport().getViewRect(), + this.getOrientation(), + direction); + } + } + + public int getUnitIncrement(int direction) + { + Component view = JScrollPane.this.getViewport().getView(); + if (view == null || (! (view instanceof Scrollable))) + return super.getUnitIncrement(direction); + else + { + Scrollable s = (Scrollable) view; + return s.getScrollableUnitIncrement(JScrollPane.this.getViewport().getViewRect(), + this.getOrientation(), + direction); } } - } - */ + } + } diff --git a/libjava/javax/swing/JSlider.java b/libjava/javax/swing/JSlider.java index 7350ea4ee98..b4db64180c3 100644 --- a/libjava/javax/swing/JSlider.java +++ b/libjava/javax/swing/JSlider.java @@ -304,7 +304,7 @@ public class JSlider extends JComponent implements SwingConstants, Accessible, */ public JSlider(int minimum, int maximum) { - this(HORIZONTAL, minimum, maximum, (maximum - minimum) / 2); + this(HORIZONTAL, minimum, maximum, (maximum + minimum) / 2); } /** diff --git a/libjava/javax/swing/JSplitPane.java b/libjava/javax/swing/JSplitPane.java index 9a9be6cf833..a8ef310708e 100644 --- a/libjava/javax/swing/JSplitPane.java +++ b/libjava/javax/swing/JSplitPane.java @@ -1,648 +1,775 @@ -/* JSplitPane.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ package javax.swing; import java.awt.Component; import java.awt.Graphics; -import java.io.IOException; -import java.io.ObjectOutputStream; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; import javax.accessibility.AccessibleStateSet; import javax.accessibility.AccessibleValue; +import javax.swing.UIManager; import javax.swing.plaf.SplitPaneUI; + /** - * JSplitPane - * @author Andrew Selkirk - * @version 1.0 + * This class implements JSplitPane. It is used to divide two components. By + * dragging the SplitPane's divider, the user can resize the two components. + * Note that the divider cannot resize a component to smaller than it's + * minimum size. */ -public class JSplitPane extends JComponent implements Accessible { - - //------------------------------------------------------------- - // Classes ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * AccessibleJSplitPane - */ - protected class AccessibleJSplitPane extends AccessibleJComponent - implements AccessibleValue { - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor AccessibleJSplitPane - * @param component TODO - */ - protected AccessibleJSplitPane(JSplitPane component) { - super(component); - // TODO - } // AccessibleJSplitPane() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * getAccessibleStateSet - * @returns AccessibleStateSet - */ - public AccessibleStateSet getAccessibleStateSet() { - return null; // TODO - } // getAccessibleStateSet() - - /** - * getAccessibleRole - * @returns AccessibleRole - */ - public AccessibleRole getAccessibleRole() { - return AccessibleRole.SPLIT_PANE; - } // getAccessibleRole() - - /** - * getAccessibleValue - * @returns AccessibleValue - */ - public AccessibleValue getAccessibleValue() { - return null; // TODO - } // getAccessibleValue() - - /** - * getCurrentAccessibleValue - * @returns Number - */ - public Number getCurrentAccessibleValue() { - return null; // TODO - } // getCurrentAccessibleValue() - - /** - * setCurrentAccessibleValue - * @param value0 TODO - * @returns boolean - */ - public boolean setCurrentAccessibleValue(Number value0) { - return false; // TODO - } // setCurrentAccessibleValue() - - /** - * getMinimumAccessibleValue - * @returns Number - */ - public Number getMinimumAccessibleValue() { - return null; // TODO - } // getMinimumAccessibleValue() - - /** - * getMaximumAccessibleValue - * @returns Number - */ - public Number getMaximumAccessibleValue() { - return null; // TODO - } // getMaximumAccessibleValue() - - - } // AccessibleJSplitPane - - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * uiClassID - */ - private static final String uiClassID = "SplitPaneUI"; - - /** - * VERTICAL_SPLIT - */ - public static final int VERTICAL_SPLIT = 0; - - /** - * HORIZONTAL_SPLIT - */ - public static final int HORIZONTAL_SPLIT = 1; - - /** - * LEFT - */ - public static final String LEFT = "left"; - - /** - * RIGHT - */ - public static final String RIGHT = "right"; - - /** - * TOP - */ - public static final String TOP = "top"; - - /** - * BOTTOM - */ - public static final String BOTTOM = "bottom"; - - /** - * DIVIDER - */ - public static final String DIVIDER = "divider"; - - /** - * ORIENTATION_PROPERTY - */ - public static final String ORIENTATION_PROPERTY = "orientation"; - - /** - * CONTINUOUS_LAYOUT_PROPERTY - */ - public static final String CONTINUOUS_LAYOUT_PROPERTY = "continuousLayout"; - - /** - * DIVIDER_SIZE_PROPERTY - */ - public static final String DIVIDER_SIZE_PROPERTY = "dividerSize"; - - /** - * ONE_TOUCH_EXPANDABLE_PROPERTY - */ - public static final String ONE_TOUCH_EXPANDABLE_PROPERTY = "oneTouchExpandable"; - - /** - * LAST_DIVIDER_LOCATION_PROPERTY - */ - public static final String LAST_DIVIDER_LOCATION_PROPERTY = "lastDividerLocation"; - - /** - * DIVIDER_LOCATION_PROPERTY - */ - public static final String DIVIDER_LOCATION_PROPERTY = "dividerLocation"; - - /** - * RESIZE_WEIGHT_PROPERTY - */ - public static final String RESIZE_WEIGHT_PROPERTY = "resizeWeight"; - - /** - * orientation - */ - protected int orientation; - - /** - * continuousLayout - */ - protected boolean continuousLayout; - - /** - * leftComponent - */ - protected Component leftComponent; - - /** - * rightComponent - */ - protected Component rightComponent; - - /** - * dividerSize - */ - protected int dividerSize; - - /** - * oneTouchExpandable - */ - protected boolean oneTouchExpandable; - - /** - * lastDividerLocation - */ - protected int lastDividerLocation; - - /** - * resizeWeight - */ - private double resizeWeight; - - /** - * dividerLocation - */ - private int dividerLocation; - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor JSplitPane - */ - public JSplitPane() { - // TODO - } // JSplitPane() - - /** - * Constructor JSplitPane - * @param value0 TODO - */ - public JSplitPane(int value0) { - // TODO - } // JSplitPane() - - /** - * Constructor JSplitPane - * @param value0 TODO - * @param value1 TODO - */ - public JSplitPane(int value0, boolean value1) { - // TODO - } // JSplitPane() - - /** - * Constructor JSplitPane - * @param value0 TODO - * @param value1 TODO - * @param value2 TODO - */ - public JSplitPane(int value0, Component value1, Component value2) { - // TODO - } // JSplitPane() - - /** - * Constructor JSplitPane - * @param value0 TODO - * @param value1 TODO - * @param value2 TODO - * @param value3 TODO - */ - public JSplitPane(int value0, boolean value1, Component value2, Component value3) { - // TODO - } // JSplitPane() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * writeObject - * @param stream TODO - * @exception IOException TODO - */ - private void writeObject(ObjectOutputStream stream) throws IOException { - // TODO - } // writeObject() - - /** - * remove - * @param value0 TODO - */ - public void remove(Component value0) { - // TODO - } // remove() - - /** - * remove - * @param value0 TODO - */ - public void remove(int value0) { - // TODO - } // remove() - - /** - * removeAll - */ - public void removeAll() { - // TODO - } // removeAll() - - /** - * setUI - * @param ui TODO - */ - public void setUI(SplitPaneUI ui) { - super.setUI(ui); - } // setUI() - - /** - * getUI - * @returns SplitPaneUI - */ - public SplitPaneUI getUI() { - return (SplitPaneUI) ui; - } // getUI() - - /** - * updateUI - */ - public void updateUI() { - setUI((SplitPaneUI) UIManager.get(this)); - invalidate(); - } // updateUI() - - /** - * getUIClassID - * @returns String - */ - public String getUIClassID() { - return uiClassID; - } // getUIClassID() - - /** - * setDividerSize - * @param value0 TODO - */ - public void setDividerSize(int value0) { - // TODO - } // setDividerSize() - - /** - * getDividerSize - * @returns int - */ - public int getDividerSize() { - return 0; // TODO - } // getDividerSize() - - /** - * setLeftComponent - * @param value0 TODO - */ - public void setLeftComponent(Component value0) { - // TODO - } // setLeftComponent() - - /** - * getLeftComponent - * @returns Component - */ - public Component getLeftComponent() { - return null; // TODO - } // getLeftComponent() - - /** - * setTopComponent - * @param value0 TODO - */ - public void setTopComponent(Component value0) { - // TODO - } // setTopComponent() - - /** - * getTopComponent - * @returns Component - */ - public Component getTopComponent() { - return null; // TODO - } // getTopComponent() - - /** - * setRightComponent - * @param value0 TODO - */ - public void setRightComponent(Component value0) { - // TODO - } // setRightComponent() - - /** - * getRightComponent - * @returns Component - */ - public Component getRightComponent() { - return null; // TODO - } // getRightComponent() - - /** - * setBottomComponent - * @param value0 TODO - */ - public void setBottomComponent(Component value0) { - // TODO - } // setBottomComponent() - - /** - * getBottomComponent - * @returns Component - */ - public Component getBottomComponent() { - return null; // TODO - } // getBottomComponent() - - /** - * setOneTouchExpandable - * @param value0 TODO - */ - public void setOneTouchExpandable(boolean value0) { - // TODO - } // setOneTouchExpandable() - - /** - * isOneTouchExpandable - * @returns boolean - */ - public boolean isOneTouchExpandable() { - return false; // TODO - } // isOneTouchExpandable() - - /** - * setLastDividerLocation - * @param value0 TODO - */ - public void setLastDividerLocation(int value0) { - // TODO - } // setLastDividerLocation() - - /** - * getLastDividerLocation - * @returns int - */ - public int getLastDividerLocation() { - return 0; // TODO - } // getLastDividerLocation() - - /** - * setOrientation - * @param value0 TODO - */ - public void setOrientation(int value0) { - // TODO - } // setOrientation() - - /** - * getOrientation - * @returns int - */ - public int getOrientation() { - return 0; // TODO - } // getOrientation() - - /** - * setContinuousLayout - * @param value0 TODO - */ - public void setContinuousLayout(boolean value0) { - // TODO - } // setContinuousLayout() - - /** - * isContinuousLayout - * @returns boolean - */ - public boolean isContinuousLayout() { - return false; // TODO - } // isContinuousLayout() - - /** - * setResizeWeight - * @param value0 TODO - */ - public void setResizeWeight(double value0) { - // TODO - } // setResizeWeight() - - /** - * getResizeWeight - * @returns double - */ - public double getResizeWeight() { - return 0.0; // TODO - } // getResizeWeight() - - /** - * resetToPreferredSizes - */ - public void resetToPreferredSizes() { - // TODO - } // resetToPreferredSizes() - - /** - * setDividerLocation - * @param value0 TODO - */ - public void setDividerLocation(double value0) { - // TODO - } // setDividerLocation() - - /** - * setDividerLocation - * @param value0 TODO - */ - public void setDividerLocation(int value0) { - // TODO - } // setDividerLocation() - - /** - * getDividerLocation - * @returns int - */ - public int getDividerLocation() { - return 0; // TODO - } // getDividerLocation() - - /** - * getMinimumDividerLocation - * @returns int - */ - public int getMinimumDividerLocation() { - return 0; // TODO - } // getMinimumDividerLocation() - - /** - * getMaximumDividerLocation - * @returns int - */ - public int getMaximumDividerLocation() { - return 0; // TODO - } // getMaximumDividerLocation() - - /** - * isValidateRoot - * @returns boolean - */ - public boolean isValidateRoot() { - return false; // TODO - } // isValidateRoot() - - /** - * addImpl - * @param value0 TODO - * @param value1 TODO - * @param value2 TODO - */ - protected void addImpl(Component value0, Object value1, int value2) { - // TODO - } // addImpl() - - /** - * paintChildren - * @param value0 TODO - */ - protected void paintChildren(Graphics value0) { - // TODO - } // paintChildren() - - /** - * paramString - * @returns String - */ - protected String paramString() { - return null; // TODO - } // paramString() - - /** - * getAccessibleContext - * @returns AccessibleContext - */ - public AccessibleContext getAccessibleContext() { - if (accessibleContext == null) { - accessibleContext = new AccessibleJSplitPane(this); - } // if - return accessibleContext; - } // getAccessibleContext() - - -} // JSplitPane +public class JSplitPane extends JComponent implements Accessible +{ + /** + * DOCUMENT ME! + */ + protected class AccessibleJSplitPane extends JComponent.AccessibleJComponent + implements AccessibleValue + { + /** + * Creates a new AccessibleJSplitPane object. + * + * @param value0 DOCUMENT ME! + */ + protected AccessibleJSplitPane(JSplitPane value0) + { + super(value0); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleStateSet getAccessibleStateSet() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleRole getAccessibleRole() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleValue getAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getCurrentAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param value0 DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean setCurrentAccessibleValue(Number value0) + { + return false; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getMinimumAccessibleValue() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Number getMaximumAccessibleValue() + { + return null; + } + } + + /** The constraints string used to add components to the bottom. */ + public static final String BOTTOM = "bottom"; + + /** The property fired when the continuousLayout property changes. */ + public static final String CONTINUOUS_LAYOUT_PROPERTY = "continuousLayout"; + + /** The property fired when the divider property changes. */ + public static final String DIVIDER = "divider"; + + /** The property fired when the divider location property changes. */ + public static final String DIVIDER_LOCATION_PROPERTY = "dividerLocation"; + + /** The property fired when the divider size property changes. */ + public static final String DIVIDER_SIZE_PROPERTY = "dividerSize"; + + /** + * The value of the orientation when the components are split horizontally. + */ + public static final int HORIZONTAL_SPLIT = 1; + + /** The property fired when the last divider location property changes. */ + public static final String LAST_DIVIDER_LOCATION_PROPERTY = "lastDividerLocation"; + + /** The constraints string used to add components to the left. */ + public static final String LEFT = "left"; + + /** The property fired when the one touch expandable property changes. */ + public static final String ONE_TOUCH_EXPANDABLE_PROPERTY = "oneTouchExpandable"; + + /** The property fired when the orientation property changes. */ + public static final String ORIENTATION_PROPERTY = "orientation"; + + /** The property fired when the resize weight property changes. */ + public static final String RESIZE_WEIGHT_PROPERTY = "resizeWeight"; + + /** The constraints string used to add components to the right. */ + public static final String RIGHT = "right"; + + /** The constraints string used to add components to the top. */ + public static final String TOP = "top"; + + /** The value of the orientation when the components are split vertically. */ + public static final int VERTICAL_SPLIT = 0; + + /** Whether the JSplitPane uses continuous layout. */ + protected boolean continuousLayout; + + /** Whether the JSplitPane uses one touch expandable buttons. */ + protected boolean oneTouchExpandable = false; + + // This is the master dividerSize variable and sets the BasicSplitPaneDivider one accordingly + + /** The size of the divider. */ + protected int dividerSize = 10; + + /** The last location of the divider given by the UI. */ + protected int lastDividerLocation; + + /** The orientation of the JSplitPane. */ + protected int orientation; + + /** The component on the top or left. */ + protected Component leftComponent; + + /** The component on the right or bottom. */ + protected Component rightComponent; + + /** Determines how extra space should be allocated. */ + private transient double resizeWeight; + + /** + * Creates a new JSplitPane object with the given orientation, layout mode, + * and left and right components. + * + * @param newOrientation The orientation to use. + * @param newContinuousLayout The layout mode to use. + * @param newLeftComponent The left component. + * @param newRightComponent The right component. + * + * @throws IllegalArgumentException DOCUMENT ME! + */ + public JSplitPane(int newOrientation, boolean newContinuousLayout, + Component newLeftComponent, Component newRightComponent) + { + if (newOrientation != HORIZONTAL_SPLIT && newOrientation != VERTICAL_SPLIT) + throw new IllegalArgumentException("orientation is invalid."); + orientation = newOrientation; + continuousLayout = newContinuousLayout; + setLeftComponent(newLeftComponent); + setRightComponent(newRightComponent); + + updateUI(); + } + + /** + * Creates a new JSplitPane object using nonContinuousLayout mode, the given + * orientation and left and right components. + * + * @param newOrientation The orientation to use. + * @param newLeftComponent The left component. + * @param newRightComponent The right component. + */ + public JSplitPane(int newOrientation, Component newLeftComponent, + Component newRightComponent) + { + this(newOrientation, false, newLeftComponent, newRightComponent); + } + + /** + * Creates a new JSplitPane object with the given layout mode and + * orientation. + * + * @param newOrientation The orientation to use. + * @param newContinuousLayout The layout mode to use. + */ + public JSplitPane(int newOrientation, boolean newContinuousLayout) + { + this(newOrientation, newContinuousLayout, null, null); + } + + /** + * Creates a new JSplitPane object using a nonContinuousLayout mode and the + * given orientation. + * + * @param newOrientation The orientation to use. + */ + public JSplitPane(int newOrientation) + { + this(newOrientation, false, null, null); + } + + /** + * Creates a new JSplitPane object using HORIZONTAL_SPLIT and a + * nonContinuousLayout mode. + */ + public JSplitPane() + { + this(HORIZONTAL_SPLIT, false, null, null); + } + + /** + * This method adds a component to the JSplitPane. The constraints object is + * a string that identifies where this component should go. If the + * constraints is not a known one, it will throw an + * IllegalArgumentException. The valid constraints are LEFT, TOP, RIGHT, + * BOTTOM and DIVIDER. + * + * @param comp The component to add. + * @param constraints The constraints string to use. + * @param index Where to place to component in the list of components. + * + * @throws IllegalArgumentException When the constraints is not a known identifier. + */ + protected void addImpl(Component comp, Object constraints, int index) + { + int left = 0; + int right = 1; + int div = 2; + int place; + if (constraints == null) + { + if (leftComponent == null) + constraints = LEFT; + else if (rightComponent == null) + constraints = RIGHT; + } + + if (constraints instanceof String) + { + String placement = (String) constraints; + + if (placement.equals(BOTTOM) || placement.equals(RIGHT)) + { + if (rightComponent != null) + remove(rightComponent); + rightComponent = comp; + } + else if (placement.equals(LEFT) || placement.equals(TOP)) + { + if (leftComponent != null) + remove(leftComponent); + leftComponent = comp; + } + else if (placement.equals(DIVIDER)) + constraints = null; + else + throw new IllegalArgumentException("Constraints is not a known identifier."); + + super.addImpl(comp, constraints, index); + } + invalidate(); + layout(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public AccessibleContext getAccessibleContext() + { + if (accessibleContext == null) + accessibleContext = new AccessibleJSplitPane(this); + return accessibleContext; + } + + /** + * This method returns the bottom component. + * + * @return The bottom component. + */ + public Component getBottomComponent() + { + return rightComponent; + } + + /** + * This method returns the location of the divider. This method is passed to + * the UI. + * + * @return The location of the divider. + */ + public int getDividerLocation() + { + if (ui != null) + return ((SplitPaneUI) ui).getDividerLocation(this); + else + return -1; + } + + /** + * This method returns the size of the divider. + * + * @return The size of the divider. + */ + public int getDividerSize() + { + return dividerSize; + } + + /** + * This method returns the last divider location. + * + * @return The last divider location. + */ + public int getLastDividerLocation() + { + return lastDividerLocation; + } + + /** + * This method returns the left component. + * + * @return The left component. + */ + public Component getLeftComponent() + { + return leftComponent; + } + + /** + * This method returns the maximum divider location. This method is passed + * to the UI. + * + * @return DOCUMENT ME! + */ + public int getMaximumDividerLocation() + { + if (ui != null) + return ((SplitPaneUI) ui).getMaximumDividerLocation(this); + else + return -1; + } + + /** + * This method returns the minimum divider location. This method is passed + * to the UI. + * + * @return The minimum divider location. + */ + public int getMinimumDividerLocation() + { + if (ui != null) + return ((SplitPaneUI) ui).getMinimumDividerLocation(this); + else + return -1; + } + + /** + * This method returns the orientation that the JSplitPane is using. + * + * @return The current orientation. + */ + public int getOrientation() + { + return orientation; + } + + /** + * This method returns the current resize weight. + * + * @return The current resize weight. + */ + public double getResizeWeight() + { + return resizeWeight; + } + + /** + * This method returns the right component. + * + * @return The right component. + */ + public Component getRightComponent() + { + return rightComponent; + } + + /** + * This method returns the top component. + * + * @return The top component. + */ + public Component getTopComponent() + { + return leftComponent; + } + + /** + * This method returns the UI. + * + * @return The UI. + */ + public SplitPaneUI getUI() + { + return (SplitPaneUI) ui; + } + + /** + * This method returns true if the JSplitPane is using a continuousLayout. + * + * @return True if using a continuousLayout. + */ + public boolean isContinuousLayout() + { + return continuousLayout; + } + + /** + * This method returns true if the divider has one touch expandable buttons. + * + * @return True if one touch expandable is used. + */ + public boolean isOneTouchExpandable() + { + return oneTouchExpandable; + } + + /** + * This method returns true. + * + * @return true. + */ + public boolean isValidateRoot() + { + return true; + } + + /** + * This method overrides JComponent's paintChildren so the UI can be + * messaged when the children have finished painting. + * + * @param g The Graphics object to paint with. + */ + protected void paintChildren(Graphics g) + { + super.paintChildren(g); + if (ui != null) + ((SplitPaneUI) ui).finishedPaintingChildren(this, g); + } + + /** + * This method returns a String that describes this JSplitPane. The string + * is primarily used for debugging purposes. + * + * @return A String used for debugging purposes. + */ + protected String paramString() + { + return "JSplitPane"; + } + + /** + * This method removes the given component from the JSplitPane. + * + * @param component The Component to remove. + */ + public void remove(Component component) + { + if (component == leftComponent) + leftComponent = null; + else if (component == rightComponent) + rightComponent = null; + super.remove(component); + } + + /** + * This method removes the component at the given index. + * + * @param index The index of the component to remove. + */ + public void remove(int index) + { + Component component = getComponentAt(index); + if (component == leftComponent) + leftComponent = null; + else if (component == rightComponent) + rightComponent = null; + super.remove(index); + } + + /** + * This method removes all components from the JSplitPane. + */ + public void removeAll() + { + leftComponent = null; + rightComponent = null; + super.removeAll(); + } + + /** + * This method resets all children of the JSplitPane to their preferred + * sizes. + */ + public void resetToPreferredSizes() + { + if (ui != null) + ((SplitPaneUI) ui).resetToPreferredSizes(this); + } + + /** + * This method sets the bottom component. + * + * @param comp The Component to be placed at the bottom. + */ + public void setBottomComponent(Component comp) + { + if (comp != null) + add(comp, BOTTOM); + else + add(new JButton("right button"), BOTTOM); + } + + /** + * This method sets the layout mode for the JSplitPane. + * + * @param newContinuousLayout Whether the JSplitPane is in continuousLayout + * mode. + */ + public void setContinuousLayout(boolean newContinuousLayout) + { + if (newContinuousLayout != continuousLayout) + { + boolean oldValue = continuousLayout; + continuousLayout = newContinuousLayout; + firePropertyChange(CONTINUOUS_LAYOUT_PROPERTY, oldValue, + continuousLayout); + } + } + + /** + * This method sets the location of the divider. A value of 0 sets the + * divider to the farthest left. A value of 1 sets the divider to the + * farthest right. + * + * @param proportionalLocation A double that describes the location of the + * divider. + * + * @throws IllegalArgumentException DOCUMENT ME! + */ + public void setDividerLocation(double proportionalLocation) + { + if (proportionalLocation > 1 || proportionalLocation < 0) + throw new IllegalArgumentException("proportion has to be between 0 and 1."); + + int max = (orientation == HORIZONTAL_SPLIT) ? getWidth() : getHeight(); + setDividerLocation((int) (proportionalLocation * max)); + } + + /** + * This method sets the location of the divider. + * + * @param location The location of the divider. + */ + public void setDividerLocation(int location) + { + if (ui != null && location != getDividerLocation()) + { + int oldLocation = getDividerLocation(); + ((SplitPaneUI) ui).setDividerLocation(this, location); + firePropertyChange(DIVIDER_LOCATION_PROPERTY, oldLocation, location); + } + } + + /** + * This method sets the size of the divider. + * + * @param newSize The size of the divider. + */ + public void setDividerSize(int newSize) + { + if (newSize != dividerSize) + { + int oldSize = dividerSize; + dividerSize = newSize; + firePropertyChange(DIVIDER_SIZE_PROPERTY, oldSize, dividerSize); + } + } + + // This doesn't appear to do anything when set from user side. + // so it probably is only used from the UI side to change the + // lastDividerLocation var. + + /** + * This method sets the last location of the divider. + * + * @param newLastLocation The last location of the divider. + */ + public void setLastDividerLocation(int newLastLocation) + { + if (newLastLocation != lastDividerLocation) + { + int oldValue = lastDividerLocation; + lastDividerLocation = newLastLocation; + firePropertyChange(LAST_DIVIDER_LOCATION_PROPERTY, oldValue, + lastDividerLocation); + } + } + + /** + * This method sets the left component. + * + * @param comp The left component. + */ + public void setLeftComponent(Component comp) + { + if (comp != null) + add(comp, LEFT); + else + add(new JButton("left button"), LEFT); + } + + /** + * This method sets whether the divider has one touch expandable buttons. + * The one touch expandable buttons can expand the size of either component + * to the maximum allowed size. + * + * @param newValue Whether the divider will have one touch expandable + * buttons. + */ + public void setOneTouchExpandable(boolean newValue) + { + if (newValue != oneTouchExpandable) + { + boolean oldValue = oneTouchExpandable; + oneTouchExpandable = newValue; + firePropertyChange(ONE_TOUCH_EXPANDABLE_PROPERTY, oldValue, + oneTouchExpandable); + } + } + + /** + * This method sets the orientation of the JSplitPane. + * + * @param orientation The orientation of the JSplitPane. + * + * @throws IllegalArgumentException DOCUMENT ME! + */ + public void setOrientation(int orientation) + { + if (orientation != HORIZONTAL_SPLIT && orientation != VERTICAL_SPLIT) + throw new IllegalArgumentException("orientation must be one of VERTICAL_SPLIT, HORIZONTAL_SPLIT"); + if (orientation != this.orientation) + { + int oldOrientation = this.orientation; + this.orientation = orientation; + firePropertyChange(ORIENTATION_PROPERTY, oldOrientation, + this.orientation); + } + } + + /** + * This method determines how extra space will be distributed among the left + * and right components. A value of 0 will allocate all extra space to the + * right component. A value of 1 indicates that all extra space will go to + * the left component. A value in between 1 and 0 will split the space + * accordingly. + * + * @param value The resize weight. + */ + public void setResizeWeight(double value) + { + resizeWeight = value; + } + + /** + * This method sets the right component. + * + * @param comp The right component. + */ + public void setRightComponent(Component comp) + { + if (comp != null) + add(comp, RIGHT); + else + add(new JButton("right button"), RIGHT); + } + + /** + * This method sets the top component. + * + * @param comp The top component. + */ + public void setTopComponent(Component comp) + { + if (comp != null) + add(comp, TOP); + else + add(new JButton("left button"), TOP); + } + + /** + * This method sets the UI used by the JSplitPane. + * + * @param ui The UI to use. + */ + public void setUI(SplitPaneUI ui) + { + super.setUI(ui); + } + + /** + * This method resets the UI to the one specified by the current Look and + * Feel. + */ + public void updateUI() + { + setUI((SplitPaneUI) UIManager.getUI(this)); + invalidate(); + repaint(); + } + + /** + * This method returns a string identifier to determine which UI class it + * needs. + * + * @return A string that identifies it's UI class. + */ + public String getUIClassID() + { + return "SplitPaneUI"; + } +} diff --git a/libjava/javax/swing/JViewport.java b/libjava/javax/swing/JViewport.java index 756d5edd555..b164dc79045 100644 --- a/libjava/javax/swing/JViewport.java +++ b/libjava/javax/swing/JViewport.java @@ -114,7 +114,13 @@ public class JViewport extends JComponent * * @see #toViewCoordinates */ - Dimension viewExtent; + Dimension extentSize; + + /** + * The width and height of the view in its own coordinate space. + */ + + Dimension viewSize; Point lastPaintPosition; @@ -124,17 +130,35 @@ public class JViewport extends JComponent updateUI(); } - public Dimension getViewSize() + public Dimension getExtentSize() { - if (viewExtent == null) + if (extentSize == null) return getPreferredSize(); else - return viewExtent; + return extentSize; + } + + public void setExtentSize(Dimension newSize) + { + extentSize = newSize; + fireStateChanged(); + } + + public Dimension getViewSize() + { + if (viewSize == null) + return getView().getPreferredSize(); + else + return viewSize; } + public void setViewSize(Dimension newSize) { - viewExtent = newSize; + viewSize = newSize; + Component view = getView(); + if (view != null) + view.setSize(newSize); fireStateChanged(); } @@ -166,7 +190,7 @@ public class JViewport extends JComponent public Rectangle getViewRect() { return new Rectangle(getViewPosition(), - getViewSize()); + getExtentSize()); } public boolean isBackingStoreEnabled() @@ -207,7 +231,24 @@ public class JViewport extends JComponent add(v); fireStateChanged(); } - + + public void revalidate() + { + fireStateChanged(); + super.revalidate(); + } + + public void reshape(int x, int y, int w, int h) + { + boolean changed = + (x != getX()) + || (y != getY()) + || (w != getWidth()) + || (h != getHeight()); + super.reshape(x, y, w, h); + if (changed) + fireStateChanged(); + } public void addImpl(Component comp, Object constraints, int index) { diff --git a/libjava/javax/swing/JWindow.java b/libjava/javax/swing/JWindow.java index 11760e92dd6..2c3c27f3703 100644 --- a/libjava/javax/swing/JWindow.java +++ b/libjava/javax/swing/JWindow.java @@ -58,7 +58,7 @@ import javax.accessibility.AccessibleContext; * * @author Ronald Veldema (rveldema@cs.vu.nl) */ -public class JWindow extends Window implements Accessible +public class JWindow extends Window implements Accessible, RootPaneContainer { public final static int HIDE_ON_CLOSE = 0; public final static int EXIT_ON_CLOSE = 1; @@ -79,8 +79,8 @@ public class JWindow extends Window implements Accessible *************/ public JWindow() - { - this(null); + { + super(); } // huuu ? @@ -124,20 +124,20 @@ public class JWindow extends Window implements Accessible public void setLayout(LayoutManager manager) { super.setLayout(manager); } - void setLayeredPane(JLayeredPane layeredPane) + public void setLayeredPane(JLayeredPane layeredPane) { getRootPane().setLayeredPane(layeredPane); } - JLayeredPane getLayeredPane() + public JLayeredPane getLayeredPane() { return getRootPane().getLayeredPane(); } - JRootPane getRootPane() + public JRootPane getRootPane() { if (rootPane == null) setRootPane(createRootPane()); return rootPane; } - void setRootPane(JRootPane root) + public void setRootPane(JRootPane root) { if (rootPane != null) remove(rootPane); @@ -146,19 +146,19 @@ public class JWindow extends Window implements Accessible add(rootPane, BorderLayout.CENTER); } - JRootPane createRootPane() + public JRootPane createRootPane() { return new JRootPane(); } - Container getContentPane() + public Container getContentPane() { return getRootPane().getContentPane(); } - void setContentPane(Container contentPane) + public void setContentPane(Container contentPane) { getRootPane().setContentPane(contentPane); } - Component getGlassPane() + public Component getGlassPane() { return getRootPane().getGlassPane(); } - void setGlassPane(Component glassPane) + public void setGlassPane(Component glassPane) { getRootPane().setGlassPane(glassPane); } diff --git a/libjava/javax/swing/MenuSelectionManager.java b/libjava/javax/swing/MenuSelectionManager.java index 9088968538a..d722b0b7275 100644 --- a/libjava/javax/swing/MenuSelectionManager.java +++ b/libjava/javax/swing/MenuSelectionManager.java @@ -1,5 +1,5 @@ /* MenuSelectionManager.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,6 +38,15 @@ exception statement from your version. */ package javax.swing; +import java.awt.Component; +import java.awt.Point; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; + +import java.util.Vector; + +import javax.swing.JMenu; +import javax.swing.JMenuItem; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; @@ -48,6 +57,10 @@ public class MenuSelectionManager protected EventListenerList listenerList = new EventListenerList (); + private static final MenuSelectionManager manager = new MenuSelectionManager(); + + private Vector selection = new Vector(); + protected void fireStateChanged () { ChangeListener[] listeners = getChangeListeners (); @@ -73,4 +86,213 @@ public class MenuSelectionManager { return (ChangeListener[]) listenerList.getListeners (ChangeListener.class); } + + /** + * Unselects all the menu elements on the selection path + */ + public void clearSelectedPath () + { + for (int i = 0; i < selection.size (); i++) + ((MenuElement) selection.get (i)).menuSelectionChanged (false); + + selection.clear (); + } + + public Component componentForPoint (Component source, Point sourcePoint) + { + throw new UnsupportedOperationException("not implemented"); + } + + /** + * Returns shared instance of MenuSelection Manager + * + * @return default Manager + */ + public static MenuSelectionManager defaultManager () + { + return manager; + } + + /** + * Returns path representing current menu selection + * + * @return Current selection path + */ + public MenuElement[] getSelectedPath () + { + MenuElement[] path = new MenuElement[selection.size ()]; + + for (int i = 0; i < path.length; i++) + path[i] = (MenuElement) selection.get (i); + + return path; + } + + /** + * Returns true if specified component is part of current menu + * heirarchy and false otherwise + * + * @param c Component for which to check + * @return True if specified component is part of current menu + */ + boolean isComponentPartOfCurrentMenu (Component c) + { + MenuElement[] subElements; + for (int i = 0; i < selection.size (); i++) + { + subElements = ((MenuElement) selection.get (i)).getSubElements (); + for (int j = 0; j < subElements.length; j++) + { + if ((subElements[j].getComponent ()).equals (c)) + return true; + } + } + + return false; + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void processKeyEvent (KeyEvent e) + { + throw new UnsupportedOperationException("not implemented"); + } + + /** + * Forwards given mouse event to all of the source subcomponents. + * + * @param event Mouse event + */ + public void processMouseEvent (MouseEvent event) + { + + Component c = ((MenuElement) event.getSource ()).getComponent (); + if (selection.size () == 0) + { + ((MenuElement) event.getSource ()).processMouseEvent (event, + getPath (c), + manager); + return; + } + + // find the index of the source component in the current menu hierarchy + int i = 0; + for (i = 0; i < selection.size (); i++) + { + MenuElement me = (MenuElement) selection.get (i); + if (me.getComponent ().equals (c)) + break; + } + + // Forward event to all subcomponents of the source + Component subComp; + for (int j = i; j < selection.size (); j++) + { + subComp = ((MenuElement)selection.get (j)).getComponent (); + ((MenuElement) selection.get (j)).processMouseEvent (event, + getPath (subComp), + manager); + } + } + + /** + * Sets menu selection to the specified path + * + * @param path new selection path + */ + public void setSelectedPath (MenuElement[] path) + { + if (path == null) + { + clearSelectedPath (); + return; + } + + int i; + int minSize = path.length; // size of the smaller path. + + if (path.length > selection.size ()) + { + // if new selected path contains more elements then current + // selection then first add all elements at + // the indexes > selection.size + + for (i = selection.size (); i < path.length; i++) + { + selection.add (path[i]); + path[i].menuSelectionChanged (true); + } + + minSize = selection.size (); + } + + else if (path.length < selection.size ()) + { + // if new selected path contains less elements then current + // selection then first remove all elements from the selection + // at the indexes > path.length + + for (i = selection.size () - 1; i >= path.length; i--) + { + ((MenuElement) selection.get (i)).menuSelectionChanged (false); + selection.remove (i); + } + + minSize = path.length; + } + + // Now compare elements in new and current selection path at the + // same location and adjust selection until + // same menu elements will be encountered at the + // same index in both current and new selection path. + + MenuElement oldSelection; + + for (i = minSize - 1; i >= 0; i--) + { + oldSelection = (MenuElement) selection.get (i); + + if (path[i].equals (oldSelection)) + break; + + oldSelection.menuSelectionChanged (false); + path[i].menuSelectionChanged (true); + selection.setElementAt (path[i], i); + } + } + + + /** + * Returns path to the specified component + * + * @param c component for which to find path for + * + * @return path to the specified component + */ + private MenuElement[] getPath (Component c) + { + Vector path = new Vector(); + path.add (c); + + Component parent = c.getParent (); + + while (parent instanceof JMenu + || parent instanceof JPopupMenu + || parent instanceof JMenuItem + || parent instanceof JMenuBar) + { + path.add (parent); + parent = parent.getParent (); + } + + MenuElement[] pathArray = new MenuElement[path.size ()]; + + for (int i = 0; i < path.size (); i++) + pathArray[i] = (MenuElement) path.get (path.size () - i - 1); + return pathArray; + } + } // class MenuSelectionManager diff --git a/libjava/javax/swing/RepaintManager.java b/libjava/javax/swing/RepaintManager.java index 55d62ae5f80..ace19cb27a5 100644 --- a/libjava/javax/swing/RepaintManager.java +++ b/libjava/javax/swing/RepaintManager.java @@ -35,248 +35,496 @@ this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ - package javax.swing; import java.awt.Component; import java.awt.Dimension; import java.awt.Image; import java.awt.Rectangle; +import java.util.AbstractMap; +import java.util.Enumeration; import java.util.Hashtable; +import java.util.HashMap; +import java.util.Iterator; import java.util.Vector; + /** - * RepaintManager - * @author Andrew Selkirk - * @version 1.0 + * <p>The repaint manager holds a set of dirty regions, invalid components, + * and a double buffer surface. The dirty regions and invalid components + * are used to coalesce multiple revalidate() and repaint() calls in the + * component tree into larger groups to be refreshed "all at once"; the + * double buffer surface is used by root components to paint + * themselves.</p> + * + * <p>In general, painting is very confusing in swing. see <a + * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">this + * document</a> for more details.</p> + * + * @author Graydon Hoare (graydon@redhat.com) */ -public class RepaintManager { - - //------------------------------------------------------------- - // Variables -------------------------------------------------- - //------------------------------------------------------------- - - /** - * dirtyComponents - */ - Hashtable dirtyComponents; - - /** - * tmpDirtyComponents - */ - Hashtable tmpDirtyComponents; - - /** - * invalidComponents - */ - Vector invalidComponents; - - /** - * doubleBufferingEnabled - */ - boolean doubleBufferingEnabled; - - /** - * doubleBuffer - */ - Image doubleBuffer; - - /** - * doubleBufferSize - */ - Dimension doubleBufferSize; - - /** - * doubleBufferMaxSize - */ - private Dimension doubleBufferMaxSize; - - /** - * resetDoubleBuffer - */ - private boolean resetDoubleBuffer; - - /** - * repaintManagerKey - */ - private static final Object repaintManagerKey = null; // TODO - - /** - * tmp - */ - Rectangle tmp; - - - //------------------------------------------------------------- - // Initialization --------------------------------------------- - //------------------------------------------------------------- - - /** - * Constructor RepaintManager - */ - public RepaintManager() { - // TODO - } // RepaintManager() - - - //------------------------------------------------------------- - // Methods ---------------------------------------------------- - //------------------------------------------------------------- - - /** - * toString - * @returns String - */ - public synchronized String toString() { - return null; // TODO - } // toString() - - /** - * currentManager - * @param component TODO - * @returns RepaintManager - */ - public static RepaintManager currentManager(Component component) { - return null; // TODO - } // currentManager() - - /** - * currentManager - * @param component TODO - * @returns RepaintManager - */ - public static RepaintManager currentManager(JComponent component) { - return null; // TODO - } // currentManager() - - /** - * setCurrentManager - * @param manager TODO - */ - public static void setCurrentManager(RepaintManager manager) { - // TODO - } // setCurrentManager() - - /** - * addInvalidComponent - * @param component TODO - */ - public synchronized void addInvalidComponent(JComponent component) { - // TODO - } // addInvalidComponent() - - /** - * removeInvalidComponent - * @param component TODO - */ - public synchronized void removeInvalidComponent(JComponent component) { - // TODO - } // removeInvalidComponent() - - /** - * addDirtyRegion - * @param component TODO - * @param x TODO - * @param y TODO - * @param w TODO - * @param h TODO - */ - public synchronized void addDirtyRegion(JComponent component, int x, - int y, int w, int h) { - // TODO - } // addDirtyRegion() - - /** - * getDirtyRegion - * @param component TODO - * @returns Rectangle - */ - public Rectangle getDirtyRegion(JComponent component) { - return null; // TODO - } // getDirtyRegion() - - /** - * markCompletelyDirty - * @param component TODO - */ - public void markCompletelyDirty(JComponent component) { - // TODO - } // markCompletelyDirty() - - /** - * markCompletelyClean - * @param component TODO - */ - public void markCompletelyClean(JComponent component) { - // TODO - } // markCompletelyClean() - - /** - * isCompletelyDirty - * @param component TODO - * @returns boolean - */ - public boolean isCompletelyDirty(JComponent component) { - return false; // TODO - } // isCompletelyDirty() - - /** - * validateInvalidComponents - */ - public void validateInvalidComponents() { - // TODO - } // validateInvalidComponents() - - /** - * paintDirtyRegions - */ - public void paintDirtyRegions() { - // TODO - } // paintDirtyRegions() - - /** - * getOffscreenBuffer - * @param component TODO - * @param proposedWidth TODO - * @param proposedHeight TODO - * @returns Image - */ - public Image getOffscreenBuffer(Component component, - int proposedWidth, int proposedHeight) { - return null; // TODO - } // getOffscreenBuffer() - - /** - * getDoubleBufferMaximumSize - * @returns Dimension - */ - public Dimension getDoubleBufferMaximumSize() { - return null; // TODO - } // getDoubleBufferMaximumSize() - - /** - * setDoubleBufferMaximumSize - * @param size TODO - */ - public void setDoubleBufferMaximumSize(Dimension size) { - // TODO - } // setDoubleBufferMaximumSize() - - /** - * setDoubleBufferingEnabled - * @param buffer TODO - */ - public void setDoubleBufferingEnabled(boolean buffer) { - // TODO - } // setDoubleBufferingEnabled() - - /** - * isDoubleBufferingEnabled - * @returns boolean - */ - public boolean isDoubleBufferingEnabled() { - return false; // TODO - } // isDoubleBufferingEnabled() - - -} // RepaintManager +public class RepaintManager +{ + + /** + * <p>A helper class which is placed into the system event queue at + * various times in order to facilitate repainting and layout. There is + * typically only one of these objects active at any time. When the + * {@link RepaintManager} is told to queue a repaint, it checks to see if + * a {@link RepaintWorker} is "live" in the system event queue, and if + * not it inserts one using {@link SwingUtilities.invokeLater}.</p> + * + * <p>When the {@link RepaintWorker} comes to the head of the system + * event queue, its {@link RepaintWorker#run} method is executed by the + * swing paint thread, which revalidates all invalid components and + * repaints any damage in the swing scene.</p> + */ + + protected class RepaintWorker + implements Runnable + { + boolean live; + public RepaintWorker() + { + live = false; + } + public synchronized void setLive(boolean b) + { + live = b; + } + public synchronized boolean isLive() + { + return live; + } + public void run() + { + RepaintManager rm = RepaintManager.globalManager; + setLive(false); + rm.validateInvalidComponents(); + rm.paintDirtyRegions(); + } + } + + + /** + * A table storing the dirty regions of components. The keys of this + * table are components, the values are rectangles. Each component maps + * to exactly one rectangle. When more regions are marked as dirty on a + * component, they are union'ed with the existing rectangle. + * + * @see #addDirtyRegion + * @see #getDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyClean + * @see #markCompletelyDirty + */ + Hashtable dirtyComponents; + + /** + * A single, shared instance of the helper class. Any methods which mark + * components as invalid or dirty eventually activate this instance. It + * is added to the event queue if it is not already active, otherwise + * reused. + * + * @see #addDirtyRegion + * @see #addInvalidComponent + */ + RepaintWorker repaintWorker; + + /** + * The set of components which need revalidation, in the "layout" sense. + * There is no additional information about "what kind of layout" they + * need (as there is with dirty regions), so it is just a vector rather + * than a table. + * + * @see #addInvalidComponent + * @see #removeInvalidComponent + * @see #validateInvalidComponents + */ + Vector invalidComponents; + + /** + * Whether or not double buffering is enabled on this repaint + * manager. This is merely a hint to clients; the RepaintManager will + * always return an offscreen buffer when one is requested. + * + * @see #getDoubleBufferingEnabled + * @see #setDoubleBufferingEnabled + */ + boolean doubleBufferingEnabled; + + /** + * The current offscreen buffer. This is reused for all requests for + * offscreen drawing buffers. It grows as necessary, up to {@link + * #doubleBufferMaximumSize}, but there is only one shared instance. + * + * @see #getOffscreenBuffer + * @see #doubleBufferMaximumSize + */ + Image doubleBuffer; + + /** + * The maximum width and height to allocate as a double buffer. Requests + * beyond this size are ignored. + * + * @see #paintDirtyRegions + * @see #getDoubleBufferMaximumSize + * @see #setDoubleBufferMaximumSize + */ + Dimension doubleBufferMaximumSize; + + + /** + * The global, shared RepaintManager instance. This is reused for all + * components in all windows. + * + * @see #currentManager + * @see #setCurrentManager + */ + private static RepaintManager globalManager; + + /** + * Create a new RepaintManager object. + */ + public RepaintManager() + { + dirtyComponents = new Hashtable(); + invalidComponents = new Vector(); + repaintWorker = new RepaintWorker(); + doubleBufferMaximumSize = new Dimension(2000,2000); + doubleBufferingEnabled = true; + } + + /** + * Get the value of the shared {@link #globalManager} instance, possibly + * returning a special manager associated with the specified + * component. The default implementaiton ignores the component parameter. + * + * @param component A component to look up the manager of + * + * @return The current repaint manager + * + * @see #setCurrentManager + */ + public static RepaintManager currentManager(Component component) + { + if (globalManager == null) + globalManager = new RepaintManager(); + return globalManager; + } + + /** + * Get the value of the shared {@link #globalManager} instance, possibly + * returning a special manager associated with the specified + * component. The default implementaiton ignores the component parameter. + * + * @param component A component to look up the manager of + * + * @return The current repaint manager + * + * @see #setCurrentManager + */ + public static RepaintManager currentManager(JComponent component) + { + return currentManager((Component)component); + } + + /** + * Set the value of the shared {@link #globalManager} instance. + * + * @param manager The new value of the shared instance + * + * @see #currentManager + */ + public static void setCurrentManager(RepaintManager manager) + { + globalManager = manager; + } + + /** + * Add a component to the {@link #invalidComponents} vector. If the + * {@link #repaintWorker} class is not active, insert it in the system + * event queue. + * + * @param component The component to add + * + * @see #removeInvalidComponent + */ + public synchronized void addInvalidComponent(JComponent component) + { + while ((component.getParent() != null) + && (component.getParent() instanceof JComponent) + && (component.isValidateRoot())) + component = (JComponent) component.getParent(); + + if (invalidComponents.contains(component)) + return; + + invalidComponents.add(component); + component.invalidate(); + + if (! repaintWorker.isLive()) + { + repaintWorker.setLive(true); + SwingUtilities.invokeLater(repaintWorker); + } + } + + /** + * Remove a component from the {@link #invalidComponents} vector. + * + * @param component The component to remove + * + * @see #addInvalidComponent + */ + public synchronized void removeInvalidComponent(JComponent component) + { + invalidComponents.removeElement(component); + } + + /** + * Add a region to the set of dirty regions for a specified component. + * This involves union'ing the new region with any existing dirty region + * associated with the component. If the {@link #repaintWorker} class + * is not active, insert it in the system event queue. + * + * @param component The component to add a dirty region for + * @param x The left x coordinate of the new dirty region + * @param y The top y coordinate of the new dirty region + * @param w The width of the new dirty region + * @param h The height of the new dirty region + * + * @see #addDirtyRegion + * @see #getDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyClean + * @see #markCompletelyDirty + */ + public synchronized void addDirtyRegion(JComponent component, int x, int y, + int w, int h) + { + Rectangle r = new Rectangle(x, y, w, h); + if (dirtyComponents.containsKey(component)) + r = r.union((Rectangle)dirtyComponents.get(component)); + dirtyComponents.put(component, r); + if (! repaintWorker.isLive()) + { + repaintWorker.setLive(true); + SwingUtilities.invokeLater(repaintWorker); + } + } + + /** + * Get the dirty region associated with a component, or <code>null</code> + * if the component has no dirty region. + * + * @param component The component to get the dirty region of + * + * @return The dirty region of the component + * + * @see #dirtyComponents + * @see #addDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyClean + * @see #markCompletelyDirty + */ + public Rectangle getDirtyRegion(JComponent component) + { + return (Rectangle) dirtyComponents.get(component); + } + + /** + * Mark a component as dirty over its entire bounds. + * + * @param component The component to mark as dirty + * + * @see #dirtyComponents + * @see #addDirtyRegion + * @see #getDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyClean + */ + public void markCompletelyDirty(JComponent component) + { + Rectangle r = component.getBounds(); + addDirtyRegion(component, r.x, r.y, r.width, r.height); + } + + /** + * Remove all dirty regions for a specified component + * + * @param component The component to mark as clean + * + * @see #dirtyComponents + * @see #addDirtyRegion + * @see #getDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyDirty + */ + public void markCompletelyClean(JComponent component) + { + dirtyComponents.remove(component); + } + + /** + * Return <code>true</code> if the specified component is completely + * contained within its dirty region, otherwise <code>false</code> + * + * @param component The component to check for complete dirtyness + * + * @return Whether the component is completely dirty + * + * @see #dirtyComponents + * @see #addDirtyRegion + * @see #getDirtyRegion + * @see #isCompletelyDirty + * @see #markCompletelyClean + */ + public boolean isCompletelyDirty(JComponent component) + { + Rectangle dirty = (Rectangle) dirtyComponents.get(component); + if (dirty == null) + return false; + Rectangle r = component.getBounds(); + if (r == null) + return true; + return dirty.contains(r); + } + + /** + * Validate all components which have been marked invalid in the {@link + * #invalidComponents} vector. + */ + public void validateInvalidComponents() + { + for (Enumeration e = invalidComponents.elements(); e.hasMoreElements(); ) + { + JComponent comp = (JComponent) e.nextElement(); + if (! (comp.isVisible() && comp.isShowing())) + continue; + comp.validate(); + } + invalidComponents.clear(); + } + + /** + * Repaint all regions of all components which have been marked dirty in + * the {@link #dirtyComponents} table. + */ + public void paintDirtyRegions() + { + // step 1: pull out roots and calculate spanning damage + + HashMap roots = new HashMap(); + for (Enumeration e = dirtyComponents.keys(); e.hasMoreElements(); ) + { + JComponent comp = (JComponent) e.nextElement(); + if (! (comp.isVisible() && comp.isShowing())) + continue; + Rectangle damaged = getDirtyRegion(comp); + if (damaged.width == 0 || damaged.height == 0) + continue; + JRootPane root = comp.getRootPane(); + Rectangle rootDamage = SwingUtilities.convertRectangle(comp, damaged, root); + if (! roots.containsKey(root)) + { + roots.put(root, rootDamage); + } + else + { + roots.put(root, ((Rectangle)roots.get(root)).union(rootDamage)); + } + } + dirtyComponents.clear(); + + // step 2: paint those roots + Iterator i = roots.iterator(AbstractMap.ENTRIES); + while(i.hasNext()) + { + AbstractMap.BasicMapEntry ent = (AbstractMap.BasicMapEntry) i.next(); + JRootPane root = (JRootPane) ent.getKey(); + Rectangle rect = (Rectangle) ent.getValue(); + root.paintImmediately(rect); + } + } + + /** + * Get an offscreen buffer for painting a component's image. This image + * may be smaller than the proposed dimensions, depending on the value of + * the {@link #doubleBufferMaximumSize} property. + * + * @param component The component to return an offscreen buffer for + * @param proposedWidth The proposed width of the offscreen buffer + * @param proposedHeight The proposed height of the offscreen buffer + * + * @return A shared offscreen buffer for painting + * + * @see #doubleBuffer + */ + public Image getOffscreenBuffer(Component component, int proposedWidth, + int proposedHeight) + { + if (doubleBuffer == null + || (((doubleBuffer.getWidth(null) < proposedWidth) + || (doubleBuffer.getHeight(null) < proposedHeight)) + && (proposedWidth < doubleBufferMaximumSize.width) + && (proposedHeight < doubleBufferMaximumSize.height))) + { + doubleBuffer = component.createImage(proposedWidth, proposedHeight); + } + return doubleBuffer; + } + + /** + * Get the value of the {@link #doubleBufferMaximumSize} property. + * + * @return The current value of the property + * + * @see #setDoubleBufferMaximumSize + */ + public Dimension getDoubleBufferMaximumSize() + { + return doubleBufferMaximumSize; + } + + /** + * Set the value of the {@link #doubleBufferMaximumSize} property. + * + * @param size The new value of the property + * + * @see #getDoubleBufferMaximumSize + */ + public void setDoubleBufferMaximumSize(Dimension size) + { + doubleBufferMaximumSize = size; + } + + /** + * Set the value of the {@link #doubleBufferingEnabled} property. + * + * @param buffer The new value of the property + * + * @see #getDoubleBufferingEnabled + */ + public void setDoubleBufferingEnabled(boolean buffer) + { + doubleBufferingEnabled = buffer; + } + + /** + * Get the value of the {@link #doubleBufferingEnabled} property. + * + * @return The current value of the property + * + * @see #setDoubleBufferingEnabled + */ + public boolean isDoubleBufferingEnabled() + { + return doubleBufferingEnabled; + } + + public String toString() + { + return "RepaintManager"; + } +} diff --git a/libjava/javax/swing/ScrollPaneLayout.java b/libjava/javax/swing/ScrollPaneLayout.java index c8573589f29..16b6c0fae33 100644 --- a/libjava/javax/swing/ScrollPaneLayout.java +++ b/libjava/javax/swing/ScrollPaneLayout.java @@ -227,7 +227,17 @@ public class ScrollPaneLayout if (horizontalScrollBar != null) horizontalScrollBarSize.setSize(horizontalScrollBar.getPreferredSize()); - + + /* + System.err.println("widths: [vp=" + viewportSize.width + + ", h=" + columnHeaderSize.width + + ", sc=" + horizontalScrollBarSize.width + "]"); + + System.err.println("heights: [vp=" + viewportSize.height + + ", h=" + rowHeaderSize.height + + ", sc=" + verticalScrollBarSize.height + "]"); + */ + return new Dimension(insetsSize.width + viewportSize.width + viewportInsetsSize.width @@ -336,9 +346,9 @@ public class ScrollPaneLayout synchronized (sc.getTreeLock ()) { Rectangle scrollPaneBounds = sc.getBounds(); - Dimension viewportSize = new Dimension(0,0); - Dimension viewSize = new Dimension(0,0); JViewport viewport = sc.getViewport(); + Dimension viewportSize = viewport.getSize(); + Dimension viewSize = viewport.getView().getSize(); int x1 = 0, x2 = 0, x3 = 0, x4 = 0; int y1 = 0, y2 = 0, y3 = 0, y4 = 0; @@ -395,7 +405,7 @@ public class ScrollPaneLayout rowHeader.setBounds(new Rectangle(x1, y2, x2-x1, y3-y2)); if (showVsb) - verticalScrollBar.setBounds(new Rectangle(x3, y2, x4-x3, y3-y2)); + verticalScrollBar.setBounds(new Rectangle(x3, y2, x4-x3, y3-y2)); if (showHsb) horizontalScrollBar.setBounds(new Rectangle(x2, y3, x3-x2, y4-y3)); diff --git a/libjava/javax/swing/SwingUtilities.java b/libjava/javax/swing/SwingUtilities.java index e75a95e0f24..d543f0be48b 100644 --- a/libjava/javax/swing/SwingUtilities.java +++ b/libjava/javax/swing/SwingUtilities.java @@ -43,6 +43,7 @@ import java.awt.ComponentOrientation; import java.awt.Container; import java.awt.Font; import java.awt.FontMetrics; +import java.awt.Frame; import java.awt.Graphics; import java.awt.Insets; import java.awt.Point; @@ -64,6 +65,8 @@ import java.lang.reflect.InvocationTargetException; public class SwingUtilities implements SwingConstants { + private static Frame ownerFrame; + /** * Calculates the portion of the base rectangle which is inside the * insets. @@ -830,5 +833,18 @@ public class SwingUtilities implements SwingConstants paintComponent(g, c, p, r.x, r.y, r.width, r.height); } + /** + * This method returns the common Frame owner used in JDialogs + * when no owner is provided. + * + * @return The common Frame + */ + static Frame getOwnerFrame() + { + if (ownerFrame == null) + ownerFrame = new Frame(); + return ownerFrame; + } + } diff --git a/libjava/javax/swing/UIManager.java b/libjava/javax/swing/UIManager.java index 81e8ea54e59..02b7823c934 100644 --- a/libjava/javax/swing/UIManager.java +++ b/libjava/javax/swing/UIManager.java @@ -178,8 +178,7 @@ public class UIManager implements Serializable */ public static Dimension getDimension(Object key) { - System.out.println("UIManager.getDim"); - return new Dimension(200,100); + return (Dimension) getLookAndFeel().getDefaults().get(key); } /** diff --git a/libjava/javax/swing/ViewportLayout.java b/libjava/javax/swing/ViewportLayout.java index 4c774d59f40..91bcf9b5e60 100644 --- a/libjava/javax/swing/ViewportLayout.java +++ b/libjava/javax/swing/ViewportLayout.java @@ -41,37 +41,62 @@ import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.LayoutManager; +import java.awt.Point; +import java.awt.Rectangle; import java.io.Serializable; /** * ViewportLayout * @author Andrew Selkirk - * @version 1.0 + * @author Graydon Hoare */ public class ViewportLayout implements LayoutManager, Serializable { static final long serialVersionUID = -788225906076097229L; - public ViewportLayout() { - } - public void addLayoutComponent(String name, Component c) { - // ignore - } - public void removeLayoutComponent(Component c) { - // ignore - } - public Dimension preferredLayoutSize(Container parent) { - return null; - } - public Dimension minimumLayoutSize(Container parent) { - return null; - } - public void layoutContainer(Container parent) { - if (parent.countComponents() == 1) - { - // This should usually be true, but if it's not it is - // probably nicer if we do not panic. - Component c = parent.getComponent(0); - } - } + public ViewportLayout() + { + } + public void addLayoutComponent(String name, Component c) + { + } + public void removeLayoutComponent(Component c) + { + } + public Dimension preferredLayoutSize(Container parent) + { + JViewport vp = (JViewport)parent; + Component view = vp.getView(); + if (view instanceof Scrollable) + { + Scrollable sc = (Scrollable) view; + Dimension d = sc.getPreferredScrollableViewportSize(); + // System.err.println(this + ".preferredLayoutSize() : scrollable -> " + d); + return d; + } + else + return view.getPreferredSize(); + } + public Dimension minimumLayoutSize(Container parent) + { + JViewport vp = (JViewport)parent; + Component view = vp.getView(); + return view.getMinimumSize(); + } + public void layoutContainer(Container parent) + { + JViewport vp = (JViewport)parent; + Component view = vp.getView(); + Rectangle portBounds = vp.getBounds(); + Dimension viewMinimum = view.getMinimumSize(); + int width = Math.max(portBounds.width, + viewMinimum.width); + int height = Math.max(portBounds.height, + viewMinimum.height); + int x = Math.min(0, portBounds.width - width); + int y = Math.min(0, portBounds.height - height); + // System.err.println(this + ".layoutContainer() : width = " + width + ", height = " + height); + vp.setViewPosition(new Point(x, y)); + vp.setViewSize(new Dimension(width, height)); + } } diff --git a/libjava/javax/swing/event/SwingPropertyChangeSupport.java b/libjava/javax/swing/event/SwingPropertyChangeSupport.java index 1f08cbfec9c..b2c6a4e4def 100644 --- a/libjava/javax/swing/event/SwingPropertyChangeSupport.java +++ b/libjava/javax/swing/event/SwingPropertyChangeSupport.java @@ -210,8 +210,9 @@ public final class SwingPropertyChangeSupport PropertyChangeListener listener; // Check Values if they are equal - if (event.getOldValue() == null || event.getNewValue() == null || - event.getOldValue().equals(event.getNewValue()) == true) { + if (event.getOldValue() == null && event.getNewValue() == null || + (event.getOldValue() != null && event.getNewValue() != null && + event.getOldValue().equals(event.getNewValue()))) { return; } // if diff --git a/libjava/javax/swing/plaf/basic/BasicButtonUI.java b/libjava/javax/swing/plaf/basic/BasicButtonUI.java index 663050ee685..5ebde8f57fb 100644 --- a/libjava/javax/swing/plaf/basic/BasicButtonUI.java +++ b/libjava/javax/swing/plaf/basic/BasicButtonUI.java @@ -92,6 +92,7 @@ public class BasicButtonUI extends ButtonUI b.setBackground(defaults.getColor("Button.background")); b.setMargin(defaults.getInsets("Button.margin")); b.setBorder(defaults.getBorder("Button.border")); + b.setOpaque(true); } protected void uninstallDefaults(AbstractButton b) diff --git a/libjava/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java b/libjava/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java index 84c8e392357..553cec3d5c0 100644 --- a/libjava/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java +++ b/libjava/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java @@ -38,7 +38,6 @@ exception statement from your version. */ package javax.swing.plaf.basic; import java.awt.event.MouseEvent; - import javax.swing.JComponent; import javax.swing.JMenuItem; import javax.swing.MenuElement; @@ -48,18 +47,39 @@ import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; +/** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.3 $ + */ public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI { + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public static ComponentUI createUI(final JComponent c) { return new BasicCheckBoxMenuItemUI(); } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ protected String getPropertyPrefix() { return null; // TODO } + /** + * DOCUMENT ME! + */ protected void installDefaults() { super.installDefaults(); @@ -68,6 +88,14 @@ public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI checkIcon = defaults.getIcon("CheckBoxMenuItem.checkIcon"); } + /** + * DOCUMENT ME! + * + * @param item DOCUMENT ME! + * @param e DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ void processMouseEvent(JMenuItem item, MouseEvent e, MenuElement[] path, MenuSelectionManager manager) { diff --git a/libjava/javax/swing/plaf/basic/BasicIconFactory.java b/libjava/javax/swing/plaf/basic/BasicIconFactory.java index ef071aa0b77..9f3a5ac5e86 100644 --- a/libjava/javax/swing/plaf/basic/BasicIconFactory.java +++ b/libjava/javax/swing/plaf/basic/BasicIconFactory.java @@ -82,7 +82,34 @@ public class BasicIconFactory implements Serializable } public static Icon getMenuArrowIcon() { - return new DummyIcon(); + return new Icon() + { + public int getIconHeight() + { + return 12; + } + + public int getIconWidth() + { + return 12; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.translate(x, y); + + Color saved = g.getColor(); + + g.setColor(Color.BLACK); + + g.fillPolygon(new Polygon(new int[] { 3, 9, 3 }, + new int[] { 2, 6, 10 }, + 3)); + + g.setColor(saved); + g.translate(-x, -y); + } + }; } public static Icon getCheckBoxIcon() diff --git a/libjava/javax/swing/plaf/basic/BasicLabelUI.java b/libjava/javax/swing/plaf/basic/BasicLabelUI.java index 669c7063645..782c2f0e5fa 100644 --- a/libjava/javax/swing/plaf/basic/BasicLabelUI.java +++ b/libjava/javax/swing/plaf/basic/BasicLabelUI.java @@ -168,23 +168,20 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener vr.width = 0; if (vr.height < 0) vr.height = 0; - + Icon icon = (b.isEnabled()) ? b.getIcon() : b.getDisabledIcon(); String text = layoutCL(b, fm, b.getText(), icon, vr, ir, tr); - if (b.isOpaque()) - { - g.setColor(b.getBackground()); - g.fillRect(vr.x, vr.y, vr.width, vr.height); - } - if (icon != null) icon.paintIcon(b, g, ir.x, ir.y); - if (b.isEnabled()) - paintEnabledText(b, g, text, tr.x, tr.y + fm.getAscent()); - else - paintDisabledText(b, g, text, tr.x, tr.y + fm.getAscent()); + if (text != null && ! text.equals("")) + { + if (b.isEnabled()) + paintEnabledText(b, g, text, tr.x, tr.y + fm.getAscent()); + else + paintDisabledText(b, g, text, tr.x, tr.y + fm.getAscent()); + } g.setFont(saved_font); } @@ -354,6 +351,7 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener c.setBackground(defaults.getColor("Label.background")); c.setFont(defaults.getFont("Label.font")); c.setBorder(defaults.getBorder("Label.border")); + c.setOpaque(true); //XXX: There are properties we don't use called disabledForeground //and disabledShadow. } diff --git a/libjava/javax/swing/plaf/basic/BasicListUI.java b/libjava/javax/swing/plaf/basic/BasicListUI.java index 4be87652735..b356bdf2a9a 100644 --- a/libjava/javax/swing/plaf/basic/BasicListUI.java +++ b/libjava/javax/swing/plaf/basic/BasicListUI.java @@ -502,6 +502,7 @@ public class BasicListUI extends ListUI list.setBackground(defaults.getColor("List.background")); list.setSelectionForeground(defaults.getColor("List.selectionForeground")); list.setSelectionBackground(defaults.getColor("List.selectionBackground")); + list.setOpaque(true); } /** @@ -620,7 +621,8 @@ public class BasicListUI extends ListUI maybeUpdateLayoutState(); if (list.getModel().getSize() == 0) return new Dimension(0, 0); - Rectangle bounds = getCellBounds(list, 0, list.getModel().getSize() - 1); + int nrows = Math.min(list.getVisibleRowCount(), list.getModel().getSize()); + Rectangle bounds = getCellBounds(list, 0, nrows - 1); return bounds.getSize(); } @@ -696,11 +698,11 @@ public class BasicListUI extends ListUI public int locationToIndex(JList list, Point location) { - throw new Error("Not implemented"); + return convertYToRow(location.y); } public Point indexToLocation(JList list, int index) { - throw new Error("Not implemented"); + return new Point(0, convertRowToY(index)); } } diff --git a/libjava/javax/swing/plaf/basic/BasicLookAndFeel.java b/libjava/javax/swing/plaf/basic/BasicLookAndFeel.java index 7a60c8e9336..f4466ef5083 100644 --- a/libjava/javax/swing/plaf/basic/BasicLookAndFeel.java +++ b/libjava/javax/swing/plaf/basic/BasicLookAndFeel.java @@ -249,7 +249,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel "Button.foreground", new ColorUIResource(Color.black), "Button.highlight", new ColorUIResource(Color.white), "Button.light", new ColorUIResource(Color.lightGray.brighter()), - "Button.margin", new InsetsUIResource(2, 14, 2, 14), + "Button.margin", new InsetsUIResource(2, 2, 2, 2), "Button.shadow", new ColorUIResource(Color.gray), "Button.textIconGap", new Integer(4), "Button.textShiftOffset", new Integer(0), @@ -694,7 +694,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel }), "SplitPane.background", new ColorUIResource(Color.lightGray), "SplitPane.border", new BasicBorders.SplitPaneBorder(null, null), - "SplitPane.dividerSize", new Integer(7), + "SplitPane.dividerSize", new Integer(10), "SplitPane.highlight", new ColorUIResource(Color.white), "SplitPane.shadow", new ColorUIResource(Color.gray), "TabbedPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { diff --git a/libjava/javax/swing/plaf/basic/BasicMenuBarUI.java b/libjava/javax/swing/plaf/basic/BasicMenuBarUI.java new file mode 100644 index 00000000000..0fe57f1c497 --- /dev/null +++ b/libjava/javax/swing/plaf/basic/BasicMenuBarUI.java @@ -0,0 +1,277 @@ +/* BasicMenuUI.java + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.awt.Dimension; +import javax.swing.BoxLayout; +import javax.swing.ButtonModel; +import javax.swing.Icon; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.KeyStroke; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuKeyEvent; +import javax.swing.event.MenuKeyListener; +import javax.swing.event.MenuListener; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.MenuBarUI; +import javax.swing.plaf.MenuItemUI; +import java.awt.Insets; +import java.awt.GridLayout; + + +/** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.1 $ + */ +public class BasicMenuBarUI extends MenuBarUI +{ + protected ChangeListener changeListener; + protected ContainerListener containerListener; + protected PropertyChangeListener propertyChangeListener; + protected JMenuBar menuBar; + + /** + * Creates a new BasicMenuBarUI object. + */ + public BasicMenuBarUI() + { + changeListener = createChangeListener(); + containerListener = createContainerListener(); + propertyChangeListener = new PropertyChangeHandler(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected ChangeListener createChangeListener() + { + return new ChangeHandler(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected ContainerListener createContainerListener() + { + return new ContainerHandler(); + } + + /** + * DOCUMENT ME! + * + * @param x DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicMenuBarUI(); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension getMaximumSize(JComponent c) + { + // let layout manager calculate its size + return null; + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension getMinimumSize(JComponent c) + { + // let layout manager calculate its size + return null; + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension getPreferredSize(JComponent c) + { + // let layout manager calculate its size + return null; + } + + /** + * DOCUMENT ME! + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + menuBar.setBackground(defaults.getColor("MenuBar.background")); + menuBar.setBorder(defaults.getBorder("MenuBar.border")); + menuBar.setFont(defaults.getFont("MenuBar.font")); + menuBar.setForeground(defaults.getColor("MenuBar.foreground")); + } + + /** + * DOCUMENT ME! + */ + protected void installKeyboardActions() + { + } + + /** + * DOCUMENT ME! + */ + protected void installListeners() + { + menuBar.addContainerListener(containerListener); + menuBar.addPropertyChangeListener(propertyChangeListener); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + */ + public void installUI(JComponent c) + { + super.installUI(c); + menuBar = (JMenuBar) c; + menuBar.setLayout(new BoxLayout(menuBar, BoxLayout.X_AXIS)); + installDefaults(); + installListeners(); + } + + /** + * DOCUMENT ME! + */ + protected void uninstallDefaults() + { + menuBar.setBackground(null); + menuBar.setBorder(null); + menuBar.setFont(null); + menuBar.setForeground(null); + } + + /** + * DOCUMENT ME! + */ + protected void uninstallKeyboardActions() + { + } + + /** + * DOCUMENT ME! + */ + protected void uninstallListeners() + { + menuBar.removeContainerListener(containerListener); + menuBar.removePropertyChangeListener(propertyChangeListener); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + */ + public void uninstallUI(JComponent c) + { + uninstallDefaults(); + uninstallListeners(); + menuBar= null; + } + + protected class ChangeHandler implements ChangeListener + { + public void stateChanged(ChangeEvent event) + { + } + } + + protected class ContainerHandler implements ContainerListener + { + public void componentAdded(ContainerEvent e) + { + } + + public void componentRemoved(ContainerEvent e) + { + } + } + + protected class PropertyChangeHandler implements PropertyChangeListener + { + public void propertyChange(PropertyChangeEvent e) + { + } + } +} diff --git a/libjava/javax/swing/plaf/basic/BasicMenuItemUI.java b/libjava/javax/swing/plaf/basic/BasicMenuItemUI.java index 886ca9dbce6..29da4ec3bf2 100644 --- a/libjava/javax/swing/plaf/basic/BasicMenuItemUI.java +++ b/libjava/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; import java.awt.Color; +import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; @@ -47,12 +48,17 @@ import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; - +import java.beans.PropertyChangeListener; +import java.util.Vector; import javax.swing.AbstractButton; import javax.swing.ButtonModel; import javax.swing.Icon; +import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; +import javax.swing.JMenu; import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButtonMenuItem; import javax.swing.KeyStroke; import javax.swing.MenuElement; import javax.swing.MenuSelectionManager; @@ -68,116 +74,219 @@ import javax.swing.plaf.ComponentUI; import javax.swing.plaf.MenuItemUI; +/** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.10 $ + */ public class BasicMenuItemUI extends MenuItemUI { - /** Font to be used when displaying menu item's accelerator. */ + /** + * Font to be used when displaying menu item's accelerator. + */ protected Font acceleratorFont; - /** Color to be used when displaying menu item's accelerator. */ + /** + * Color to be used when displaying menu item's accelerator. + */ protected Color acceleratorForeground; - /** Color to be used when displaying menu item's accelerator - * when menu item is selected. - */ + /** + * Color to be used when displaying menu item's accelerator when menu item is + * selected. + */ protected Color acceleratorSelectionForeground; - + /** - * Icon that is displayed after the text to indicated that this menu - * contains submenu. + * Icon that is displayed after the text to indicated that this menu contains + * submenu. */ protected Icon arrowIcon; - + /** * Icon that is displayed before the text. This icon is only used in * JCheckBoxMenuItem or JRadioBoxMenuItem. */ protected Icon checkIcon; - /** Number of spaces between icon and text. */ + /** + * Number of spaces between icon and text. + */ protected int defaultTextIconGap = 4; - - /** Color of the text when menu item is disabled*/ + + /** + * Color of the text when menu item is disabled + */ protected Color disabledForeground; - - /** The menu Drag mouse listener listening to the menu item. */ + + /** + * The menu Drag mouse listener listening to the menu item. + */ protected MenuDragMouseListener menuDragMouseListener; - - /** The menu item itself*/ + + /** + * The menu item itself + */ protected JMenuItem menuItem; - - /** Menu Key listener listening to the menu item. */ + + /** + * Menu Key listener listening to the menu item. + */ protected MenuKeyListener menuKeyListener; - - /** mouse input listener listening to menu item. */ + + /** + * mouse input listener listening to menu item. + */ protected MouseInputListener mouseInputListener; - - /** Indicates if border should be painted */ + + /** + * Indicates if border should be painted + */ protected boolean oldBorderPainted; - /** Color of text that is used when menu item is selected */ + /** + * Color of text that is used when menu item is selected + */ protected Color selectionBackground; - - /** Color of the background that is used when menu item is selected.*/ + + /** + * Color of the background that is used when menu item is selected. + */ protected Color selectionForeground; - /** String that separates description of the modifiers and the key*/ + /** + * String that separates description of the modifiers and the key + */ private String acceleratorDelimiter; - - /** Number of spaces between accelerator and menu item's label. */ + private PropertyChangeListener propertyChangeListener; + + /** + * Number of spaces between accelerator and menu item's label. + */ private int defaultAcceleratorLabelGap = 4; - // Constructor Summary - BasicMenuItemUI() + public BasicMenuItemUI() { mouseInputListener = createMouseInputListener(menuItem); menuDragMouseListener = createMenuDragMouseListener(menuItem); menuKeyListener = createMenuKeyListener(menuItem); + propertyChangeListener = new PropertyChangeHandler(); } - // Method Summary protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) { return new MenuDragMouseHandler(); } + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ protected MenuKeyListener createMenuKeyListener(JComponent c) { return new MenuKeyHandler(); } + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ protected MouseInputListener createMouseInputListener(JComponent c) { return new MouseInputHandler(); } + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public static ComponentUI createUI(JComponent c) { return new BasicMenuItemUI(); } + /** + * DOCUMENT ME! + * + * @param msm DOCUMENT ME! + */ protected void doClick(MenuSelectionManager msm) { - // TODO + menuItem.doClick(); + msm.clearSelectedPath(); } + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public Dimension getMaximumSize(JComponent c) { - // TODO return null; } + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public Dimension getMinimumSize(JComponent c) { - // TODO return null; } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public MenuElement[] getPath() { - // TODO - return null; + Vector path = new Vector(); + Component c = menuItem; + while (c instanceof MenuElement) + { + path.add(c); + + if (c instanceof JPopupMenu) + c = ((JPopupMenu) c).getInvoker(); + else + c = c.getParent(); + } + + // convert from vector to array + MenuElement[] pathArray = new MenuElement[path.size()]; + for (int i = 0; i < path.size(); i++) + pathArray[i] = (MenuElement) path.get(path.size() - i - 1); + + return pathArray; } + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * @param checkIcon DOCUMENT ME! + * @param arrowIcon DOCUMENT ME! + * @param defaultTextIconGap DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap) @@ -186,51 +295,80 @@ public class BasicMenuItemUI extends MenuItemUI return null; } + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public Dimension getPreferredSize(JComponent c) { AbstractButton b = (AbstractButton) c; Dimension d = BasicGraphicsUtils.getPreferredButtonSize(b, defaultTextIconGap); - + // if menu item has accelerator then take accelerator's size into account // when calculating preferred size. - KeyStroke accelerator = ((JMenuItem) c).getAccelerator(); Rectangle rect; + if (accelerator != null) { - rect = getAcceleratorRect(accelerator, - b.getToolkit().getFontMetrics(acceleratorFont)); - - // add width of accelerator's text - d.width = d.width + rect.width + defaultAcceleratorLabelGap; - - // adjust the heigth of the preferred size if necessary - if (d.height < rect.height) - d.height = rect.height; + rect = getAcceleratorRect(accelerator, + b.getToolkit().getFontMetrics(acceleratorFont)); + + // add width of accelerator's text + d.width = d.width + rect.width + defaultAcceleratorLabelGap; + + // adjust the heigth of the preferred size if necessary + if (d.height < rect.height) + d.height = rect.height; } if (checkIcon != null) { - d.width = d.width + checkIcon.getIconWidth() + defaultTextIconGap; - if (checkIcon.getIconHeight() > d.height) - d.height = checkIcon.getIconHeight(); + d.width = d.width + checkIcon.getIconWidth() + defaultTextIconGap; + + if (checkIcon.getIconHeight() > d.height) + d.height = checkIcon.getIconHeight(); } - + + if (arrowIcon != null && (c instanceof JMenu)) + { + d.width = d.width + arrowIcon.getIconWidth() + defaultTextIconGap; + + if (arrowIcon.getIconHeight() > d.height) + d.height = arrowIcon.getIconHeight(); + } + return d; } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ protected String getPropertyPrefix() { // TODO return null; } + /** + * DOCUMENT ME! + * + * @param menuItem DOCUMENT ME! + */ protected void installComponents(JMenuItem menuItem) { // TODO } + /** + * DOCUMENT ME! + */ protected void installDefaults() { UIDefaults defaults = UIManager.getLookAndFeelDefaults(); @@ -240,27 +378,40 @@ public class BasicMenuItemUI extends MenuItemUI menuItem.setFont(defaults.getFont("MenuItem.font")); menuItem.setForeground(defaults.getColor("MenuItem.foreground")); menuItem.setMargin(defaults.getInsets("MenuItem.margin")); + menuItem.setOpaque(true); + acceleratorFont = defaults.getFont("MenuItem.acceleratorFont"); acceleratorForeground = defaults.getColor("MenuItem.acceleratorForeground"); acceleratorSelectionForeground = defaults.getColor("MenuItem.acceleratorSelectionForeground"); - arrowIcon = defaults.getIcon("MenuItem.arrowIcon"); selectionBackground = defaults.getColor("MenuItem.selectionBackground"); selectionForeground = defaults.getColor("MenuItem.selectionForeground"); acceleratorDelimiter = defaults.getString("MenuItem.acceleratorDelimiter"); } + /** + * DOCUMENT ME! + */ protected void installKeyboardActions() { // TODO } + /** + * DOCUMENT ME! + */ protected void installListeners() { menuItem.addMouseListener(mouseInputListener); menuItem.addMenuDragMouseListener(menuDragMouseListener); menuItem.addMenuKeyListener(menuKeyListener); + menuItem.addPropertyChangeListener(propertyChangeListener); } + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + */ public void installUI(JComponent c) { super.installUI(c); @@ -269,12 +420,25 @@ public class BasicMenuItemUI extends MenuItemUI installListeners(); } + /** + * DOCUMENT ME! + * + * @param g DOCUMENT ME! + * @param c DOCUMENT ME! + */ public void paint(Graphics g, JComponent c) { - paintMenuItem(g, c, checkIcon, arrowIcon, c.getBackground(), + paintMenuItem(g, c, checkIcon, arrowIcon, c.getBackground(), c.getForeground(), defaultTextIconGap); } + /** + * DOCUMENT ME! + * + * @param g DOCUMENT ME! + * @param menuItem DOCUMENT ME! + * @param bgColor DOCUMENT ME! + */ protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { Dimension size = getPreferredSize(menuItem); @@ -284,6 +448,17 @@ public class BasicMenuItemUI extends MenuItemUI g.setColor(foreground); } + /** + * DOCUMENT ME! + * + * @param g DOCUMENT ME! + * @param c DOCUMENT ME! + * @param checkIcon DOCUMENT ME! + * @param arrowIcon DOCUMENT ME! + * @param background DOCUMENT ME! + * @param foreground DOCUMENT ME! + * @param defaultTextIconGap DOCUMENT ME! + */ protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon, Icon arrowIcon, Color background, Color foreground, int defaultTextIconGap) @@ -295,7 +470,7 @@ public class BasicMenuItemUI extends MenuItemUI Rectangle br = new Rectangle(); // border rectangle Rectangle ar = new Rectangle(); // accelerator rectangle Rectangle cr = new Rectangle(); // checkIcon rectangle - + int vertAlign = b.getVerticalAlignment(); int horAlign = b.getHorizontalAlignment(); int vertTextPos = b.getVerticalTextPosition(); @@ -303,64 +478,67 @@ public class BasicMenuItemUI extends MenuItemUI Font f = c.getFont(); g.setFont(f); - FontMetrics fm = g.getFontMetrics(f); + FontMetrics fm = g.getFontMetrics(f); SwingUtilities.calculateInnerArea(b, br); - SwingUtilities.calculateInsetArea(br, b.getMargin(), vr); + SwingUtilities.calculateInsetArea(br, b.getMargin(), vr); paintBackground(g, (JMenuItem) c, c.getBackground()); - + if ((b.getModel().isArmed() && b.getModel().isPressed())) { - if (((AbstractButton) b).isContentAreaFilled()) - { - g.setColor(b.getBackground().darker()); - g.fillRect(br.x, br.y, br.width, br.height); - } + if (((AbstractButton) b).isContentAreaFilled()) + { + g.setColor(b.getBackground().darker()); + g.fillRect(br.x, br.y, br.width, br.height); + } } else { - if (((AbstractButton) b).isContentAreaFilled()) - { - g.setColor(b.getBackground()); - g.fillRect(br.x, br.y, br.width, br.height); - } + if (((AbstractButton) b).isContentAreaFilled()) + { + g.setColor(b.getBackground()); + g.fillRect(br.x, br.y, br.width, br.height); + } } - - + if (checkIcon != null) { - SwingUtilities.layoutCompoundLabel(c, fm, null, checkIcon, vertAlign, - horAlign, vertTextPos, horTextPos, - vr, cr, tr, defaultTextIconGap); - checkIcon.paintIcon(c, g, cr.x, cr.y); + SwingUtilities.layoutCompoundLabel(c, fm, null, checkIcon, vertAlign, + horAlign, vertTextPos, horTextPos, + vr, cr, tr, defaultTextIconGap); + checkIcon.paintIcon(c, g, cr.x, cr.y); - // We need to calculate position of the menu text and position of - // user menu icon if there exists one relative to the check icon. + // We need to calculate position of the menu text and position of + // user menu icon if there exists one relative to the check icon. // So we need to adjust view rectangle s.t. its starting point is at // checkIcon.width + defaultTextIconGap. - - vr.x = cr.x + cr.width + defaultTextIconGap; + vr.x = cr.x + cr.width + defaultTextIconGap; } - if (arrowIcon != null) + if (arrowIcon != null && (c instanceof JMenu)) { - // FIXME: if this menu contains a submenu, we need to draw arrow icon - // here as well + if (! ((JMenu) c).isTopLevelMenu()) + { + int width = arrowIcon.getIconWidth(); + int height = arrowIcon.getIconHeight(); + + arrowIcon.paintIcon(c, g, vr.width - width + defaultTextIconGap, + vr.y + 2); + } } - // paint text and user menu icon if it exists SwingUtilities.layoutCompoundLabel(c, fm, b.getText(), b.getIcon(), vertAlign, horAlign, vertTextPos, horTextPos, vr, ir, tr, defaultTextIconGap); - paintText(g, (JMenuItem) c, tr, b.getText()); - + paintText(g, (JMenuItem) c, tr, b.getText()); + // paint icon // FIXME: should paint different icon at different button state's. // i.e disabled icon when button is disabled.. etc. - - /* + + /* Icon i = b.getIcon(); if (i != null) { @@ -369,28 +547,35 @@ public class BasicMenuItemUI extends MenuItemUI i.paintIcon(c, g, x, y); } */ - + // paint accelerator String acceleratorText = ""; + if (((JMenuItem) c).getAccelerator() != null) { - acceleratorText = getAcceleratorText(((JMenuItem) c).getAccelerator()); - fm = g.getFontMetrics(acceleratorFont); - ar.width = fm.stringWidth(acceleratorText); - ar.x = br.width - ar.width; - vr.x = br.width - ar.width; - - SwingUtilities.layoutCompoundLabel(c, fm, acceleratorText, null, - vertAlign, horAlign, vertTextPos, - horTextPos, vr, ir, ar, - defaultTextIconGap); - - paintAccelerator(g, (JMenuItem) c, ar, acceleratorText); - - } - + acceleratorText = getAcceleratorText(((JMenuItem) c).getAccelerator()); + fm = g.getFontMetrics(acceleratorFont); + ar.width = fm.stringWidth(acceleratorText); + ar.x = br.width - ar.width; + vr.x = br.width - ar.width; + + SwingUtilities.layoutCompoundLabel(c, fm, acceleratorText, null, + vertAlign, horAlign, vertTextPos, + horTextPos, vr, ir, ar, + defaultTextIconGap); + + paintAccelerator(g, (JMenuItem) c, ar, acceleratorText); + } } + /** + * DOCUMENT ME! + * + * @param g DOCUMENT ME! + * @param menuItem DOCUMENT ME! + * @param textRect DOCUMENT ME! + * @param text DOCUMENT ME! + */ protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { @@ -400,14 +585,22 @@ public class BasicMenuItemUI extends MenuItemUI g.setColor(menuItem.getForeground()); BasicGraphicsUtils.drawString(g, text, 0, textRect.x, - textRect.y + fm.getAscent()); + textRect.y + fm.getAscent()); } + /** + * DOCUMENT ME! + * + * @param menuItem DOCUMENT ME! + */ protected void uninstallComponents(JMenuItem menuItem) { // TODO } + /** + * DOCUMENT ME! + */ protected void uninstallDefaults() { menuItem.setForeground(null); @@ -428,18 +621,30 @@ public class BasicMenuItemUI extends MenuItemUI acceleratorDelimiter = null; } + /** + * DOCUMENT ME! + */ protected void uninstallKeyboardActions() { // TODO } + /** + * DOCUMENT ME! + */ protected void uninstallListeners() { menuItem.removeMouseListener(mouseInputListener); menuItem.removeMenuDragMouseListener(menuDragMouseListener); menuItem.removeMenuKeyListener(menuKeyListener); + menuItem.removePropertyChangeListener(propertyChangeListener); } + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + */ public void uninstallUI(JComponent c) { uninstallListeners(); @@ -447,24 +652,35 @@ public class BasicMenuItemUI extends MenuItemUI menuItem = null; } + /** + * DOCUMENT ME! + * + * @param g DOCUMENT ME! + * @param c DOCUMENT ME! + */ public void update(Graphics g, JComponent c) { - // TODO + paint(g, c); } + /** + * DOCUMENT ME! + * + * @param accelerator DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ private String getAcceleratorText(KeyStroke accelerator) { - // convert keystroke into string format - String modifiersText = ""; int modifiers = accelerator.getModifiers(); char keyChar = accelerator.getKeyChar(); int keyCode = accelerator.getKeyCode(); if (modifiers != 0) - modifiersText = KeyEvent.getKeyModifiersText(modifiers) + - acceleratorDelimiter; + modifiersText = KeyEvent.getKeyModifiersText(modifiers) + + acceleratorDelimiter; if (keyCode == KeyEvent.VK_UNDEFINED) return modifiersText + keyChar; @@ -472,161 +688,233 @@ public class BasicMenuItemUI extends MenuItemUI return modifiersText + KeyEvent.getKeyText(keyCode); } + /** + * DOCUMENT ME! + * + * @param accelerator DOCUMENT ME! + * @param fm DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ private Rectangle getAcceleratorRect(KeyStroke accelerator, FontMetrics fm) - { + { int width = fm.stringWidth(getAcceleratorText(accelerator)); int height = fm.getHeight(); return new Rectangle(0, 0, width, height); } - private void paintAccelerator(Graphics g, JMenuItem menuItem, Rectangle acceleratorRect, - String acceleratorText) + /** + * DOCUMENT ME! + * + * @param g DOCUMENT ME! + * @param menuItem DOCUMENT ME! + * @param acceleratorRect DOCUMENT ME! + * @param acceleratorText DOCUMENT ME! + */ + private void paintAccelerator(Graphics g, JMenuItem menuItem, + Rectangle acceleratorRect, + String acceleratorText) { g.setFont(acceleratorFont); FontMetrics fm = g.getFontMetrics(acceleratorFont); g.setColor(acceleratorForeground); BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x, - acceleratorRect.y + fm.getAscent()); + acceleratorRect.y + fm.getAscent()); } + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.10 $ + */ protected class MouseInputHandler implements MouseInputListener { + /** + * Creates a new MouseInputHandler object. + */ protected MouseInputHandler() { } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void mouseClicked(MouseEvent e) { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void mouseDragged(MouseEvent e) { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void mouseEntered(MouseEvent e) { - if (e.getSource() instanceof AbstractButton) - { - AbstractButton button = (AbstractButton) e.getSource(); - ButtonModel model = button.getModel(); - - if (button.isRolloverEnabled()) - { - model.setRollover(true); - } - - if (model.isPressed() && - ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0)) - { - model.setArmed(true); - } - else - { - model.setArmed(false); - } - } + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void mouseExited(MouseEvent e) { - if (e.getSource() instanceof AbstractButton) - { - AbstractButton button = (AbstractButton) e.getSource(); - ButtonModel model = button.getModel(); - - if (button.isRolloverEnabled()) - { - model.setRollover(false); - } - - model.setArmed(false); - } + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void mouseMoved(MouseEvent e) { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void mousePressed(MouseEvent e) { - if (e.getSource() instanceof AbstractButton) - { - AbstractButton button = (AbstractButton) e.getSource(); - ButtonModel model = button.getModel(); - - if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) - { - // It is important that these transitions happen in this order. - model.setArmed(true); - model.setPressed(true); - } - } + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void mouseReleased(MouseEvent e) { - - if (e.getSource() instanceof AbstractButton) - { - AbstractButton button = (AbstractButton) e.getSource(); - ButtonModel model = button.getModel(); - - if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) - { - // It is important that these transitions happen in this order. - model.setPressed(false); - model.setArmed(false); - } - } + // FIXME: Should check if the mouse released while mouse cursor + // was indeed over the menu item. If this wasn't the case we probably + // should sent this event to MenuSelectionManager. + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + menuItem.doClick(0); } } + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.10 $ + */ protected class MenuDragMouseHandler implements MenuDragMouseListener { + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void menuDragMouseDragged(MenuDragMouseEvent e) { - // TODO } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void menuDragMouseEntered(MenuDragMouseEvent e) { - // TODO } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void menuDragMouseExited(MenuDragMouseEvent e) { - // TODO } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void menuDragMouseReleased(MenuDragMouseEvent e) { - // TODO } } + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.10 $ + */ protected class MenuKeyHandler implements MenuKeyListener { + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void menuKeyPressed(MenuKeyEvent e) { - // TODO } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void menuKeyReleased(MenuKeyEvent e) { - // TODO } + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ public void menuKeyTyped(MenuKeyEvent e) { - // TODO } } - protected class PropertyChangeHandler + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.10 $ + */ + protected class PropertyChangeHandler implements PropertyChangeListener { + /** + * DOCUMENT ME! + * + * @param evt DOCUMENT ME! + */ public void propertyChange(PropertyChangeEvent evt) { - // TODO } } } diff --git a/libjava/javax/swing/plaf/basic/BasicMenuUI.java b/libjava/javax/swing/plaf/basic/BasicMenuUI.java new file mode 100644 index 00000000000..406934e3adc --- /dev/null +++ b/libjava/javax/swing/plaf/basic/BasicMenuUI.java @@ -0,0 +1,357 @@ +/* BasicMenuUI.java + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuKeyEvent; +import javax.swing.event.MenuKeyListener; +import javax.swing.event.MenuListener; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.MenuItemUI; + + +/** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.3 $ + */ +public class BasicMenuUI extends BasicMenuItemUI +{ + protected ChangeListener changeListener; + protected MenuListener menuListener; + protected PropertyChangeListener propertyChangeListener; + + /** + * Creates a new BasicMenuUI object. + */ + public BasicMenuUI() + { + mouseInputListener = createMouseInputListener(menuItem); + menuListener = createMenuListener(menuItem); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected ChangeListener createChangeListener(JComponent c) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected MenuKeyListener createMenuKeyListener(JComponent c) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected MenuListener createMenuListener(JComponent c) + { + return new MenuHandler(); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected MouseInputListener createMouseInputListener(JComponent c) + { + return new MouseInputHandler(); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected PropertyChangeListener createPropertyChangeListener(JComponent c) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param x DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicMenuUI(); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension getMaximumSize(JComponent c) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected String getPropertyPrefix() + { + return null; + } + + /** + * DOCUMENT ME! + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + menuItem.setBackground(defaults.getColor("Menu.background")); + menuItem.setBorder(defaults.getBorder("Menu.border")); + menuItem.setFont(defaults.getFont("Menu.font")); + menuItem.setForeground(defaults.getColor("Menu.foreground")); + menuItem.setMargin(defaults.getInsets("Menu.margin")); + acceleratorFont = defaults.getFont("Menu.acceleratorFont"); + acceleratorForeground = defaults.getColor("Menu.acceleratorForeground"); + acceleratorSelectionForeground = defaults.getColor("Menu.acceleratorSelectionForeground"); + arrowIcon = defaults.getIcon("Menu.arrowIcon"); + oldBorderPainted = defaults.getBoolean("Menu.borderPainted"); + } + + /** + * DOCUMENT ME! + */ + protected void installKeyboardActions() + { + } + + /** + * DOCUMENT ME! + */ + protected void installListeners() + { + ((JMenu) menuItem).addMouseListener(mouseInputListener); + ((JMenu) menuItem).addMenuListener(menuListener); + } + + /** + * DOCUMENT ME! + * + * @param menu DOCUMENT ME! + */ + protected void setupPostTimer(JMenu menu) + { + } + + /** + * DOCUMENT ME! + */ + protected void uninstallDefaults() + { + menuItem.setBackground(null); + menuItem.setBorder(null); + menuItem.setFont(null); + menuItem.setForeground(null); + menuItem.setMargin(null); + acceleratorFont = null; + acceleratorForeground = null; + acceleratorSelectionForeground = null; + arrowIcon = null; + } + + /** + * DOCUMENT ME! + */ + protected void uninstallKeyboardActions() + { + } + + /** + * DOCUMENT ME! + */ + protected void uninstallListeners() + { + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.3 $ + */ + protected class MouseInputHandler implements MouseInputListener + { + protected MouseInputHandler() + { + } + + public void mouseClicked(MouseEvent e) + { + } + + public void mouseDragged(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + public void mouseEntered(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.setSelectedPath(manager.getPath((Component) e.getSource())); + manager.processMouseEvent(e); + + JMenu subMenu = (JMenu) menuItem; + + int x = 0; + int y = 0; + + // location of the popup menu is relative to the invoker + if (subMenu.isTopLevelMenu()) + { + JMenuBar mb = (JMenuBar) subMenu.getParent(); + + // Subtract menuBar's insets.bottom and popupMenu's insets.top, + // s.t. the space between menu bar and its popup menu is equal to + // menuBar's margin. By default menuBar's margin is Insets(0,0,0,0). + y = subMenu.getHeight() - mb.getInsets().bottom + - subMenu.getPopupMenu().getInsets().top + mb.getMargin().bottom; + } + else + x = subMenu.getWidth(); + + subMenu.getPopupMenu().show(subMenu, x, y); + } + + public void mouseExited(MouseEvent e) + { + } + + public void mouseMoved(MouseEvent e) + { + } + + public void mousePressed(MouseEvent e) + { + } + + public void mouseReleased(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + } + + protected class MenuHandler implements MenuListener + { + public void menuCanceled(MenuEvent e) + { + } + + public void menuDeselected(MenuEvent e) + { + } + + public void menuSelected(MenuEvent e) + { + } + } +} diff --git a/libjava/javax/swing/plaf/basic/BasicOptionPaneUI.java b/libjava/javax/swing/plaf/basic/BasicOptionPaneUI.java index 466f4a5c285..8d65ee0928d 100644 --- a/libjava/javax/swing/plaf/basic/BasicOptionPaneUI.java +++ b/libjava/javax/swing/plaf/basic/BasicOptionPaneUI.java @@ -1,5 +1,5 @@ /* BasicOptionPaneUI.java - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -35,124 +35,1275 @@ this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ - package javax.swing.plaf.basic; +import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Component; +import java.awt.Container; import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; import java.awt.LayoutManager; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.Icon; import javax.swing.JButton; +import javax.swing.JComboBox; import javax.swing.JComponent; +import javax.swing.JDialog; import javax.swing.JLabel; +import javax.swing.JList; import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.IconUIResource; import javax.swing.plaf.OptionPaneUI; + +/** + * This class is the UI delegate for JOptionPane in the Basic Look and Feel. + */ public class BasicOptionPaneUI extends OptionPaneUI { - JOptionPane pane; + /** + * This is a helper class that listens to the buttons located at the bottom + * of the JOptionPane. + */ + protected class ButtonActionListener implements ActionListener + { + /** The index of the option this button represents. */ + protected int buttonIndex; + + /** + * Creates a new ButtonActionListener object with the given buttonIndex. + * + * @param buttonIndex The index of the option this button represents. + */ + public ButtonActionListener(int buttonIndex) + { + this.buttonIndex = buttonIndex; + } + + /** + * This method is called when one of the option buttons are pressed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + Object value = new Integer(JOptionPane.CLOSED_OPTION); + Object[] options = optionPane.getOptions(); + if (options != null) + value = options[buttonIndex]; + else + { + String text = ((JButton) e.getSource()).getText(); + if (text.equals(OK_STRING)) + value = new Integer(JOptionPane.OK_OPTION); + if (text.equals(CANCEL_STRING)) + value = new Integer(JOptionPane.CANCEL_OPTION); + if (text.equals(YES_STRING)) + value = new Integer(JOptionPane.YES_OPTION); + if (text.equals(NO_STRING)) + value = new Integer(JOptionPane.NO_OPTION); + } + optionPane.setValue(value); + resetInputValue(); + + Window owner = SwingUtilities.windowForComponent(optionPane); + + if (owner instanceof JDialog) + ((JDialog) owner).dispose(); + } + } + + /** + * This helper layout manager is responsible for the layout of the button + * area. The button area is the panel that holds the buttons which + * represent the options. + */ + protected class ButtonAreaLayout implements LayoutManager + { + /** Whether this layout will center the buttons. */ + protected boolean centersChildren = true; + + /** The space between the buttons. */ + protected int padding; + + /** Whether the buttons will share the same widths. */ + protected boolean syncAllWidths; - BasicOptionPaneUI() + /** The width of the widest button. */ + private transient int widthOfWidestButton; + + /** The height of the tallest button. */ + private transient int tallestButton; + + /** + * Creates a new ButtonAreaLayout object with the given sync widths + * property and padding. + * + * @param syncAllWidths Whether the buttons will share the same widths. + * @param padding The padding between the buttons. + */ + public ButtonAreaLayout(boolean syncAllWidths, int padding) { + this.syncAllWidths = syncAllWidths; + this.padding = padding; } - public static ComponentUI createUI(JComponent x) + /** + * This method is called when a component is added to the container. + * + * @param string The constraints string. + * @param comp The component added. + */ + public void addLayoutComponent(String string, Component comp) { - return new BasicOptionPaneUI(); + // Do nothing. } - public void installUI(JComponent c) + /** + * This method returns whether the children will be centered. + * + * @return Whether the children will be centered. + */ + public boolean getCentersChildren() { - super.installUI(c); - pane = (JOptionPane)c; + return centersChildren; + } - System.out.println(" -------------: " + pane); + /** + * This method returns the amount of space between components. + * + * @return The amount of space between components. + */ + public int getPadding() + { + return padding; + } - JLabel message = null; - JButton ok_button = new JButton("Ok"); + /** + * This method returns whether all components will share widths (set to + * largest width). + * + * @return Whether all components will share widths. + */ + public boolean getSyncAllWidths() + { + return syncAllWidths; + } - ok_button.addActionListener(new ActionListener() + /** + * This method lays out the given container. + * + * @param container The container to lay out. + */ + public void layoutContainer(Container container) + { + Component[] buttonList = container.getComponents(); + int x = container.getInsets().left; + if (getCentersChildren()) + x += (int) ((double) (container.getSize().width) / 2 + - (double) (buttonRowLength(container)) / 2); + for (int i = 0; i < buttonList.length; i++) + { + Dimension dims = buttonList[i].getPreferredSize(); + if (getSizeButtonsToSameWidth()) { - public void actionPerformed(ActionEvent a) - { - System.out.println("ACTION ---> " + a); - // pane.dialog.dispose(); - - if (pane.dialog.isModal()) - { - System.out.println("modal dialog !!"); - pane.dialog.setModal(false); - } - pane.dialog.setVisible(false); - } - }); - - Object[] options = null; - if (options != null) + buttonList[i].setBounds(x, 0, widthOfWidestButton, dims.height); + x += widthOfWidestButton + getPadding(); + } + else { - for (int i=0; i<options.length; i++) - { - Object o = options[i]; - if (o != null) - { - if (o instanceof String) - { - String s = (String) o; - JLabel m = new JLabel(s); - pane.add(m); - } - else if (o instanceof Component) - { - Component com = (Component) o; - pane.add(com); - } - else - { - System.out.println("UNRECOGNIZED ARG: " + o); - } - } - } + buttonList[i].setBounds(x, 0, dims.width, dims.height); + x += dims.width + getPadding(); } + } + } + + /** + * This method returns the width of the given container taking into + * consideration the padding and syncAllWidths. + * + * @param c The container to calculate width for. + * + * @return The width of the given container. + */ + private int buttonRowLength(Container c) + { + Component[] buttonList = c.getComponents(); + + int buttonLength = 0; + int widest = 0; + int tallest = 0; + + for (int i = 0; i < buttonList.length; i++) + { + Dimension dims = buttonList[i].getPreferredSize(); + buttonLength += dims.width + getPadding(); + widest = Math.max(widest, dims.width); + tallest = Math.max(tallest, dims.height); + } + + widthOfWidestButton = widest; + tallestButton = tallest; + + int width; + if (getSyncAllWidths()) + width = widest * buttonList.length + + getPadding() * (buttonList.length - 1); + else + width = buttonLength; - pane.add(message); - pane.add(ok_button); + Insets insets = c.getInsets(); + width += insets.left + insets.right; + + return width; } - Dimension getMinimumOptionPaneSize() + /** + * This method returns the minimum layout size for the given container. + * + * @param c The container to measure. + * + * @return The minimum layout size. + */ + public Dimension minimumLayoutSize(Container c) { - return new Dimension(300,100); + return preferredLayoutSize(c); } - public Dimension getPreferredSize(JComponent c) + /** + * This method returns the preferred size of the given container. + * + * @param c The container to measure. + * + * @return The preferred size. + */ + public Dimension preferredLayoutSize(Container c) { - if (c == null) - return getMinimumOptionPaneSize(); + int w = buttonRowLength(c); - if (c != pane) - return null; + return new Dimension(w, tallestButton); + } - LayoutManager l = c.getLayout(); - if (l == null) - return getMinimumOptionPaneSize(); + /** + * This method removes the given component from the layout manager's + * knowledge. + * + * @param c The component to remove. + */ + public void removeLayoutComponent(Component c) + { + // Do nothing. + } - Dimension d1 = l.preferredLayoutSize(c); - Dimension d2 = getMinimumOptionPaneSize(); - - d1.width = Math.max(d1.width, d2.width); - d1.height = Math.max(d1.height, d2.height); + /** + * This method sets whether the children will be centered. + * + * @param newValue Whether the children will be centered. + */ + public void setCentersChildren(boolean newValue) + { + centersChildren = newValue; + optionPane.invalidate(); + } - return d2; + /** + * This method sets the amount of space between each component. + * + * @param newPadding The padding between components. + */ + public void setPadding(int newPadding) + { + padding = newPadding; + optionPane.invalidate(); } - public void selectInitialValue(JOptionPane op) + /** + * This method sets whether the widths will be synced. + * + * @param newValue Whether the widths will be synced. + */ + public void setSyncAllWidths(boolean newValue) + { + syncAllWidths = newValue; + optionPane.invalidate(); + } + } + + /** + * This helper class handles property change events from the JOptionPane. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called when one of the properties of the JOptionPane + * changes. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JOptionPane.ICON_PROPERTY) + || e.getPropertyName().equals(JOptionPane.MESSAGE_TYPE_PROPERTY)) + addIcon(messageAreaContainer); + else if (e.getPropertyName().equals(JOptionPane.INITIAL_SELECTION_VALUE_PROPERTY)) + resetSelectedValue(); + else if (e.getPropertyName().equals(JOptionPane.INITIAL_VALUE_PROPERTY) + || e.getPropertyName().equals(JOptionPane.OPTIONS_PROPERTY) + || e.getPropertyName().equals(JOptionPane.OPTION_TYPE_PROPERTY)) + { + Container newButtons = createButtonArea(); + optionPane.remove(buttonContainer); + optionPane.add(newButtons); + buttonContainer = newButtons; + } + + else if (e.getPropertyName().equals(JOptionPane.MESSAGE_PROPERTY) + || e.getPropertyName().equals(JOptionPane.WANTS_INPUT_PROPERTY) + || e.getPropertyName().equals(JOptionPane.SELECTION_VALUES_PROPERTY)) + { + optionPane.removeAll(); + messageAreaContainer = createMessageArea(); + optionPane.add(messageAreaContainer); + optionPane.add(buttonContainer); + } + optionPane.invalidate(); + optionPane.repaint(); + } + } + + /** Whether the JOptionPane contains custom components. */ + protected boolean hasCustomComponents = false; + + // The initialFocusComponent seems to always be set to a button (even if + // I try to set initialSelectionValue). This is different from what the + // javadocs state (which should switch this reference to the input component + // if one is present since that is what's going to get focus). + + /** + * The button that will receive focus based on initialValue when no input + * component is present. If an input component is present, then the input + * component will receive focus instead. + */ + protected Component initialFocusComponent; + + /** The component that receives input when the JOptionPane needs it. */ + protected JComponent inputComponent; + + /** The minimum height of the JOptionPane. */ + public static int minimumHeight; + + /** The minimum width of the JOptionPane. */ + public static int minimumWidth; + + /** The minimum dimensions of the JOptionPane. */ + protected Dimension minimumSize; + + /** The propertyChangeListener for the JOptionPane. */ + protected PropertyChangeListener propertyChangeListener; + + /** The JOptionPane this UI delegate is used for. */ + protected JOptionPane optionPane; + + /** The size of the icons. */ + private static int iconSize = 36; + + /** The foreground color for the message area. */ + private transient Color messageForeground; + + /** The border around the message area. */ + private transient Border messageBorder; + + /** The border around the button area. */ + private transient Border buttonBorder; + + /** The string used to describe OK buttons. */ + private static String OK_STRING = "OK"; + + /** The string used to describe Yes buttons. */ + private static String YES_STRING = "Yes"; + + /** The string used to describe No buttons. */ + private static String NO_STRING = "No"; + + /** The string used to describe Cancel buttons. */ + private static String CANCEL_STRING = "Cancel"; + + /** The container for the message area. */ + private transient Container messageAreaContainer; + + /** The container for the buttons. */ + private transient Container buttonContainer; + + /** + * A helper class that implements Icon. This is used temporarily until + * ImageIcons are fixed. + */ + private static class messageIcon implements Icon + { + /** + * This method returns the width of the icon. + * + * @return The width of the icon. + */ + public int getIconWidth() + { + return iconSize; + } + + /** + * This method returns the height of the icon. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return iconSize; + } + + /** + * This method paints the icon as a part of the given component using the + * given graphics and the given x and y position. + * + * @param c The component that owns this icon. + * @param g The Graphics object to paint with. + * @param x The x coordinate. + * @param y The y coordinate. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + } + } + + /** The icon displayed for ERROR_MESSAGE. */ + private static messageIcon errorIcon = new messageIcon() + { + public void paintIcon(Component c, Graphics g, int x, int y) + { + Polygon oct = new Polygon(new int[] { 0, 0, 9, 27, 36, 36, 27, 9 }, + new int[] { 9, 27, 36, 36, 27, 9, 0, 0 }, 8); + g.translate(x, y); + + Color saved = g.getColor(); + g.setColor(Color.RED); + + g.fillPolygon(oct); + + g.setColor(Color.BLACK); + g.drawRect(13, 16, 10, 4); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** The icon displayed for INFORMATION_MESSAGE. */ + private static messageIcon infoIcon = new messageIcon() + { + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.translate(x, y); + Color saved = g.getColor(); + + // Should be purple. + g.setColor(Color.RED); + + g.fillOval(0, 0, iconSize, iconSize); + + g.setColor(Color.BLACK); + g.drawOval(16, 6, 4, 4); + + Polygon bottomI = new Polygon(new int[] { 15, 15, 13, 13, 23, 23, 21, 21 }, + new int[] { 12, 28, 28, 30, 30, 28, 28, 12 }, + 8); + g.drawPolygon(bottomI); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** The icon displayed for WARNING_MESSAGE. */ + private static messageIcon warningIcon = new messageIcon() + { + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.translate(x, y); + Color saved = g.getColor(); + g.setColor(Color.YELLOW); + + Polygon triangle = new Polygon(new int[] { 0, 18, 36 }, + new int[] { 36, 0, 36 }, 3); + g.fillPolygon(triangle); + + g.setColor(Color.BLACK); + + Polygon excl = new Polygon(new int[] { 15, 16, 20, 21 }, + new int[] { 8, 26, 26, 8 }, 4); + g.drawPolygon(excl); + g.drawOval(16, 30, 4, 4); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** The icon displayed for MESSAGE_ICON. */ + private static messageIcon questionIcon = new messageIcon() + { + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.translate(x, y); + Color saved = g.getColor(); + g.setColor(Color.GREEN); + + g.fillRect(0, 0, iconSize, iconSize); + + g.setColor(Color.BLACK); + + g.drawOval(11, 2, 16, 16); + g.drawOval(14, 5, 10, 10); + + g.setColor(Color.GREEN); + g.fillRect(0, 10, iconSize, iconSize - 10); + + g.setColor(Color.BLACK); + + g.drawLine(11, 10, 14, 10); + + g.drawLine(24, 10, 17, 22); + g.drawLine(27, 10, 20, 22); + g.drawLine(17, 22, 20, 22); + + g.drawOval(17, 25, 3, 3); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + // FIXME: Uncomment when the ImageIcons are fixed. + + /* IconUIResource warningIcon, questionIcon, infoIcon, errorIcon;*/ + + /** + * Creates a new BasicOptionPaneUI object. + */ + public BasicOptionPaneUI() + { + } + + /** + * This method is messaged to add the buttons to the given container. + * + * @param container The container to add components to. + * @param buttons The buttons to add. (If it is an instance of component, + * the Object is added directly. If it is an instance of Icon, it is + * packed into a label and added. For all other cases, the string + * representation of the Object is retreived and packed into a + * label.) + * @param initialIndex The index of the component that is the initialValue. + */ + protected void addButtonComponents(Container container, Object[] buttons, + int initialIndex) + { + if (buttons == null) + return; + for (int i = 0; i < buttons.length; i++) + { + if (buttons[i] != null) + { + Component toAdd; + if (buttons[i] instanceof Component) + toAdd = (Component) buttons[i]; + else + { + if (buttons[i] instanceof Icon) + toAdd = new JButton((Icon) buttons[i]); + else + toAdd = new JButton(buttons[i].toString()); + ((JButton) toAdd).addActionListener(createButtonActionListener(i)); + hasCustomComponents = true; + } + + if (i == initialIndex) + initialFocusComponent = toAdd; + container.add(toAdd); + } + } + selectInitialValue(optionPane); + } + + /** + * This method adds the appropriate icon the given container. + * + * @param top The container to add an icon to. + */ + protected void addIcon(Container top) + { + JLabel iconLabel = null; + Icon icon = getIcon(); + if (icon != null) + { + iconLabel = new JLabel(icon); + top.add(iconLabel, BorderLayout.WEST); + } + } + + /** + * A helper method that returns an instance of GridBagConstraints to be used + * for creating the message area. + * + * @return An instance of GridBagConstraints. + */ + private static GridBagConstraints createConstraints() + { + GridBagConstraints constraints = new GridBagConstraints(); + constraints.gridx = GridBagConstraints.REMAINDER; + constraints.gridy = GridBagConstraints.REMAINDER; + constraints.gridwidth = 0; + constraints.anchor = GridBagConstraints.LINE_START; + constraints.fill = GridBagConstraints.NONE; + constraints.insets = new Insets(0, 0, 3, 0); + + return constraints; + } + + /** + * This method creates the proper object (if necessary) to represent msg. + * (If msg is an instance of Component, it will add it directly. If it is + * an icon, then it will pack it in a label and add it. Otherwise, it gets + * treated as a string. If the string is longer than maxll, a box is + * created and the burstStringInto is called with the box as the container. + * The box is then added to the given container. Otherwise, the string is + * packed in a label and placed in the given container.) This method is + * also used for adding the inputComponent to the container. + * + * @param container The container to add to. + * @param cons The constraints when adding. + * @param msg The message to add. + * @param maxll The max line length. + * @param internallyCreated Whether the msg is internally created. + */ + protected void addMessageComponents(Container container, + GridBagConstraints cons, Object msg, + int maxll, boolean internallyCreated) + { + if (msg == null) + return; + hasCustomComponents = internallyCreated; + if (msg instanceof Object[]) + { + Object[] arr = (Object[]) msg; + for (int i = 0; i < arr.length; i++) + addMessageComponents(container, cons, arr[i], maxll, + internallyCreated); + return; + } + else if (msg instanceof Component) + { + container.add((Component) msg, cons); + cons.gridy++; + } + else if (msg instanceof Icon) + { + container.add(new JLabel((Icon) msg), cons); + cons.gridy++; + } + else + { + // Undocumented behaviour. + // if msg.toString().length greater than maxll + // it will create a box and burst the string. + // otherwise, it will just create a label and re-call + // this method with the label o.O + if (msg.toString().length() > maxll) + { + Box tmp = new Box(BoxLayout.Y_AXIS); + burstStringInto(tmp, msg.toString(), maxll); + addMessageComponents(container, cons, tmp, maxll, true); + } + else + addMessageComponents(container, cons, new JLabel(msg.toString()), + maxll, true); + } + } + + /** + * This method creates instances of d (recursively if necessary based on + * maxll) and adds to c. + * + * @param c The container to add to. + * @param d The string to burst. + * @param maxll The max line length. + */ + protected void burstStringInto(Container c, String d, int maxll) { - throw new Error ("Not implemented"); + // FIXME: Verify that this is the correct behaviour. + // One interpretation of the spec is that this method + // should recursively call itself to create (and add) + // JLabels to the container if the length of the String d + // is greater than maxll. + // but in practice, even with a really long string, this is + // all that happens. + if (d == null || c == null) + return; + JLabel label = new JLabel(d); + c.add(label); } + /** + * This method returns true if the given JOptionPane contains custom + * components. + * + * @param op The JOptionPane to check. + * + * @return True if the JOptionPane contains custom components. + */ public boolean containsCustomComponents(JOptionPane op) { - throw new Error ("Not implemented"); + return hasCustomComponents; + } + + /** + * This method creates a button action listener for the given button index. + * + * @param buttonIndex The index of the button in components. + * + * @return A new ButtonActionListener. + */ + protected ActionListener createButtonActionListener(int buttonIndex) + { + return new ButtonActionListener(buttonIndex); + } + + /** + * This method creates the button area. + * + * @return A new Button Area. + */ + protected Container createButtonArea() + { + JPanel buttonPanel = new JPanel(); + + buttonPanel.setLayout(createLayoutManager()); + addButtonComponents(buttonPanel, getButtons(), getInitialValueIndex()); + + return buttonPanel; + } + + /** + * This method creates a new LayoutManager for the button area. + * + * @return A new LayoutManager for the button area. + */ + protected LayoutManager createLayoutManager() + { + return new ButtonAreaLayout(getSizeButtonsToSameWidth(), 6); + } + + /** + * This method creates the message area. + * + * @return A new message area. + */ + protected Container createMessageArea() + { + JPanel messageArea = new JPanel(); + messageArea.setLayout(new BorderLayout()); + addIcon(messageArea); + + JPanel rightSide = new JPanel() + { + public Dimension getPreferredSize() + { + int w = Math.max(optionPane.getSize().width, + minimumWidth); + Insets i = optionPane.getInsets(); + Dimension orig = super.getPreferredSize(); + Dimension value = new Dimension(w - i.left - i.right - iconSize, + orig.height); + return value; + } + }; + rightSide.setLayout(new GridBagLayout()); + GridBagConstraints con = createConstraints(); + + addMessageComponents(rightSide, con, getMessage(), + getMaxCharactersPerLineCount(), false); + + if (optionPane.getWantsInput()) + { + Object[] selection = optionPane.getSelectionValues(); + + if (selection == null) + inputComponent = new JTextField(); + else if (selection.length < 20) + inputComponent = new JComboBox(selection); + else + inputComponent = new JList(selection); + if (inputComponent != null) + { + addMessageComponents(rightSide, con, inputComponent, + getMaxCharactersPerLineCount(), true); + resetSelectedValue(); + selectInitialValue(optionPane); + } + } + + messageArea.add(rightSide, BorderLayout.EAST); + + return messageArea; + } + + /** + * This method creates a new PropertyChangeListener for listening to the + * JOptionPane. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * This method creates a Container that will separate the message and button + * areas. + * + * @return A Container that will separate the message and button areas. + */ + protected Container createSeparator() + { + return null; + } + + /** + * This method creates a new BasicOptionPaneUI for the given component. + * + * @param x The component to create a UI for. + * + * @return A new BasicOptionPaneUI. + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicOptionPaneUI(); + } + + /** + * This method returns the buttons for the JOptionPane. If no options are + * set, a set of options will be created based upon the optionType. + * + * @return The buttons that will be added. + */ + protected Object[] getButtons() + { + if (optionPane.getOptions() != null) + return optionPane.getOptions(); + switch (optionPane.getOptionType()) + { + case JOptionPane.YES_NO_OPTION: + return new Object[] { YES_STRING, NO_STRING }; + case JOptionPane.YES_NO_CANCEL_OPTION: + return new Object[] { YES_STRING, NO_STRING, CANCEL_STRING }; + case JOptionPane.OK_CANCEL_OPTION: + case JOptionPane.DEFAULT_OPTION: + return new Object[] { OK_STRING, CANCEL_STRING }; + } + return null; + } + + /** + * This method will return the icon the user has set or the icon that will + * be used based on message type. + * + * @return The icon to use in the JOptionPane. + */ + protected Icon getIcon() + { + if (optionPane.getIcon() != null) + return optionPane.getIcon(); + else + return getIconForType(optionPane.getMessageType()); + } + + /** + * This method returns the icon for the given messageType. + * + * @param messageType The type of message. + * + * @return The icon for the given messageType. + */ + protected Icon getIconForType(int messageType) + { + Icon tmp = null; + switch (messageType) + { + case JOptionPane.ERROR_MESSAGE: + tmp = errorIcon; + break; + case JOptionPane.INFORMATION_MESSAGE: + tmp = infoIcon; + break; + case JOptionPane.WARNING_MESSAGE: + tmp = warningIcon; + break; + case JOptionPane.QUESTION_MESSAGE: + tmp = questionIcon; + break; + } + return new IconUIResource(tmp); + } + + /** + * This method returns the index of the initialValue in the options array. + * + * @return The index of the initalValue. + */ + protected int getInitialValueIndex() + { + Object[] buttons = getButtons(); + + if (buttons == null) + return -1; + + Object select = optionPane.getInitialValue(); + + for (int i = 0; i < buttons.length; i++) + { + if (select == buttons[i]) + return i; + } + return 0; + } + + /** + * This method returns the maximum number of characters that should be + * placed on a line. + * + * @return The maximum number of characteres that should be placed on a + * line. + */ + protected int getMaxCharactersPerLineCount() + { + return optionPane.getMaxCharactersPerLineCount(); + } + + /** + * This method returns the maximum size. + * + * @param c The JComponent to measure. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the message of the JOptionPane. + * + * @return The message. + */ + protected Object getMessage() + { + return optionPane.getMessage(); + } + + /** + * This method returns the minimum size of the JOptionPane. + * + * @return The minimum size. + */ + public Dimension getMinimumOptionPaneSize() + { + return minimumSize; + } + + /** + * This method returns the minimum size. + * + * @param c The JComponent to measure. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the preferred size of the JOptionPane. The preferred + * size is the maximum of the size desired by the layout and the minimum + * size. + * + * @param c The JComponent to measure. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + Dimension d = optionPane.getLayout().preferredLayoutSize(optionPane); + Dimension d2 = getMinimumOptionPaneSize(); + + int w = Math.max(d.width, d2.width); + int h = Math.max(d.height, d2.height); + return new Dimension(w, h); + } + + /** + * This method returns whether all buttons should have the same width. + * + * @return Whether all buttons should have the same width. + */ + protected boolean getSizeButtonsToSameWidth() + { + return true; + } + + /** + * This method installs components for the JOptionPane. + */ + protected void installComponents() + { + // reset it. + hasCustomComponents = false; + Container msg = createMessageArea(); + if (msg != null) + { + ((JComponent) msg).setBorder(messageBorder); + msg.setForeground(messageForeground); + messageAreaContainer = msg; + optionPane.add(msg); + } + + Container sep = createSeparator(); + if (sep != null) + optionPane.add(sep); + + Container button = createButtonArea(); + if (button != null) + { + ((JComponent) button).setBorder(buttonBorder); + buttonContainer = button; + optionPane.add(button); + } + + optionPane.invalidate(); + } + + /** + * This method installs defaults for the JOptionPane. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + optionPane.setFont(defaults.getFont("OptionPane.font")); + optionPane.setBackground(defaults.getColor("OptionPane.background")); + optionPane.setForeground(defaults.getColor("OptionPane.foreground")); + optionPane.setBorder(defaults.getBorder("OptionPane.border")); + + messageBorder = defaults.getBorder("OptionPane.messageAreaBorder"); + messageForeground = defaults.getColor("OptionPane.messageForeground"); + buttonBorder = defaults.getBorder("OptionPane.buttonAreaBorder"); + + minimumSize = defaults.getDimension("OptionPane.minimumSize"); + minimumWidth = minimumSize.width; + minimumHeight = minimumSize.height; + + // FIXME: Image icons don't seem to work properly right now. + // Once they do, replace the synthetic icons with these ones. + + /* + warningIcon = (IconUIResource) defaults.getIcon("OptionPane.warningIcon"); + infoIcon = (IconUIResource) defaults.getIcon("OptionPane.informationIcon"); + errorIcon = (IconUIResource) defaults.getIcon("OptionPane.errorIcon"); + questionIcon = (IconUIResource) defaults.getIcon("OptionPane.questionIcon"); + */ + } + + /** + * This method installs keyboard actions for the JOptionpane. + */ + protected void installKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method installs listeners for the JOptionPane. + */ + protected void installListeners() + { + propertyChangeListener = createPropertyChangeListener(); + + optionPane.addPropertyChangeListener(propertyChangeListener); + } + + /** + * This method installs the UI for the JOptionPane. + * + * @param c The JComponent to install the UI for. + */ + public void installUI(JComponent c) + { + if (c instanceof JOptionPane) + { + optionPane = (JOptionPane) c; + + installDefaults(); + installComponents(); + installListeners(); + installKeyboardActions(); + } + } + + /** + * Changes the inputValue property in the JOptionPane based on the current + * value of the inputComponent. + */ + protected void resetInputValue() + { + if (optionPane.getWantsInput() && inputComponent != null) + { + Object output = null; + if (inputComponent instanceof JTextField) + output = ((JTextField) inputComponent).getText(); + else if (inputComponent instanceof JComboBox) + output = ((JComboBox) inputComponent).getSelectedItem(); + else if (inputComponent instanceof JList) + output = ((JList) inputComponent).getSelectedValue(); + + if (output != null) + optionPane.setInputValue(output); + } + } + + /** + * This method requests focus to the inputComponent (if one is present) and + * the initialFocusComponent otherwise. + * + * @param op The JOptionPane. + */ + public void selectInitialValue(JOptionPane op) + { + if (inputComponent != null) + { + inputComponent.requestFocus(); + return; + } + if (initialFocusComponent != null) + initialFocusComponent.requestFocus(); + } + + /** + * This method resets the value in the inputComponent to the + * initialSelectionValue property. + */ + private void resetSelectedValue() + { + if (inputComponent != null) + { + Object init = optionPane.getInitialSelectionValue(); + if (init == null) + return; + if (inputComponent instanceof JTextField) + ((JTextField) inputComponent).setText((String) init); + else if (inputComponent instanceof JComboBox) + ((JComboBox) inputComponent).setSelectedItem(init); + else if (inputComponent instanceof JList) + { + // ((JList) inputComponent).setSelectedValue(init, true); + } + } + } + + /** + * This method uninstalls all the components in the JOptionPane. + */ + protected void uninstallComponents() + { + optionPane.removeAll(); + buttonContainer = null; + messageAreaContainer = null; + } + + /** + * This method uninstalls the defaults for the JOptionPane. + */ + protected void uninstallDefaults() + { + optionPane.setFont(null); + optionPane.setForeground(null); + optionPane.setBackground(null); + + minimumSize = null; + + messageBorder = null; + buttonBorder = null; + messageForeground = null; + + // FIXME: ImageIcons don't seem to work properly + + /* + warningIcon = null; + errorIcon = null; + questionIcon = null; + infoIcon = null; + */ + } + + /** + * This method uninstalls keyboard actions for the JOptionPane. + */ + protected void uninstallKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method uninstalls listeners for the JOptionPane. + */ + protected void uninstallListeners() + { + optionPane.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + } + + /** + * This method uninstalls the UI for the given JComponent. + * + * @param c The JComponent to uninstall for. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + + optionPane = null; } } diff --git a/libjava/javax/swing/plaf/basic/BasicPopupMenuUI.java b/libjava/javax/swing/plaf/basic/BasicPopupMenuUI.java new file mode 100644 index 00000000000..d7ced7654ae --- /dev/null +++ b/libjava/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -0,0 +1,362 @@ +/* BasicPopupMenuUI.java + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +import java.awt.AWTKeyStroke; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.Stroke; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.EventListener; +import javax.swing.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.Icon; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.KeyStroke; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuKeyEvent; +import javax.swing.event.MenuKeyListener; +import javax.swing.event.MouseInputListener; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.MenuItemUI; +import javax.swing.plaf.PopupMenuUI; + + +/** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.1 $ + */ +public class BasicPopupMenuUI extends PopupMenuUI +{ + protected JPopupMenu popupMenu; + private static transient MouseInputListener mouseInputListener; + private transient PopupMenuListener popupMenuListener; + + /** + * Creates a new BasicPopupMenuUI object. + */ + public BasicPopupMenuUI() + { + popupMenuListener = new PopupMenuHandler(); + mouseInputListener = new MouseInputHandler(); + } + + /** + * DOCUMENT ME! + * + * @param x DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicPopupMenuUI(); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + */ + public void installUI(JComponent c) + { + super.installUI(c); + popupMenu = (JPopupMenu) c; + popupMenu.setLayout(new GridBagLayout()); + popupMenu.setBorderPainted(true); + popupMenu.setDefaultLightWeightPopupEnabled(true); + + installDefaults(); + installListeners(); + } + + /** + * DOCUMENT ME! + */ + public void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + popupMenu.setBackground(defaults.getColor("PopupMenu.background")); + popupMenu.setBorder(defaults.getBorder("PopupMenu.border")); + popupMenu.setFont(defaults.getFont("PopupMenu.font")); + popupMenu.setForeground(defaults.getColor("PopupMenu.foreground")); + } + + /** + * DOCUMENT ME! + */ + protected void installListeners() + { + popupMenu.addMouseListener(mouseInputListener); + popupMenu.addMouseMotionListener(mouseInputListener); + popupMenu.addPopupMenuListener(popupMenuListener); + } + + /** + * DOCUMENT ME! + */ + protected void installKeyboardActions() + { + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + */ + public void uninstallUI(JComponent c) + { + uninstallListeners(); + uninstallDefaults(); + popupMenu = null; + } + + /** + * DOCUMENT ME! + */ + protected void uninstallDefaults() + { + popupMenu.setBackground(null); + popupMenu.setBorder(null); + popupMenu.setFont(null); + popupMenu.setForeground(null); + } + + /** + * DOCUMENT ME! + */ + protected void uninstallListeners() + { + } + + /** + * DOCUMENT ME! + */ + protected void uninstallKeyboardActions() + { + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension getMinimumSize(JComponent c) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension getPreferredSize(JComponent c) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension getMaximumSize(JComponent c) + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean isPopupTrigger(MouseEvent e) + { + return false; + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.1 $ + */ + protected class PopupMenuHandler implements PopupMenuListener + { + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ + public void popupMenuCanceled(PopupMenuEvent event) + { + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ + public void popupMenuWillBecomeInvisible(PopupMenuEvent event) + { + } + + /** + * DOCUMENT ME! + * + * @param event DOCUMENT ME! + */ + public void popupMenuWillBecomeVisible(PopupMenuEvent event) + { + } + } + + /** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.1 $ + */ + protected class MouseInputHandler implements MouseInputListener + { + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void mouseClicked(MouseEvent e) + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void mouseDragged(MouseEvent e) + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void mouseEntered(MouseEvent e) + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void mouseExited(MouseEvent e) + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void mouseMoved(MouseEvent e) + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void mousePressed(MouseEvent e) + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void mouseReleased(MouseEvent e) + { + } + } +} diff --git a/libjava/javax/swing/plaf/basic/BasicProgressBarUI.java b/libjava/javax/swing/plaf/basic/BasicProgressBarUI.java index 673c502a547..4a74617726d 100644 --- a/libjava/javax/swing/plaf/basic/BasicProgressBarUI.java +++ b/libjava/javax/swing/plaf/basic/BasicProgressBarUI.java @@ -712,6 +712,7 @@ public class BasicProgressBarUI extends ProgressBarUI progressBar.setForeground(defaults.getColor("ProgressBar.foreground")); progressBar.setBackground(defaults.getColor("ProgressBar.background")); progressBar.setBorder(defaults.getBorder("ProgressBar.border")); + progressBar.setOpaque(true); selectionForeground = defaults.getColor("ProgressBar.selectionForeground"); selectionBackground = defaults.getColor("ProgressBar.selectionBackground"); diff --git a/libjava/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java b/libjava/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java index 9a9f2e89c66..c3c3c840ddb 100644 --- a/libjava/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java +++ b/libjava/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java @@ -48,27 +48,55 @@ import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; +/** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision: 1.1.2.3 $ + */ public class BasicRadioButtonMenuItemUI extends BasicMenuItemUI { - + /** + * Creates a new BasicRadioButtonMenuItemUI object. + */ public BasicRadioButtonMenuItemUI() - { + { super(); UIDefaults defaults = UIManager.getLookAndFeelDefaults(); checkIcon = defaults.getIcon("RadioButtonMenuItem.checkIcon"); } + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ public static ComponentUI createUI(JComponent b) { return new BasicRadioButtonMenuItemUI(); } + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ protected String getPropertyPrefix() { return null; // TODO } + /** + * DOCUMENT ME! + * + * @param item DOCUMENT ME! + * @param e DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ void processMouseEvent(JMenuItem item, MouseEvent e, MenuElement[] path, MenuSelectionManager manager) { diff --git a/libjava/javax/swing/plaf/basic/BasicRootPaneUI.java b/libjava/javax/swing/plaf/basic/BasicRootPaneUI.java index e6472160587..96f09a11980 100644 --- a/libjava/javax/swing/plaf/basic/BasicRootPaneUI.java +++ b/libjava/javax/swing/plaf/basic/BasicRootPaneUI.java @@ -52,6 +52,8 @@ public class BasicRootPaneUI extends RootPaneUI public void installUI(JComponent c) { + c.setOpaque(true); + c.setBackground(javax.swing.UIManager.getColor("control")); super.installUI(c); } } diff --git a/libjava/javax/swing/plaf/basic/BasicScrollBarUI.java b/libjava/javax/swing/plaf/basic/BasicScrollBarUI.java index d6b31a2bafa..c52ca00409c 100644 --- a/libjava/javax/swing/plaf/basic/BasicScrollBarUI.java +++ b/libjava/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -125,6 +125,9 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ public void stateChanged(ChangeEvent e) { + // System.err.println(this + ".stateChanged()"); + calculatePreferredSize(); + layoutContainer(scrollbar); getThumbBounds(); scrollbar.repaint(); } @@ -734,6 +737,8 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ private void calculatePreferredSize() { + // System.err.println(this + ".calculatePreferredSize()"); + int height; int width; height = width = 0; @@ -743,7 +748,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, width += incrButton.getPreferredSize().getWidth(); width += decrButton.getPreferredSize().getWidth(); - width += Math.max(200, scrollbar.getVisibleAmount()); + width += (scrollbar.getMaximum() - scrollbar.getMinimum()); height = Math.max(incrButton.getPreferredSize().height, decrButton.getPreferredSize().height); @@ -756,7 +761,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, height += incrButton.getPreferredSize().getHeight(); height += decrButton.getPreferredSize().getHeight(); - height += Math.max(200, scrollbar.getVisibleAmount()); + height += (scrollbar.getMaximum() - scrollbar.getMinimum()); width = Math.max(incrButton.getPreferredSize().width, decrButton.getPreferredSize().width); @@ -804,6 +809,8 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, int value = scrollbar.getValue(); int extent = scrollbar.getVisibleAmount(); + // System.err.println(this + ".getThumbBounds()"); + if (max == min) { thumbRect.x = trackRect.x; @@ -892,8 +899,8 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, scrollbar.setForeground(defaults.getColor("ScrollBar.foreground")); scrollbar.setBackground(defaults.getColor("ScrollBar.background")); - scrollbar.setBorder(defaults.getBorder("ScrollBar.border")); + scrollbar.setOpaque(true); maximumThumbSize = defaults.getDimension("ScrollBar.maximumThumbSize"); minimumThumbSize = defaults.getDimension("ScrollBar.minimumThumbSize"); @@ -1046,14 +1053,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, public void paint(Graphics g, JComponent c) { layoutContainer(scrollbar); - -// Rectangle r = incrButton.getBounds(); -// SwingUtilities.paintComponent(g, incrButton, scrollbar, r.x, r.y, r.width, -// r.height); -// r = decrButton.getBounds(); -// SwingUtilities.paintComponent(g, decrButton, scrollbar, r.x, r.y, r.width, -// r.height); - paintTrack(g, c, getTrackBounds()); paintThumb(g, c, getThumbBounds()); diff --git a/libjava/javax/swing/plaf/basic/BasicSeparatorUI.java b/libjava/javax/swing/plaf/basic/BasicSeparatorUI.java index b7df0acb27d..8f4500fd58c 100644 --- a/libjava/javax/swing/plaf/basic/BasicSeparatorUI.java +++ b/libjava/javax/swing/plaf/basic/BasicSeparatorUI.java @@ -123,6 +123,7 @@ public class BasicSeparatorUI extends SeparatorUI shadow = defaults.getColor("Separator.shadow"); highlight = defaults.getColor("Separator.highlight"); + s.setOpaque(true); } /** diff --git a/libjava/javax/swing/plaf/basic/BasicSliderUI.java b/libjava/javax/swing/plaf/basic/BasicSliderUI.java index 05e3bb334f2..7b5a52f832c 100644 --- a/libjava/javax/swing/plaf/basic/BasicSliderUI.java +++ b/libjava/javax/swing/plaf/basic/BasicSliderUI.java @@ -681,6 +681,7 @@ public class BasicSliderUI extends SliderUI highlightColor = defaults.getColor("Slider.highlight"); focusColor = defaults.getColor("Slider.focus"); slider.setBorder(defaults.getBorder("Slider.border")); + slider.setOpaque(true); thumbHeight = defaults.getInt("Slider.thumbHeight"); thumbWidth = defaults.getInt("Slider.thumbWidth"); diff --git a/libjava/javax/swing/plaf/basic/BasicSplitPaneDivider.java b/libjava/javax/swing/plaf/basic/BasicSplitPaneDivider.java index 39db7e76bfb..3a2db55a863 100644 --- a/libjava/javax/swing/plaf/basic/BasicSplitPaneDivider.java +++ b/libjava/javax/swing/plaf/basic/BasicSplitPaneDivider.java @@ -1,5 +1,5 @@ /* BasicSplitPaneDivider.java - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -35,14 +35,15 @@ this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ - package javax.swing.plaf.basic; +import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; +import java.awt.LayoutManager; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; @@ -50,173 +51,173 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JButton; import javax.swing.JSplitPane; +import javax.swing.SwingConstants; import javax.swing.border.Border; /** - * The divider that separates the two parts of a JSplitPane in the - * Basic look and feel. - * - * <p>Implementation status: We do not have a real implementation yet. - * Currently, it is mostly a stub to allow compiling other parts of - * the javax.swing.plaf.basic package, although some parts are already + * The divider that separates the two parts of a JSplitPane in the Basic look + * and feel. + * + * <p> + * Implementation status: We do not have a real implementation yet. Currently, + * it is mostly a stub to allow compiling other parts of the + * javax.swing.plaf.basic package, although some parts are already * functional. + * </p> * - * @author Sascha Brawer (brawer@dandelis.ch) + * @author Sascha Brawer (brawer_AT_dandelis.ch) */ -public class BasicSplitPaneDivider - extends Container +public class BasicSplitPaneDivider extends Container implements PropertyChangeListener { /** - * Determined using the <code>serialver</code> tool - * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + * Determined using the <code>serialver</code> tool of Apple/Sun JDK 1.3.1 + * on MacOS X 10.1.5. */ static final long serialVersionUID = 1463404307042803342L; - /** - * The width and height of the little buttons for showing and - * hiding parts of a JSplitPane in a single mouse click. + * The width and height of the little buttons for showing and hiding parts + * of a JSplitPane in a single mouse click. */ protected static final int ONE_TOUCH_SIZE = 6; - - // FIXME: Javadoc. + /** The distance the one touch buttons will sit from the divider's edges. */ protected static final int ONE_TOUCH_OFFSET = 2; - /** * An object that performs the tasks associated with an ongoing drag - * operation, or <code>null</code> if the user is currently not - * dragging the divider. + * operation, or <code>null</code> if the user is currently not dragging + * the divider. */ protected DragController dragger; - /** * The delegate object that is responsible for the UI of the * <code>JSplitPane</code> that contains this divider. */ protected BasicSplitPaneUI splitPaneUI; - - /** - * The thickness of the divider in pixels. - */ + /** The thickness of the divider in pixels. */ protected int dividerSize; - - /** - * A divider that is used for layout purposes. - */ + /** A divider that is used for layout purposes. */ protected Component hiddenDivider; - - /** - * The JSplitPane containing this divider. - */ + /** The JSplitPane containing this divider. */ protected JSplitPane splitPane; - /** - * The listener for handling mouse events from both the divider - * and the containing <code>JSplitPane</code>. - * - * <p>The reason for also handling MouseEvents from the containing - * <code>JSplitPane</code> is that users should be able to start - * a drag gesture from inside the JSplitPane, but slightly outisde - * the divider. + * The listener for handling mouse events from both the divider and the + * containing <code>JSplitPane</code>. + * + * <p> + * The reason for also handling MouseEvents from the containing + * <code>JSplitPane</code> is that users should be able to start a drag + * gesture from inside the JSplitPane, but slightly outisde the divider. + * </p> */ protected MouseHandler mouseHandler = new MouseHandler(); - /** - * The current orientation of the containing <code>JSplitPane</code>, - * which is either {@link javax.swing.JSplitPane#HORIZONTAL_SPLIT} - * or {@link javax.swing.JSplitPane#VERTICAL_SPLIT}. + * The current orientation of the containing <code>JSplitPane</code>, which + * is either {@link javax.swing.JSplitPane#HORIZONTAL_SPLIT} or {@link + * javax.swing.JSplitPane#VERTICAL_SPLIT}. */ protected int orientation; - /** - * The button for showing and hiding the left (or top) component - * of the <code>JSplitPane</code>. + * The button for showing and hiding the left (or top) component of the + * <code>JSplitPane</code>. */ protected JButton leftButton; - /** - * The button for showing and hiding the right (or bottom) component - * of the <code>JSplitPane</code>. + * The button for showing and hiding the right (or bottom) component of the + * <code>JSplitPane</code>. */ protected JButton rightButton; - /** - * The border of this divider. Typically, this will be an instance of - * {@link javax.swing.plaf.basic.BasicBorders.SplitPaneDividerBorder}. + * The border of this divider. Typically, this will be an instance of {@link + * javax.swing.plaf.basic.BasicBorders.SplitPaneDividerBorder}. * * @see #getBorder() * @see #setBorder(javax.swing.border.Border) */ private Border border; + // This is not a pixel count. + // This int should be able to take 3 values. + // left (top), middle, right(bottom) + // 0 1 2 + + /** Keeps track of where the divider should be placed when using one touch expand + * buttons. */ + private transient int currentDividerLocation = 1; /** * Constructs a new divider. * - * @param ui the UI delegate of the enclosing - * <code>JSplitPane</code>. + * @param ui the UI delegate of the enclosing <code>JSplitPane</code>. */ public BasicSplitPaneDivider(BasicSplitPaneUI ui) { + setLayout(new DividerLayout()); setBasicSplitPaneUI(ui); + setDividerSize(splitPane.getDividerSize()); } - /** - * Sets the delegate object that is responsible for the UI of the - * {@link javax.swing.JSplitPane} containing this divider. + * Sets the delegate object that is responsible for the UI of the {@link + * javax.swing.JSplitPane} containing this divider. * - * @param newUI the UI delegate, or <code>null</code> to release - * the connection to the current delegate. + * @param newUI the UI delegate, or <code>null</code> to release the + * connection to the current delegate. */ public void setBasicSplitPaneUI(BasicSplitPaneUI newUI) { /* Remove the connection to the existing JSplitPane. */ if (splitPane != null) - { - splitPane.removePropertyChangeListener(this); - splitPane.removeMouseListener(mouseHandler); - splitPane.removeMouseMotionListener(mouseHandler); - splitPane = null; - } - + { + splitPane.removePropertyChangeListener(this); + splitPane.removeMouseListener(mouseHandler); + splitPane.removeMouseMotionListener(mouseHandler); + removeMouseListener(mouseHandler); + removeMouseMotionListener(mouseHandler); + splitPane = null; + hiddenDivider = null; + } + /* Establish the connection to the new JSplitPane. */ splitPaneUI = newUI; if (splitPaneUI != null) splitPane = newUI.getSplitPane(); if (splitPane != null) - { - splitPane.addPropertyChangeListener(this); - splitPane.addMouseListener(mouseHandler); - splitPane.addMouseMotionListener(mouseHandler); - orientation = splitPane.getOrientation(); - } + { + splitPane.addPropertyChangeListener(this); + splitPane.addMouseListener(mouseHandler); + splitPane.addMouseMotionListener(mouseHandler); + addMouseListener(mouseHandler); + addMouseMotionListener(mouseHandler); + hiddenDivider = splitPaneUI.getNonContinuousLayoutDivider(); + orientation = splitPane.getOrientation(); + oneTouchExpandableChanged(); + } } - /** - * Returns the delegate object that is responsible for the UI of the - * {@link javax.swing.JSplitPane} containing this divider. + * Returns the delegate object that is responsible for the UI of the {@link + * javax.swing.JSplitPane} containing this divider. + * + * @return The UI for the JSplitPane. */ public BasicSplitPaneUI getBasicSplitPaneUI() { return splitPaneUI; } - /** * Sets the thickness of the divider. * @@ -227,37 +228,40 @@ public class BasicSplitPaneDivider this.dividerSize = newSize; } - /** * Retrieves the thickness of the divider. + * + * @return The thickness of the divider. */ public int getDividerSize() { return dividerSize; } - - + /** * Sets the border of this divider. * * @param border the new border. Typically, this will be an instance of - * {@link javax.swing.plaf.basic.BasicBorders.SplitPaneDividerBorder}. + * {@link + * javax.swing.plaf.basic.BasicBorders.SplitPaneDividerBorder}. * * @since 1.3 */ public void setBorder(Border border) { - Border oldValue = this.border; - this.border = border; - firePropertyChange("border", oldValue, border); + if (border != this.border) + { + Border oldValue = this.border; + this.border = border; + firePropertyChange("border", oldValue, border); + } } - /** * Retrieves the border of this divider. * - * @return the current border, or <code>null</code> if no border - * has been set. + * @return the current border, or <code>null</code> if no border has been + * set. * * @since 1.3 */ @@ -265,13 +269,12 @@ public class BasicSplitPaneDivider { return border; } - /** - * Retrieves the insets of the divider. If a border has been - * installed on the divider, the result of calling its - * <code>getBorderInsets</code> method is returned. Otherwise, - * the inherited implementation will be invoked. + * Retrieves the insets of the divider. If a border has been installed on + * the divider, the result of calling its <code>getBorderInsets</code> + * method is returned. Otherwise, the inherited implementation will be + * invoked. * * @see javax.swing.border.Border#getBorderInsets(java.awt.Component) */ @@ -282,42 +285,56 @@ public class BasicSplitPaneDivider else return super.getInsets(); } - - + /** * Returns the preferred size of this divider, which is - * <code>dividerSize</code> by <code>dividerSize</code> - * pixels. + * <code>dividerSize</code> by <code>dividerSize</code> pixels. + * + * @return The preferred size of the divider. */ public Dimension getPreferredSize() { - return new Dimension(dividerSize, dividerSize); + return getLayout().preferredLayoutSize(this); } - /** * Returns the minimal size of this divider, which is - * <code>dividerSize</code> by <code>dividerSize</code> - * pixels. + * <code>dividerSize</code> by <code>dividerSize</code> pixels. + * + * @return The minimal size of the divider. */ public Dimension getMinimumSize() { return getPreferredSize(); } - - + /** - * Processes events from the <code>JSplitPane</code> that contains - * this divider. + * Processes events from the <code>JSplitPane</code> that contains this + * divider. + * + * @param e The PropertyChangeEvent. */ public void propertyChange(PropertyChangeEvent e) { - // FIXME: Not yet implemented. + if (e.getPropertyName().equals(JSplitPane.ONE_TOUCH_EXPANDABLE_PROPERTY)) + oneTouchExpandableChanged(); + else if (e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY)) + { + orientation = splitPane.getOrientation(); + if (splitPane.isOneTouchExpandable()) + { + layout(); + repaint(); + } + } + else if (e.getPropertyName().equals(JSplitPane.DIVIDER_SIZE_PROPERTY)) + dividerSize = splitPane.getDividerSize(); } - /** * Paints the divider by painting its border. + * + * @param g The Graphics Object to paint with. */ public void paint(Graphics g) { @@ -325,50 +342,85 @@ public class BasicSplitPaneDivider super.paint(g); if (border != null) - { - dividerSize = getSize(); - border.paintBorder(this, g, 0, 0, dividerSize.width, dividerSize.height); - //System.out.println(dividerSize); - //g.setColor(java.awt.Color.white); - //g.drawRect(0, 0, 5, 5); - } + { + dividerSize = getSize(); + border.paintBorder(this, g, 0, 0, dividerSize.width, dividerSize.height); + } } - /** - * Reacts to changes of the <code>oneToughExpandable</code> - * property of the containing <code>JSplitPane</code>. + * Reacts to changes of the <code>oneToughExpandable</code> property of the + * containing <code>JSplitPane</code>. */ protected void oneTouchExpandableChanged() { - // FIXME: Not yet implemented. + if (splitPane.isOneTouchExpandable()) + { + leftButton = createLeftOneTouchButton(); + rightButton = createRightOneTouchButton(); + add(leftButton); + add(rightButton); + + leftButton.addMouseListener(mouseHandler); + rightButton.addMouseListener(mouseHandler); + + // Set it to 1. + currentDividerLocation = 1; + } + else + { + if (leftButton != null && rightButton != null) + { + leftButton.removeMouseListener(mouseHandler); + rightButton.removeMouseListener(mouseHandler); + + remove(leftButton); + remove(rightButton); + leftButton = null; + rightButton = null; + } + } + layout(); + repaint(); } - /** - * Creates a button for showing and hiding the left (or top) - * part of a <code>JSplitPane</code>. + * Creates a button for showing and hiding the left (or top) part of a + * <code>JSplitPane</code>. + * + * @return The left one touch button. */ protected JButton createLeftOneTouchButton() { - return new OneTouchButton(/* left */ true); - } + int dir = SwingConstants.WEST; + if (orientation == JSplitPane.VERTICAL_SPLIT) + dir = SwingConstants.NORTH; + JButton button = new BasicArrowButton(dir); + button.setBorderPainted(false); + return button; + } /** - * Creates a button for showing and hiding the right (or bottom) - * part of a <code>JSplitPane</code>. + * Creates a button for showing and hiding the right (or bottom) part of a + * <code>JSplitPane</code>. + * + * @return The right one touch button. */ protected JButton createRightOneTouchButton() { - return new OneTouchButton(/* left */ false); + int dir = SwingConstants.EAST; + if (orientation == JSplitPane.VERTICAL_SPLIT) + dir = SwingConstants.SOUTH; + JButton button = new BasicArrowButton(dir); + button.setBorderPainted(false); + return button; } - /** * Prepares the divider for dragging by calling the - * <code>startDragging</code> method of the UI delegate of the - * enclosing <code>JSplitPane</code>. + * <code>startDragging</code> method of the UI delegate of the enclosing + * <code>JSplitPane</code>. * * @see BasicSplitPaneUI#startDragging() */ @@ -378,15 +430,14 @@ public class BasicSplitPaneDivider splitPaneUI.startDragging(); } - /** * Drags the divider to a given location by calling the - * <code>dragDividerTo</code> method of the UI delegate of the - * enclosing <code>JSplitPane</code>. + * <code>dragDividerTo</code> method of the UI delegate of the enclosing + * <code>JSplitPane</code>. * * @param location the new location of the divider. * - * @see BasicSplitPaneUI#dragDividerTo(int location) + * @see BasicSplitPaneUI#dragDividerTo(int location) */ protected void dragDividerTo(int location) { @@ -394,11 +445,9 @@ public class BasicSplitPaneDivider splitPaneUI.dragDividerTo(location); } - /** - * Finishes a dragging gesture by calling the - * <code>finishDraggingTo</code> method of the UI delegate of the - * enclosing <code>JSplitPane</code>. + * Finishes a dragging gesture by calling the <code>finishDraggingTo</code> + * method of the UI delegate of the enclosing <code>JSplitPane</code>. * * @param location the new, final location of the divider. * @@ -410,125 +459,425 @@ public class BasicSplitPaneDivider splitPaneUI.finishDraggingTo(location); } - /** - * The listener for handling mouse events from both the divider - * and the containing <code>JSplitPane</code>. + * This helper method moves the divider to one of the + * three locations when using one touch expand buttons. + * Location 0 is the left (or top) most location. + * Location 1 is the middle. + * Location 2 is the right (or bottom) most location. * - * <p>The reason for also handling MouseEvents from the containing - * <code>JSplitPane</code> is that users should be able to start - * a drag gesture from inside the JSplitPane, but slightly outisde - * the divider. + * @param locationIndex The location to move to. + */ + private void moveDividerTo(int locationIndex) + { + Insets insets = splitPane.getInsets(); + switch (locationIndex) + { + case 1: + splitPane.setDividerLocation(splitPane.getLastDividerLocation()); + break; + case 0: + int top = (orientation == JSplitPane.HORIZONTAL_SPLIT) ? insets.left + : insets.top; + splitPane.setDividerLocation(top); + break; + case 2: + int bottom; + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + bottom = splitPane.getBounds().width - insets.right - dividerSize; + else + bottom = splitPane.getBounds().height - insets.bottom - dividerSize; + splitPane.setDividerLocation(bottom); + break; + } + } + + /** + * The listener for handling mouse events from both the divider and the + * containing <code>JSplitPane</code>. + * + * <p> + * The reason for also handling MouseEvents from the containing + * <code>JSplitPane</code> is that users should be able to start a drag + * gesture from inside the JSplitPane, but slightly outisde the divider. + * </p> * - * @author Sascha Brawer (brawer@dandelis.ch) + * @author Sascha Brawer (brawer_AT_dandelis.ch) */ - protected class MouseHandler - extends MouseAdapter + protected class MouseHandler extends MouseAdapter implements MouseMotionListener { - + /** Keeps track of whether a drag is occurring. */ + private transient boolean isDragging; + + /** + * This method is called when the mouse is pressed. + * + * @param e The MouseEvent. + */ public void mousePressed(MouseEvent e) { - // FIXME: Not yet implemented. + if (splitPane.isOneTouchExpandable()) + { + if (e.getSource() == leftButton) + { + currentDividerLocation--; + if (currentDividerLocation < 0) + currentDividerLocation = 0; + moveDividerTo(currentDividerLocation); + return; + } + else if (e.getSource() == rightButton) + { + currentDividerLocation++; + if (currentDividerLocation > 2) + currentDividerLocation = 2; + moveDividerTo(currentDividerLocation); + return; + } + } + isDragging = true; + currentDividerLocation = 1; + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + dragger = new DragController(e); + else + dragger = new VerticalDragController(e); + prepareForDragging(); } - + /** + * This method is called when the mouse is released. + * + * @param e The MouseEvent. + */ public void mouseReleased(MouseEvent e) { - // FIXME: Not yet implemented. + if (isDragging) + dragger.completeDrag(e); + isDragging = false; } - /** - * Repeatedly invoked when the user is dragging the mouse cursor - * while having pressed a mouse button. + * Repeatedly invoked when the user is dragging the mouse cursor while + * having pressed a mouse button. + * + * @param e The MouseEvent. */ public void mouseDragged(MouseEvent e) { - // FIXME: Not yet implemented. + if (dragger != null) + dragger.continueDrag(e); } - /** - * Repeatedly invoked when the user is dragging the mouse cursor - * without having pressed a mouse button. + * Repeatedly invoked when the user is dragging the mouse cursor without + * having pressed a mouse button. + * + * @param e The MouseEvent. */ public void mouseMoved(MouseEvent e) { - // FIXME: Not yet implemented. + // Do nothing. } } - /** - * A small button for showing and hiding parts of a - * <code>JSplitPane</code> with a single mouse click. + * Performs the tasks associated with an ongoing drag operation. * - * @author Sascha Brawer (brawer@dandelis.ch) + * @author Sascha Brawer (brawer_AT_dandelis.ch) */ - private static class OneTouchButton - extends JButton + protected class DragController { - OneTouchButton(boolean left) + /** The difference between where the mouse is clicked and the + * initial divider location. */ + transient int offset; + + /** + * Creates a new DragController object. + * + * @param e The MouseEvent to initialize with. + */ + protected DragController(MouseEvent e) { - // FIXME: Set various properties of the button. - // Make sure it looks identical to the small - // buttons of the Sun reference implementation. - // The size should also be the same. - if (left) - setText("<"); - else - setText(">"); + offset = e.getX(); + } - Dimension butSize = new Dimension(ONE_TOUCH_SIZE, ONE_TOUCH_SIZE); - setMinimumSize(butSize); - setMaximumSize(butSize); - setPreferredSize(butSize); + /** + * This method returns true if the divider can move. + * + * @return True if dragging is allowed. + */ + protected boolean isValid() + { + // Views can always be resized? + return true; + } - setBorderPainted(false); + /** + * Returns a position for the divider given the MouseEvent. + * + * @param e MouseEvent. + * + * @return The position for the divider to move to. + */ + protected int positionForMouseEvent(MouseEvent e) + { + return e.getX() + getX() - offset; + ; } - } + /** + * This method returns one of the two paramters + * for the orientation. In this case, it returns x. + * + * @param x The x coordinate. + * @param y The y coordinate. + * + * @return The x coordinate. + */ + protected int getNeededLocation(int x, int y) + { + return x; + } + + /** + * This method is called to pass on the drag information + * to the UI through dragDividerTo. + * + * @param newX The x coordinate of the MouseEvent. + * @param newY The y coordinate of the MouseEvent. + */ + protected void continueDrag(int newX, int newY) + { + if (isValid()) + dragDividerTo(adjust(x, y)); + } + + /** + * This method is called to pass on the drag information + * to the UI through dragDividerTo. + * + * @param e The MouseEvent. + */ + protected void continueDrag(MouseEvent e) + { + if (isValid()) + dragDividerTo(positionForMouseEvent(e)); + } + + /** + * This method is called to finish the drag session + * by calling finishDraggingTo. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + */ + protected void completeDrag(int x, int y) + { + finishDraggingTo(adjust(x, y)); + } + + /** + * This method is called to finish the drag session + * by calling finishDraggingTo. + * + * @param e The MouseEvent. + */ + protected void completeDrag(MouseEvent e) + { + finishDraggingTo(positionForMouseEvent(e)); + } + + /** + * This is a helper method that includes the offset + * in the needed location. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The needed location adjusted by the offsets. + */ + int adjust(int x, int y) + { + return getNeededLocation(x, y) + getX() - offset; + } + } /** - * Performs the tasks associated with an ongoing drag - * operation. - * - * @author Sascha Brawer (brawer@dandelis.ch) + * This is a helper class that controls dragging when + * the orientation is VERTICAL_SPLIT. */ - protected class DragController + protected class VerticalDragController extends DragController { - // FIXME: Not yet implemented. - protected DragController(MouseEvent e) + /** + * Creates a new VerticalDragController object. + * + * @param e The MouseEvent to initialize with. + */ + protected VerticalDragController(MouseEvent e) { + super(e); + offset = e.getY(); } - protected boolean isValid() + /** + * This method returns one of the two parameters given + * the orientation. In this case, it returns y. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The y coordinate. + */ + protected int getNeededLocation(int x, int y) { - // FIXME: Not yet implemented. - return true; + return y; } + /** + * This method returns the new location of the divider + * given a MouseEvent. + * + * @param e The MouseEvent. + * + * @return The new location of the divider. + */ protected int positionForMouseEvent(MouseEvent e) { - return 0; + return e.getY() + getY() - offset; } - protected int getNeededLocation(int x, int y) + /** + * This is a helper method that includes the offset + * in the needed location. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The needed location adjusted by the offsets. + */ + int adjust(int x, int y) + { + return getNeededLocation(x, y) + getY() - offset; + } + } + + /** + * This helper class acts as the Layout Manager for + * the divider. + */ + protected class DividerLayout implements LayoutManager + { + /** + * Creates a new DividerLayout object. + */ + protected DividerLayout() { - return 0; } - protected void continueDrag(int newX, int newY) + /** + * This method is called when a Component is added. + * + * @param string The constraints string. + * @param c The Component to add. + */ + public void addLayoutComponent(String string, Component c) { + // Do nothing. } - protected void completeDrag(int x, int y) + /** + * This method is called to lay out the container. + * + * @param c The container to lay out. + */ + public void layoutContainer(Container c) { + if (splitPane.isOneTouchExpandable()) + { + changeButtonOrientation(); + positionButtons(); + } } - protected void completeDrag(MouseEvent e) + /** + * This method returns the minimum layout size. + * + * @param c The container to calculate for. + * + * @return The minimum layout size. + */ + public Dimension minimumLayoutSize(Container c) { + return preferredLayoutSize(c); + } + + /** + * This method returns the preferred layout size. + * + * @param c The container to calculate for. + * + * @return The preferred layout size. + */ + public Dimension preferredLayoutSize(Container c) + { + return new Dimension(dividerSize, dividerSize); + } + + /** + * This method is called when a component is removed. + * + * @param c The component to remove. + */ + public void removeLayoutComponent(Component c) + { + // Do nothing. + } + + /** + * This method changes the button orientation when + * the orientation of the SplitPane changes. + */ + private void changeButtonOrientation() + { + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + { + ((BasicArrowButton) rightButton).setDirection(SwingConstants.EAST); + ((BasicArrowButton) leftButton).setDirection(SwingConstants.WEST); + } + else + { + ((BasicArrowButton) rightButton).setDirection(SwingConstants.SOUTH); + ((BasicArrowButton) leftButton).setDirection(SwingConstants.NORTH); + } + } + + /** + * This method sizes and positions the buttons. + */ + private void positionButtons() + { + int w = 0; + int h = 0; + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + { + rightButton.setLocation(ONE_TOUCH_OFFSET, ONE_TOUCH_OFFSET); + leftButton.setLocation(ONE_TOUCH_OFFSET, + ONE_TOUCH_OFFSET + 2 * ONE_TOUCH_SIZE); + w = dividerSize - 2 * ONE_TOUCH_OFFSET; + h = 2 * ONE_TOUCH_SIZE; + } + else + { + leftButton.setLocation(ONE_TOUCH_OFFSET, ONE_TOUCH_OFFSET); + rightButton.setLocation(ONE_TOUCH_OFFSET + 2 * ONE_TOUCH_SIZE, + ONE_TOUCH_OFFSET); + h = dividerSize - 2 * ONE_TOUCH_OFFSET; + w = 2 * ONE_TOUCH_SIZE; + } + Dimension dims = new Dimension(w, h); + leftButton.setSize(dims); + rightButton.setSize(dims); } } } diff --git a/libjava/javax/swing/plaf/basic/BasicSplitPaneUI.java b/libjava/javax/swing/plaf/basic/BasicSplitPaneUI.java index 5c1c7f25e4f..f1ccb133997 100644 --- a/libjava/javax/swing/plaf/basic/BasicSplitPaneUI.java +++ b/libjava/javax/swing/plaf/basic/BasicSplitPaneUI.java @@ -1,5 +1,5 @@ /* BasicSplitPaneUI.java - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,273 +37,1484 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Canvas; +import java.awt.Color; import java.awt.Component; +import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; +import java.awt.LayoutManager2; +import java.awt.Point; +import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JSplitPane; import javax.swing.KeyStroke; +import javax.swing.UIDefaults; +import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.SplitPaneUI; + /** - * FIXME: Stubbed to allow compiling other classes, - * no real implementation. + * This is the Basic Look and Feel implementation of the SplitPaneUI class. */ -public class BasicSplitPaneUI - extends SplitPaneUI +public class BasicSplitPaneUI extends SplitPaneUI { - protected static final String NON_CONTINUOUS_DIVIDER - = "nonContinuousDivider"; + /** + * This Layout Manager controls the position and size of the components when + * the JSplitPane's orientation is HORIZONTAL_SPLIT. + */ + protected class BasicHorizontalLayoutManager implements LayoutManager2 + { + // 3 components at a time. + // LEFT/TOP = 0 + // RIGHT/BOTTOM = 1 + // DIVIDER = 2 + + /** + * This array contains the components in the JSplitPane. The left/top + * component is at index 0, the right/bottom is at 1, and the divider is + * at 2. + */ + protected Component[] components = new Component[3]; + + // These are the _current_ widths of the associated component. + + /** + * This array contains the current width (for HORIZONTAL_SPLIT) or height + * (for VERTICAL_SPLIT) of the components. The indices are the same as + * for components. + */ + protected int[] sizes = new int[3]; + + /** + * This method adds the component given to the JSplitPane. The position of + * the component is given by the constraints object. + * + * @param comp The Component to add. + * @param constraints The constraints that bind the object. + */ + public void addLayoutComponent(Component comp, Object constraints) + { + addLayoutComponent((String) constraints, comp); + } + + /** + * This method is called to add a Component to the JSplitPane. The + * placement string determines where the Component will be placed. The + * string should be one of LEFT, RIGHT, TOP, BOTTOM or null (signals that + * the component is the divider). + * + * @param place The placement of the Component. + * @param component The Component to add. + * + * @throws IllegalArgumentException DOCUMENT ME! + */ + public void addLayoutComponent(String place, Component component) + { + int i = 0; + if (place == null) + i = 2; + else if (place.equals(JSplitPane.TOP) || place.equals(JSplitPane.LEFT)) + i = 0; + else if (place.equals(JSplitPane.BOTTOM) + || place.equals(JSplitPane.RIGHT)) + i = 1; + else + throw new IllegalArgumentException("Illegal placement in JSplitPane"); + components[i] = component; + resetSizeAt(i); + layoutContainer(splitPane); + splitPane.repaint(); + } + + /** + * This method returns the width of the JSplitPane minus the insets. + * + * @param containerSize The Dimensions of the JSplitPane. + * @param insets The Insets of the JSplitPane. + * + * @return The width of the JSplitPane minus the insets. + */ + protected int getAvailableSize(Dimension containerSize, Insets insets) + { + return containerSize.width - insets.left - insets.right; + } + + /** + * This method returns the given insets left value. If the given inset is + * null, then 0 is returned. + * + * @param insets The Insets to use with the JSplitPane. + * + * @return The inset's left value. + */ + protected int getInitialLocation(Insets insets) + { + if (insets != null) + return insets.left; + return 0; + } + + /** + * This specifies how a component is aligned with respect to other + * components in the x fdirection. + * + * @param target The container. + * + * @return The component's alignment. + */ + public float getLayoutAlignmentX(Container target) + { + return target.getAlignmentX(); + } + + /** + * This specifies how a component is aligned with respect to other + * components in the y direction. + * + * @param target The container. + * + * @return The component's alignment. + */ + public float getLayoutAlignmentY(Container target) + { + return target.getAlignmentY(); + } + + /** + * This method returns the preferred width of the component. + * + * @param c The component to measure. + * + * @return The preferred width of the component. + */ + protected int getPreferredSizeOfComponent(Component c) + { + Dimension dims = c.getPreferredSize(); + if (dims != null) + return dims.width; + return 0; + } + + /** + * This method returns the current width of the component. + * + * @param c The component to measure. + * + * @return The width of the component. + */ + protected int getSizeOfComponent(Component c) + { + return c.getWidth(); + } + + /** + * This method returns the sizes array. + * + * @return The sizes array. + */ + protected int[] getSizes() + { + return sizes; + } + + /** + * This method invalidates the layout. It does nothing. + * + * @param c The container to invalidate. + */ + public void invalidateLayout(Container c) + { + // DO NOTHING + } + + /** + * This method lays out the components in the container. + * + * @param container The container to lay out. + */ + public void layoutContainer(Container container) + { + if (container instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) container; + distributeExtraSpace(); + Insets insets = split.getInsets(); + int width = getInitialLocation(insets); + Dimension dims = split.getSize(); + for (int i = 0; i < components.length; i += 2) + { + if (components[i] == null) + continue; + setComponentToSize(components[i], sizes[i], width, insets, dims); + width += sizes[i]; + } + if (components[1] != null) + { + setComponentToSize(components[1], sizes[1], width, insets, dims); + width += sizes[1]; + } + } + } + + /** + * This method returns the maximum size for the container given the + * components. It returns a new Dimension object that has width and + * height equal to Integer.MAX_VALUE. + * + * @param target The container to measure. + * + * @return The maximum size. + */ + public Dimension maximumLayoutSize(Container target) + { + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + /** + * This method returns the container's minimum size. The minimum width is + * the sum of all the component's minimum widths. The minimum height is + * the maximum of all the components' minimum heights. + * + * @param target The container to measure. + * + * @return The minimum size. + */ + public Dimension minimumLayoutSize(Container target) + { + if (target instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) target; + Insets insets = target.getInsets(); + + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getMinimumSize(); + if (dims != null) + { + width += dims.width; + height = Math.max(height, dims.height); + } + } + return new Dimension(width, height); + } + return null; + } + + /** + * This method returns the container's preferred size. The preferred width + * is the sum of all the component's preferred widths. The preferred + * height is the maximum of all the components' preferred heights. + * + * @param target The container to measure. + * + * @return The preferred size. + */ + public Dimension preferredLayoutSize(Container target) + { + if (target instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) target; + Insets insets = target.getInsets(); + + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getPreferredSize(); + if (dims != null) + { + width += dims.width; + if (! (components[i] instanceof BasicSplitPaneDivider)) + height = Math.max(height, dims.height); + } + } + return new Dimension(500, 500); //width, height); + } + return null; + } + + /** + * This method removes the component from the layout. + * + * @param component The component to remove from the layout. + */ + public void removeLayoutComponent(Component component) + { + for (int i = 0; i < components.length; i++) + { + if (component == components[i]) + { + components[i] = null; + sizes[i] = 0; + } + } + } + + /** + * This method resets the size of Component to the preferred size. + * + * @param index The index of the component to reset. + */ + protected void resetSizeAt(int index) + { + if (components[index] != null) + sizes[index] = getPreferredSizeOfComponent(components[index]); + } + + /** + * This method resets the sizes of all the components. + */ + public void resetToPreferredSizes() + { + for (int i = 0; i < components.length; i++) + resetSizeAt(i); + } + + /** + * This methods sets the bounds of the given component. The width is the + * size. The height is the container size minus the top and bottom + * inset. The x coordinate is the location given. The y coordinate is + * the top inset. + * + * @param c The component to set. + * @param size The width of the component. + * @param location The x coordinate. + * @param insets The insets to use. + * @param containerSize The height of the container. + */ + protected void setComponentToSize(Component c, int size, int location, + Insets insets, Dimension containerSize) + { + int w = size; + int h = containerSize.height - insets.top - insets.bottom; + int x = location; + int y = insets.top; + c.setBounds(x, y, w, h); + } + + /** + * This method stores the given int array as the new sizes array. + * + * @param newSizes The array to use as sizes. + */ + protected void setSizes(int[] newSizes) + { + sizes = newSizes; + } + + /** + * This method determines the size of each component. It should be called + * when a new Layout Manager is created for an existing JSplitPane. + */ + protected void updateComponents() + { + Component left = splitPane.getLeftComponent(); + Component right = splitPane.getRightComponent(); + + if (left != null) + { + components[0] = left; + resetSizeAt(0); + } + if (right != null) + { + components[1] = right; + resetSizeAt(1); + } + components[2] = divider; + resetSizeAt(2); + } + + /** + * This method resizes the left and right components to fit inside the + * JSplitPane when there is extra space. + */ + void distributeExtraSpace() + { + int availSize = getAvailableSize(splitPane.getSize(), + splitPane.getInsets()); + int[] newSizes = new int[3]; + double weight = splitPane.getResizeWeight(); + + int oldLen = sizes[0] + sizes[1]; + + // dividers don't change size. + availSize -= sizes[2] + oldLen; + + int rightAlloc = (int) (availSize * (1 - weight)); + int leftAlloc = availSize - rightAlloc; + + sizes[0] += leftAlloc; + sizes[1] += rightAlloc; + } + + /** + * This method returns the minimum width of the component at the given + * index. + * + * @param index The index to check. + * + * @return The minimum width. + */ + int minimumSizeOfComponent(int index) + { + Dimension dims = components[index].getMinimumSize(); + if (dims != null) + return dims.width; + else + return 0; + } + } //end BasicHorizontalLayoutManager + + /** + * This class is the Layout Manager for the JSplitPane when the orientation + * is VERTICAL_SPLIT. + */ + protected class BasicVerticalLayoutManager + extends BasicHorizontalLayoutManager + { + /** + * This method returns the height of the container minus the top and + * bottom inset. + * + * @param containerSize The size of the container. + * @param insets The insets of the container. + * + * @return The height minus top and bottom inset. + */ + protected int getAvailableSize(Dimension containerSize, Insets insets) + { + return containerSize.height - insets.top - insets.bottom; + } + + /** + * This method returns the top inset. + * + * @param insets The Insets to use. + * + * @return The top inset. + */ + protected int getInitialLocation(Insets insets) + { + return insets.top; + } + + /** + * This method returns the preferred height of the component. + * + * @param c The component to measure. + * + * @return The preferred height of the component. + */ + protected int getPreferredSizeOfComponent(Component c) + { + Dimension dims = c.getPreferredSize(); + if (dims != null) + return dims.height; + return 0; + } + + /** + * This method returns the current height of the component. + * + * @param c The component to measure. + * + * @return The current height of the component. + */ + protected int getSizeOfComponent(Component c) + { + return c.getHeight(); + } + + /** + * This method returns the minimum layout size. The minimum height is the + * sum of all the components' minimum heights. The minimum width is the + * maximum of all the components' minimum widths. + * + * @param container The container to measure. + * + * @return The minimum size. + */ + public Dimension minimumLayoutSize(Container container) + { + if (container instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) container; + Insets insets = container.getInsets(); + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getMinimumSize(); + if (dims != null) + { + height += dims.height; + width = Math.max(width, dims.width); + } + } + return new Dimension(width, height); + } + return null; + } + + /** + * This method returns the preferred layout size. The preferred height is + * the sum of all the components' preferred heights. The preferred width + * is the maximum of all the components' preferred widths. + * + * @param container The container to measure. + * + * @return The preferred size. + */ + public Dimension preferredLayoutSize(Container container) + { + if (container instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) container; + Insets insets = container.getInsets(); + + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getPreferredSize(); + if (dims != null) + { + height += dims.height; + width = Math.max(width, dims.width); + } + } + return new Dimension(500, 500); //width, height); + } + return null; + } + + /** + * This method sets the bounds of the given component. The y coordinate is + * the location given. The x coordinate is the left inset. The height is + * the size given. The width is the container size minus the left and + * right inset. + * + * @param c The component to set bounds for. + * @param size The height. + * @param location The y coordinate. + * @param insets The insets to use. + * @param containerSize The container's size. + */ + protected void setComponentToSize(Component c, int size, int location, + Insets insets, Dimension containerSize) + { + int y = location; + int x = insets.left; + int h = size; + int w = containerSize.width - insets.left - insets.right; + + c.setBounds(x, y, w, h); + } + + /** + * This method returns the minimum height of the component at the given + * index. + * + * @param index The index of the component to check. + * + * @return The minimum height of the given component. + */ + int minimumSizeOfComponent(int index) + { + Dimension dims = components[index].getMinimumSize(); + if (dims != null) + return dims.height; + else + return 0; + } + } + + /** + * This class handles FocusEvents from the JComponent. + */ + protected class FocusHandler extends FocusAdapter + { + /** + * This method is called when the JSplitPane gains focus. + * + * @param ev The FocusEvent. + */ + public void focusGained(FocusEvent ev) + { + // FIXME: implement. + } + + /** + * This method is called when the JSplitPane loses focus. + * + * @param ev The FocusEvent. + */ + public void focusLost(FocusEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling down + * and right key presses. + */ + protected class KeyboardDownRightHandler implements ActionListener + { + /** + * This method is called when the down or right keys are pressed. + * + * @param ev The ActionEvent + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling end + * key presses. + */ + protected class KeyboardEndHandler implements ActionListener + { + /** + * This method is called when the end key is pressed. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling home + * key presses. + */ + protected class KeyboardHomeHandler implements ActionListener + { + /** + * This method is called when the home key is pressed. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling resize + * toggles. + */ + protected class KeyboardResizeToggleHandler implements ActionListener + { + /** + * This method is called when a resize is toggled. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handler up and + * left key presses. + */ + protected class KeyboardUpLeftHandler implements ActionListener + { + /** + * This method is called when the left or up keys are pressed. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This helper class handles PropertyChangeEvents from the JSplitPane. When + * a property changes, this will update the UI accordingly. + */ + protected class PropertyHandler implements PropertyChangeListener + { + /** + * This method is called whenever one of the JSplitPane's properties + * change. + * + * @param e DOCUMENT ME! + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JSplitPane.DIVIDER_SIZE_PROPERTY)) + { + int newSize = splitPane.getDividerSize(); + int[] tmpSizes = layoutManager.getSizes(); + dividerSize = tmpSizes[2]; + Component left = splitPane.getLeftComponent(); + Component right = splitPane.getRightComponent(); + int newSpace = newSize - tmpSizes[2]; + + tmpSizes[2] = newSize; + + tmpSizes[0] += newSpace / 2; + tmpSizes[1] += newSpace / 2; + + layoutManager.setSizes(tmpSizes); + } + else if (e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY)) + { + int max = layoutManager.getAvailableSize(splitPane.getSize(), + splitPane.getInsets()); + int dividerLoc = getDividerLocation(splitPane); + double prop = ((double) dividerLoc) / max; + + resetLayoutManager(); + if (prop <= 1 && prop >= 0) + splitPane.setDividerLocation(prop); + } + layoutManager.layoutContainer(splitPane); + splitPane.repaint(); + // Don't have to deal with continuous_layout - only + // necessary in dragging modes (and it's checked + // every time you drag there) + // Don't have to deal with resize_weight (as there + // will be no extra space associated with this + // event - the changes to the weighting will + // be taken into account the next time the + // sizes change.) + // Don't have to deal with divider_location + // The method in JSplitPane calls our setDividerLocation + // so we'll know about those anyway. + // Don't have to deal with last_divider_location + // Although I'm not sure why, it doesn't seem to + // have any effect on Sun's JSplitPane. + // one_touch_expandable changes are dealt with + // by our divider. + } + } + + /** The location of the divider when dragging began. */ + protected int beginDragDividerLocation; + + /** The size of the divider while dragging. */ + protected int dividerSize; + + /** The location where the last drag location ended. */ + transient int lastDragLocation = -1; + + /** The distance the divider is moved when moved by keyboard actions. */ protected static int KEYBOARD_DIVIDER_MOVE_OFFSET; - protected JSplitPane splitPane; + /** The divider that divides this JSplitPane. */ protected BasicSplitPaneDivider divider; + + /** The listener that listens for PropertyChangeEvents from the JSplitPane. */ protected PropertyChangeListener propertyChangeListener; + + /** The JSplitPane's focus handler. */ protected FocusListener focusListener; - protected int dividerSize; - protected Component nonContinuousLayoutDivider; - protected boolean draggingHW; - protected int beginDragDividerLocation; - protected KeyStroke upKey; - protected KeyStroke downKey; - protected KeyStroke leftKey; - protected KeyStroke rightKey; - protected KeyStroke homeKey; - protected KeyStroke endKey; - protected KeyStroke dividerResizeToggleKey; - protected ActionListener keyboardUpLeftListener; + + /** Deprecated. The handler for down and right key presses. */ protected ActionListener keyboardDownRightListener; - protected ActionListener keyboardHomeListener; + + /** Deprecated. The handler for end key presses. */ protected ActionListener keyboardEndListener; + + /** Deprecated. The handler for home key presses. */ + protected ActionListener keyboardHomeListener; + + /** Deprecated. The handler for toggling resizes. */ protected ActionListener keyboardResizeToggleListener; - public static ComponentUI createUI(JComponent c) - { - BasicSplitPaneUI newUI; + /** Deprecated. The handler for up and left key presses. */ + protected ActionListener keyboardUpLeftListener; - newUI = new BasicSplitPaneUI(); - newUI.installUI(c); - return newUI; - } + /** The JSplitPane's current layout manager. */ + protected BasicHorizontalLayoutManager layoutManager; + + /** Deprecated. The divider resize toggle key. */ + protected KeyStroke dividerResizeToggleKey; + + /** Deprecated. The down key. */ + protected KeyStroke downKey; + + /** Deprecated. The end key. */ + protected KeyStroke endKey; + + /** Deprecated. The home key. */ + protected KeyStroke homeKey; + + /** Deprecated. The left key. */ + protected KeyStroke leftKey; + + /** Deprecated. The right key. */ + protected KeyStroke rightKey; + + /** Deprecated. The up key. */ + protected KeyStroke upKey; + + /** Set to true when dragging heavy weight components. */ + protected boolean draggingHW; + + /** + * The constraints object used when adding the non-continuous divider to the + * JSplitPane. + */ + protected static String NON_CONTINUOUS_DIVIDER; + + /** The dark divider used when dragging in non-continuous layout mode. */ + protected Component nonContinuousLayoutDivider; + + /** The JSplitPane that this UI draws. */ + protected JSplitPane splitPane; + /** + * Creates a new BasicSplitPaneUI object. + */ public BasicSplitPaneUI() { - propertyChangeListener = createPropertyChangeListener(); - focusListener = createFocusListener(); } - public void installUI(JComponent c) + /** + * This method creates a new BasicSplitPaneUI for the given JComponent. + * + * @param x The JComponent to create a UI for. + * + * @return A new BasicSplitPaneUI. + */ + public static ComponentUI createUI(JComponent x) { + return new BasicSplitPaneUI(); } - protected void installDefaults() + /** + * This method installs the BasicSplitPaneUI for the given JComponent. + * + * @param c The JComponent to install the UI for. + */ + public void installUI(JComponent c) { + if (c instanceof JSplitPane) + { + splitPane = (JSplitPane) c; + installDefaults(); + installListeners(); + installKeyboardActions(); + } } - protected void installListeners() + /** + * This method uninstalls the BasicSplitPaneUI for the given JComponent. + * + * @param c The JComponent to uninstall the UI for. + */ + public void uninstallUI(JComponent c) { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallDefaults(); + + splitPane = null; } - protected void installKeyboardListeners() + /** + * This method installs the defaults given by the Look and Feel. + */ + protected void installDefaults() { + resetLayoutManager(); + divider = createDefaultDivider(); + nonContinuousLayoutDivider = createDefaultNonContinuousLayoutDivider(); + splitPane.add(divider, JSplitPane.DIVIDER); + + // There is no need to add the nonContinuousLayoutDivider + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + splitPane.setBackground(defaults.getColor("SplitPane.background")); + splitPane.setBorder(defaults.getBorder("SplitPane.border")); + splitPane.setDividerSize(defaults.getInt("SplitPane.dividerSize")); } - protected void installKeyboardActions() + /** + * This method uninstalls the defaults and nulls any objects created during + * install. + */ + protected void uninstallDefaults() { + layoutManager = null; + splitPane.remove(divider); + divider = null; + nonContinuousLayoutDivider = null; + + splitPane.setBackground(null); + splitPane.setBorder(null); } - public void uninstallUI(JComponent c) + /** + * This method installs the listeners needed for this UI to function. + */ + protected void installListeners() { + propertyChangeListener = createPropertyChangeListener(); + focusListener = createFocusListener(); + + splitPane.addPropertyChangeListener(propertyChangeListener); + splitPane.addFocusListener(focusListener); } - protected void uninstallDefaults() + /** + * This method uninstalls all listeners registered for the UI. + */ + protected void uninstallListeners() { + splitPane.removePropertyChangeListener(propertyChangeListener); + splitPane.removeFocusListener(focusListener); + + focusListener = null; + propertyChangeListener = null; } - protected void uninstallListeners() + /** + * This method installs the keyboard actions for the JSplitPane. + */ + protected void installKeyboardActions() { + // FIXME: implement. } + /** + * This method reverses the work done in installKeyboardActions. + */ protected void uninstallKeyboardActions() { + // FIXME: implement. } + /** + * This method creates a new PropertyChangeListener. + * + * @return A new PropertyChangeListener. + */ protected PropertyChangeListener createPropertyChangeListener() { - return null; + return new PropertyHandler(); } + /** + * This method creates a new FocusListener. + * + * @return A new FocusListener. + */ protected FocusListener createFocusListener() { - return null; + return new FocusHandler(); } + /** + * Deprecated. This method creates a new ActionListener for up and left key + * presses. + * + * @return A new ActionListener for up and left keys. + */ protected ActionListener createKeyboardUpLeftListener() { - return null; + return new KeyboardUpLeftHandler(); } + /** + * Deprecated. This method creates a new ActionListener for down and right + * key presses. + * + * @return A new ActionListener for down and right keys. + */ protected ActionListener createKeyboardDownRightListener() { - return null; + return new KeyboardDownRightHandler(); } + /** + * Deprecated. This method creates a new ActionListener for home key + * presses. + * + * @return A new ActionListener for home keys. + */ protected ActionListener createKeyboardHomeListener() { - return null; + return new KeyboardHomeHandler(); } + /** + * Deprecated. This method creates a new ActionListener for end key presses. + * + * @return A new ActionListener for end keys. + */ protected ActionListener createKeyboardEndListener() { - return null; + return new KeyboardEndHandler(); } + /** + * Depcreated. This method creates a new ActionListener for resize toggle + * key events. + * + * @return A new ActionListener for resize toggle keys. + */ protected ActionListener createKeyboardResizeToggleListener() { - return null; + return new KeyboardResizeToggleHandler(); } + /** + * This method returns the orientation of the JSplitPane. + * + * @return The orientation of the JSplitPane. + */ public int getOrientation() { return splitPane.getOrientation(); } + /** + * This method sets the orientation of the JSplitPane. + * + * @param orientation The new orientation of the JSplitPane. + */ public void setOrientation(int orientation) { + splitPane.setOrientation(orientation); } - + /** + * This method returns true if the JSplitPane is using continuous layout. + * + * @return True if the JSplitPane is using continuous layout. + */ public boolean isContinuousLayout() { - return false; + return splitPane.isContinuousLayout(); } + /** + * This method sets the continuous layout property of the JSplitPane. + * + * @param b True if the JsplitPane is to use continuous layout. + */ public void setContinuousLayout(boolean b) { + splitPane.setContinuousLayout(b); } + /** + * This method returns the last location the divider was dragged to. + * + * @return The last location the divider was dragged to. + */ public int getLastDragLocation() { - return 0; + return lastDragLocation; } + /** + * This method sets the last location the divider was dragged to. + * + * @param l The last location the divider was dragged to. + */ public void setLastDragLocation(int l) { + lastDragLocation = l; } - + /** + * This method returns the BasicSplitPaneDivider that divides this + * JSplitPane. + * + * @return The divider for the JSplitPane. + */ public BasicSplitPaneDivider getDivider() { return divider; } - + /** + * This method creates a nonContinuousLayoutDivider for use with the + * JSplitPane in nonContinousLayout mode. The default divider is a gray + * Canvas. + * + * @return The default nonContinousLayoutDivider. + */ protected Component createDefaultNonContinuousLayoutDivider() { - return null; + if (nonContinuousLayoutDivider == null) + { + nonContinuousLayoutDivider = new Canvas(); + nonContinuousLayoutDivider.setBackground(Color.DARK_GRAY); + } + return nonContinuousLayoutDivider; } + /** + * This method sets the component to use as the nonContinuousLayoutDivider. + * + * @param newDivider The component to use as the nonContinuousLayoutDivider. + */ protected void setNonContinuousLayoutDivider(Component newDivider) { - setNonContinuousLayoutDivider(newDivider, true /* false? */); + setNonContinuousLayoutDivider(newDivider, true); } + /** + * This method sets the component to use as the nonContinuousLayoutDivider. + * + * @param newDivider The component to use as the nonContinuousLayoutDivider. + * @param rememberSizes FIXME: document. + */ protected void setNonContinuousLayoutDivider(Component newDivider, boolean rememberSizes) { + // FIXME: use rememberSizes for something nonContinuousLayoutDivider = newDivider; } + /** + * This method returns the nonContinuousLayoutDivider. + * + * @return The nonContinuousLayoutDivider. + */ public Component getNonContinuousLayoutDivider() { return nonContinuousLayoutDivider; } + /** + * This method returns the JSplitPane that this BasicSplitPaneUI draws. + * + * @return The JSplitPane. + */ public JSplitPane getSplitPane() { return splitPane; } + /** + * This method creates the divider used normally with the JSplitPane. + * + * @return The default divider. + */ public BasicSplitPaneDivider createDefaultDivider() { - return null; + if (divider == null) + divider = new BasicSplitPaneDivider(this); + return divider; } + /** + * This method is called when JSplitPane's resetToPreferredSizes is called. + * It resets the sizes of all components in the JSplitPane. + * + * @param jc The JSplitPane to reset. + */ public void resetToPreferredSizes(JSplitPane jc) { + layoutManager.resetToPreferredSizes(); } + /** + * This method sets the location of the divider. + * + * @param jc The JSplitPane to set the divider location in. + * @param location The new location of the divider. + */ public void setDividerLocation(JSplitPane jc, int location) { + setLastDragLocation(getDividerLocation(splitPane)); + splitPane.setLastDividerLocation(getDividerLocation(splitPane)); + int[] tmpSizes = layoutManager.getSizes(); + tmpSizes[0] = location + - layoutManager.getInitialLocation(splitPane.getInsets()); + tmpSizes[1] = layoutManager.getAvailableSize(splitPane.getSize(), + splitPane.getInsets()) + - tmpSizes[0] - tmpSizes[1]; + Point p = divider.getLocation(); + +// if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) + // setLastDragLocation(p.x); +// else +// setLastDragLocation(p.y); + layoutManager.setSizes(tmpSizes); + layoutManager.layoutContainer(splitPane); + + splitPane.repaint(); } + /** + * This method returns the location of the divider. + * + * @param jc The JSplitPane to retrieve the location for. + * + * @return The location of the divider. + */ public int getDividerLocation(JSplitPane jc) { - return 0; + return layoutManager.sizes[0] + + layoutManager.getInitialLocation(splitPane.getInsets()); } + /** + * This method returns the smallest value possible for the location of the + * divider. + * + * @param jc The JSplitPane. + * + * @return The minimum divider location. + */ public int getMinimumDividerLocation(JSplitPane jc) { - return 0; + int value = layoutManager.getInitialLocation(jc.getInsets()); + if (layoutManager.components[0] != null) + value += layoutManager.minimumSizeOfComponent(0); + return value; } + /** + * This method returns the largest value possible for the location of the + * divider. + * + * @param jc The JSplitPane. + * + * @return The maximum divider location. + */ public int getMaximumDividerLocation(JSplitPane jc) { - return 0; + int value = layoutManager.getInitialLocation(jc.getInsets()) + + layoutManager.getAvailableSize(jc.getSize(), jc.getInsets()) + - splitPane.getDividerSize(); + if (layoutManager.components[1] != null) + value -= layoutManager.minimumSizeOfComponent(1); + return value; } + /** + * This method is called after the children of the JSplitPane are painted. + * + * @param jc The JSplitPane. + * @param g The Graphics object to paint with. + */ public void finishedPaintingChildren(JSplitPane jc, Graphics g) { + if (! splitPane.isContinuousLayout() && nonContinuousLayoutDivider != null + && nonContinuousLayoutDivider.isVisible()) + javax.swing.SwingUtilities.paintComponent(g, nonContinuousLayoutDivider, + null, + nonContinuousLayoutDivider + .getBounds()); } + /** + * This method is called to paint the JSplitPane. + * + * @param g The Graphics object to paint with. + * @param jc The JSplitPane to paint. + */ public void paint(Graphics g, JComponent jc) { + // Do nothing. All the painting is handled by children. } + /** + * This method returns the preferred size of the JSplitPane. + * + * @param jc The JSplitPane. + * + * @return The preferred size of the JSplitPane. + */ public Dimension getPreferredSize(JComponent jc) { - return null; + return layoutManager.preferredLayoutSize((Container) jc); } + /** + * This method returns the minimum size of the JSplitPane. + * + * @param jc The JSplitPane. + * + * @return The minimum size of the JSplitPane. + */ public Dimension getMinimumSize(JComponent jc) { - return null; + return layoutManager.minimumLayoutSize((Container) jc); } + /** + * This method returns the maximum size of the JSplitPane. + * + * @param jc The JSplitPane. + * + * @return The maximum size of the JSplitPane. + */ public Dimension getMaximumSize(JComponent jc) { - return null; + return layoutManager.maximumLayoutSize((Container) jc); } + /** + * This method returns the border insets of the current border. + * + * @param jc The JSplitPane. + * + * @return The current border insets. + */ public Insets getInsets(JComponent jc) { - return new Insets(0, 0, 0, 0); + return splitPane.getBorder().getBorderInsets(splitPane); } + /** + * This method resets the current layout manager. The type of layout manager + * is dependent on the current orientation. + */ protected void resetLayoutManager() { + if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) + layoutManager = new BasicHorizontalLayoutManager(); + else + layoutManager = new BasicVerticalLayoutManager(); + layoutManager.invalidateLayout(splitPane); + layoutManager.updateComponents(); + getSplitPane().setLayout(layoutManager); + + // invalidating by itself does not invalidate the layout. + getSplitPane().invalidate(); } + /** + * This method is called when dragging starts. It resets lastDragLocation + * and dividerSize. + */ protected void startDragging() { + dividerSize = divider.getDividerSize(); + setLastDragLocation(-1); + + if (! splitPane.getLeftComponent().isLightweight() + || ! splitPane.getRightComponent().isLightweight()) + draggingHW = true; + + if (splitPane.isContinuousLayout()) + nonContinuousLayoutDivider.setVisible(false); + else + { + nonContinuousLayoutDivider.setVisible(true); + nonContinuousLayoutDivider.setBounds(divider.getBounds()); + } + splitPane.invalidate(); + splitPane.repaint(); } + /** + * This method is called whenever the divider is dragged. If the JSplitPane + * is in continuousLayout mode, the divider needs to be moved and the + * JSplitPane needs to be laid out. + * + * @param location The new location of the divider. + */ protected void dragDividerTo(int location) { + location = validLocation(location); + if (beginDragDividerLocation == -1) + beginDragDividerLocation = location; + + if (splitPane.isContinuousLayout()) + splitPane.setDividerLocation(location); + else + { + Point p = nonContinuousLayoutDivider.getLocation(); + if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) + p.x = location; + else + p.y = location; + nonContinuousLayoutDivider.setLocation(p); + } + setLastDragLocation(location); + splitPane.repaint(); } + /** + * This method is called when the dragging is finished. + * + * @param location The location where the drag finished. + */ protected void finishDraggingTo(int location) { + if (nonContinuousLayoutDivider != null) + nonContinuousLayoutDivider.setVisible(false); + draggingHW = false; + location = validLocation(location); + dragDividerTo(location); + splitPane.setDividerLocation(location); + splitPane.setLastDividerLocation(beginDragDividerLocation); + beginDragDividerLocation = -1; + splitPane.repaint(); } + /** + * Deprecated. This method returns the width of one of the sides of the + * divider's border. + * + * @return The width of one side of the divider's border. + */ protected int getDividerBorderSize() { - return 0; + if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) + return divider.getBorder().getBorderInsets(divider).left; + else + return divider.getBorder().getBorderInsets(divider).top; + } + + /** + * This is a helper method that returns a valid location for the divider + * when dragging. + * + * @param location The location to check. + * + * @return A valid location. + */ + private int validLocation(int location) + { + if (location < getMinimumDividerLocation(splitPane)) + return getMinimumDividerLocation(splitPane); + if (location > getMaximumDividerLocation(splitPane)) + return getMaximumDividerLocation(splitPane); + return location; } } diff --git a/libjava/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/libjava/javax/swing/plaf/basic/BasicTabbedPaneUI.java index 4dcec822537..a0100558be5 100644 --- a/libjava/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/libjava/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -223,10 +223,11 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { Component visible = getVisibleComponent(); Insets insets = getContentBorderInsets(tabPane.getTabPlacement()); - visible.setBounds(contentRect.x + insets.left, - contentRect.y + insets.top, - contentRect.width - insets.left - insets.right, - contentRect.height - insets.top - insets.bottom); + if (visible != null) + visible.setBounds(contentRect.x + insets.left, + contentRect.y + insets.top, + contentRect.width - insets.left - insets.right, + contentRect.height - insets.top - insets.bottom); } } @@ -1510,6 +1511,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants tabPane.setFont(defaults.getFont("TabbedPane.font")); tabPane.setForeground(defaults.getColor("TabbedPane.foreground")); tabPane.setBackground(defaults.getColor("TabbedPane.background")); + tabPane.setOpaque(true); highlight = defaults.getColor("TabbedPane.highlight"); lightHighlight = defaults.getColor("TabbedPane.lightHighlight"); @@ -1790,7 +1792,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants // FIXME: Paint little folding corner and jagged edge clipped tab. if (icon != null) paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected); - if (title == null || ! title.equals("")) + if (title != null && ! title.equals("")) paintText(g, tabPlacement, tabPane.getFont(), fm, tabIndex, title, textRect, isSelected); } diff --git a/libjava/javax/swing/plaf/basic/BasicViewportUI.java b/libjava/javax/swing/plaf/basic/BasicViewportUI.java index 463865c5be9..c1adad1853c 100644 --- a/libjava/javax/swing/plaf/basic/BasicViewportUI.java +++ b/libjava/javax/swing/plaf/basic/BasicViewportUI.java @@ -47,6 +47,7 @@ import java.awt.Rectangle; import java.awt.image.ImageObserver; import javax.swing.JComponent; import javax.swing.JViewport; +import javax.swing.ViewportLayout; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.ComponentUI; @@ -70,7 +71,8 @@ public class BasicViewportUI extends ViewportUI } void installDefaults(JComponent c) - { + { + c.setOpaque(true); } void uninstallDefaults(JComponent c) @@ -100,6 +102,7 @@ public class BasicViewportUI extends ViewportUI public void installUI(JComponent c) { super.installUI(c); + c.setLayout(new ViewportLayout()); installListeners(c); } @@ -111,9 +114,8 @@ public class BasicViewportUI extends ViewportUI public Dimension getPreferredSize(JComponent c) { - // FIXME: integrate with Scrollable - Dimension d = new Dimension(100,100); - return d; + // let the ViewportLayout decide + return null; } public void paint(Graphics g, JComponent c) @@ -129,6 +131,12 @@ public class BasicViewportUI extends ViewportUI Rectangle viewBounds = view.getBounds(); Rectangle portBounds = v.getBounds(); + if (viewBounds.width == 0 + || viewBounds.height == 0 + || portBounds.width == 0 + || portBounds.height == 0) + return; + if (backingStoreImage == null || backingStoreWidth != viewBounds.width || backingStoreHeight != viewBounds.height) diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c index afb705bf6e1..a56e7d27d5b 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c @@ -112,9 +112,10 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkClasspathFontPeer_setFont struct peerfont *pfont = NULL; PangoFontMap *map = NULL; char const *family_name = NULL; + enum java_awt_font_style style; gdk_threads_enter (); - enum java_awt_font_style style = (enum java_awt_font_style) style_int; + style = (enum java_awt_font_style) style_int; g_assert (self != NULL); pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self); diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c index b05d76ecb53..5e8562455a4 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c @@ -636,9 +636,12 @@ JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphIsHori gdk_threads_leave (); - return + return 1; + /* FIXME: Pango doesn't seem to have decided how it will deal + with vertical text. for the time being we inherit this limitation. ((dir == PANGO_DIRECTION_LTR) || (dir == PANGO_DIRECTION_RTL)); + */ } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c index a161ba49992..733461dcfc1 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c @@ -67,7 +67,9 @@ struct state_table *native_graphics2d_state_table; JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initStaticState (JNIEnv *env, jclass clazz) { - NSA_G2D_INIT (env, clazz); + gdk_threads_enter(); + NSA_G2D_INIT (env, clazz); + gdk_threads_leave(); } /* these public final constants are part of the java2d public API, so we @@ -124,6 +126,32 @@ enum java_awt_rendering_hints_filter }; +static int +peer_is_disposed(JNIEnv *env, jobject obj) +{ + static jfieldID fid = NULL; + jclass cls; + jobject peer; + + return 0; + + if (fid == NULL) + { + cls = (*env)->GetObjectClass(env, obj); + fid = (*env)->GetFieldID(env, cls, "component", + "Lgnu/java/awt/peer/gtk/GtkComponentPeer;"); + } + g_assert(fid != NULL); + peer = (*env)->GetObjectField(env, obj, fid); + if (peer == NULL || NSA_GET_PTR (env, peer) != NULL) + return 0; + else + { + return 1; + } +} + + static void grab_current_drawable (GtkWidget *widget, GdkDrawable **draw, GdkWindow **win) { @@ -220,7 +248,7 @@ init_graphics2d_as_renderable (struct graphics2d *gr) static void begin_drawing_operation (struct graphics2d * gr) { - gdk_threads_enter (); + g_assert(cairo_status (gr->cr) == CAIRO_STATUS_SUCCESS); if (gr->drawbuf) { @@ -248,6 +276,7 @@ begin_drawing_operation (struct graphics2d * gr) static void end_drawing_operation (struct graphics2d * gr) { + g_assert(cairo_status (gr->cr) == CAIRO_STATUS_SUCCESS); if (gr->drawbuf) { gint drawable_width, drawable_height; @@ -268,7 +297,6 @@ end_drawing_operation (struct graphics2d * gr) if (gr->debug) printf ("copied (%d, %d) pixels from pixbuf to GDK drawable\n", width, height); } - gdk_threads_leave (); } @@ -288,7 +316,7 @@ update_pattern_transform (struct graphics2d *gr) mat = cairo_matrix_create (); g_assert (mat != NULL); cairo_matrix_set_affine (mat, a, b, c, d, tx, ty); - cairo_surface_set_matrix (gr->pattern, mat); + cairo_pattern_set_matrix (gr->pattern, mat); cairo_matrix_destroy (mat); } @@ -303,6 +331,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState { struct graphics2d *g = NULL, *g_old = NULL; + gdk_threads_enter(); g = (struct graphics2d *) malloc (sizeof (struct graphics2d)); g_assert (g != NULL); memset (g, 0, sizeof(struct graphics2d)); @@ -315,7 +344,6 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState g->drawable = g_old->drawable; g->debug = g_old->debug; - gdk_threads_enter (); g_object_ref (g->drawable); g->cr = cairo_create(); @@ -328,9 +356,8 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState cairo_surface_set_filter (g->surface, CAIRO_FILTER_FAST); - gdk_threads_leave (); - NSA_SET_G2D_PTR (env, obj, g); + gdk_threads_leave(); } @@ -338,9 +365,8 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__II (JNIEnv *env, jobject obj, jint width, jint height) { struct graphics2d *gr; - - gdk_threads_enter (); + gdk_threads_enter(); gr = (struct graphics2d *) malloc (sizeof (struct graphics2d)); g_assert (gr != NULL); memset (gr, 0, sizeof(struct graphics2d)); @@ -362,22 +388,23 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__II else init_graphics2d_as_pixbuf (gr); - gdk_threads_leave (); if (gr->debug) printf ("constructed offscreen drawable of size (%d,%d)\n", width, height); NSA_SET_G2D_PTR (env, obj, gr); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable (JNIEnv *env, jobject self, jobject other, jint x, jint y) { - GdkRectangle clipRect; struct graphics2d *src = NULL, *dst = NULL; gint s_height, s_width, d_height, d_width, height, width; cairo_matrix_t *matrix; GdkGC *gc; cairo_operator_t tmp_op; + gdk_threads_enter(); + if (peer_is_disposed(env, self)) { gdk_threads_leave(); return; } src = (struct graphics2d *)NSA_GET_G2D_PTR (env, other); dst = (struct graphics2d *)NSA_GET_G2D_PTR (env, self); g_assert (src != NULL); @@ -385,14 +412,14 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable if (src->debug) printf ("copying from offscreen drawable\n"); - gdk_threads_enter (); + begin_drawing_operation(dst); + + gdk_flush(); + gdk_drawable_get_size (src->drawable, &s_width, &s_height); gdk_drawable_get_size (dst->drawable, &d_width, &d_height); width = min (s_width, d_width); height = min (s_height, d_height); - gdk_threads_leave (); - - begin_drawing_operation(dst); matrix = cairo_matrix_create (); cairo_surface_get_matrix (src->surface, matrix); @@ -408,14 +435,12 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable cairo_surface_set_matrix (src->surface, matrix); cairo_matrix_destroy (matrix); - end_drawing_operation(dst); + gdk_flush(); - gdk_threads_enter (); - gdk_flush (); - gdk_threads_leave (); + end_drawing_operation(dst); if (src->debug) printf ("copied %d x %d pixels from offscreen drawable\n", width, height); - + gdk_threads_leave(); } static jintArray @@ -454,9 +479,10 @@ JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__ void *ptr = NULL; jintArray color; + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } ptr = NSA_GET_PTR (env, peer); g_assert (ptr != NULL); - gdk_threads_enter (); gr = (struct graphics2d *) malloc (sizeof (struct graphics2d)); g_assert (gr != NULL); @@ -480,8 +506,8 @@ JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__ color = current_colors_of_widget (widget, env); - gdk_threads_leave (); NSA_SET_G2D_PTR (env, obj, gr); + gdk_threads_leave(); return color; } @@ -490,11 +516,13 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose { struct graphics2d *gr = NULL; + gdk_threads_enter(); gr = (struct graphics2d *) NSA_DEL_G2D_PTR (env, obj); if (gr == NULL) - return; /* dispose has been called more than once */ - - gdk_threads_enter (); + { + gdk_threads_leave(); + return; /* dispose has been called more than once */ + } if (gr->surface) cairo_surface_destroy (gr->surface); @@ -507,15 +535,18 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose g_object_unref (gr->drawable); if (gr->pattern) - cairo_surface_destroy (gr->pattern); + cairo_pattern_destroy (gr->pattern); + + if (gr->pattern_surface) + cairo_surface_destroy (gr->pattern_surface); if (gr->pattern_pixels) free (gr->pattern_pixels); if (gr->debug) printf ("disposed of graphics2d\n"); - free (gr); - gdk_threads_leave (); + free (gr); + gdk_threads_leave(); } @@ -533,6 +564,8 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setGradient gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } if (gr->debug) printf ("setGradient (%f,%f) -> (%f,%f); (%d,%d,%d,%d) -> (%d,%d,%d,%d)\n", x1, y1, x2, y2, @@ -623,19 +656,21 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setGradient /* cairo_surface_set_repeat (surf, cyclic ? 1 : 0); */ if (gr->pattern) - cairo_surface_destroy (gr->pattern); + cairo_pattern_destroy (gr->pattern); + + if (gr->pattern_surface) + cairo_surface_destroy (gr->pattern_surface); if (gr->pattern_pixels) - { - free (gr->pattern_pixels); - gr->pattern_pixels = NULL; - } - - gr->pattern = surf; + free (gr->pattern_pixels); + + gr->pattern_pixels = NULL; + gr->pattern_surface = surf; + gr->pattern = cairo_pattern_create_for_surface(surf); cairo_restore (gr->cr); cairo_set_pattern (gr->cr, gr->pattern); - + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setTexturePixels @@ -644,6 +679,8 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setTexturePixels struct graphics2d *gr = NULL; jint *jpixels = NULL; + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); @@ -651,12 +688,16 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setTexturePixels (*env)->GetArrayLength (env, jarr), w, h, stride); if (gr->pattern) - cairo_surface_destroy (gr->pattern); + cairo_pattern_destroy (gr->pattern); + + if (gr->pattern_surface) + cairo_surface_destroy (gr->pattern_surface); if (gr->pattern_pixels) free (gr->pattern_pixels); gr->pattern = NULL; + gr->pattern_surface = NULL; gr->pattern_pixels = NULL; gr->pattern_pixels = (char *) malloc (h * stride * 4); @@ -667,13 +708,15 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setTexturePixels memcpy (gr->pattern_pixels, jpixels, h * stride * 4); (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0); - gr->pattern = cairo_surface_create_for_image (gr->pattern_pixels, - CAIRO_FORMAT_ARGB32, - w, h, stride * 4); + gr->pattern_surface = cairo_surface_create_for_image (gr->pattern_pixels, + CAIRO_FORMAT_ARGB32, + w, h, stride * 4); + g_assert (gr->pattern_surface != NULL); + cairo_surface_set_repeat (gr->pattern_surface, 1); + gr->pattern = cairo_pattern_create_for_surface (gr->pattern_surface); g_assert (gr->pattern != NULL); - cairo_surface_set_repeat (gr->pattern, 1); cairo_set_pattern (gr->cr, gr->pattern); - + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels @@ -684,6 +727,9 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels jint *native_pixels = NULL; jdouble *native_matrix = NULL; + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); @@ -716,10 +762,11 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels } end_drawing_operation (gr); - - (*env)->ReleaseIntArrayElements (env, java_pixels, native_pixels, 0); - (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); - + + (*env)->ReleaseIntArrayElements (env, java_pixels, native_pixels, 0); + (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); + + gdk_threads_leave(); } JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_getImagePixels @@ -735,6 +782,9 @@ JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_getImagePix gint total_channels = 4; jint i, px; + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); @@ -783,8 +833,8 @@ JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_getImagePix (jsize)0, (jsize) width*height, (jint*) native_pixels); + gdk_threads_leave(); return java_pixels; - } /* passthrough methods to cairo */ @@ -793,21 +843,31 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSave (JNIEnv *env, jobject obj) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_save\n"); cairo_save (gr->cr); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRestore (JNIEnv *env, jobject obj) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_restore\n"); cairo_restore (gr->cr); update_pattern_transform (gr); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix @@ -816,6 +876,9 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix struct graphics2d *gr = NULL; jdouble *native_matrix = NULL; + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); @@ -840,6 +903,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); update_pattern_transform (gr); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFont @@ -850,14 +914,15 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFont cairo_font_t *ft = NULL; FT_Face face = NULL; + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); g_assert (pfont != NULL); - gdk_threads_enter (); - face = pango_ft2_font_get_face (pfont->font); g_assert (face != NULL); @@ -873,8 +938,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFont (double)PANGO_SCALE); cairo_font_destroy (ft); - - gdk_threads_leave (); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoShowGlyphs @@ -887,6 +951,9 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoShowGlyphs jint i; jint ncodes, nposns; + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); @@ -921,12 +988,17 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoShowGlyphs end_drawing_operation (gr); free(glyphs); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetOperator (JNIEnv *env, jobject obj, jint op) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_set_operator %d\n", op); @@ -980,12 +1052,17 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetOperator cairo_set_operator (gr->cr, CAIRO_OPERATOR_XOR); break; } + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetRGBColor (JNIEnv *env, jobject obj, jdouble r, jdouble g, jdouble b) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); @@ -1000,22 +1077,33 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetRGBColor cairo_set_rgb_color (gr->cr, b, g, r); else cairo_set_rgb_color (gr->cr, r, g, b); + + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetAlpha (JNIEnv *env, jobject obj, jdouble a) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_set_alpha %f\n", a); cairo_set_alpha (gr->cr, a); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFillRule (JNIEnv *env, jobject obj, jint rule) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); if (gr->debug) printf ("cairo_set_fill_rule %d\n", rule); g_assert (gr != NULL); @@ -1028,22 +1116,32 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFillRule cairo_set_fill_rule (gr->cr, CAIRO_FILL_RULE_EVEN_ODD); break; } + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineWidth (JNIEnv *env, jobject obj, jdouble width) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_set_line_width %f\n", width); cairo_set_line_width (gr->cr, width); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineCap (JNIEnv *env, jobject obj, jint cap) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_set_line_cap %d\n", cap); @@ -1061,12 +1159,17 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineCap cairo_set_line_cap (gr->cr, CAIRO_LINE_CAP_SQUARE); break; } + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineJoin (JNIEnv *env, jobject obj, jint join) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_set_line_join %d\n", join); @@ -1084,6 +1187,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetLineJoin cairo_set_line_join (gr->cr, CAIRO_LINE_JOIN_BEVEL); break; } + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetDash @@ -1091,6 +1195,10 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetDash { struct graphics2d *gr = NULL; jdouble *dasharr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_set_dash\n"); @@ -1098,16 +1206,22 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetDash g_assert (dasharr != NULL); cairo_set_dash (gr->cr, dasharr, ndash, offset); (*env)->ReleaseDoubleArrayElements (env, dashes, dasharr, 0); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMiterLimit (JNIEnv *env, jobject obj, jdouble miter) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_set_miter_limit %f\n", miter); cairo_set_miter_limit (gr->cr, miter); + gdk_threads_leave(); } @@ -1115,132 +1229,197 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoNewPath (JNIEnv *env, jobject obj) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_new_path\n"); cairo_new_path (gr->cr); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoMoveTo (JNIEnv *env, jobject obj, jdouble x, jdouble y) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_move_to (%f, %f)\n", x, y); cairo_move_to (gr->cr, x, y); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoLineTo (JNIEnv *env, jobject obj, jdouble x, jdouble y) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_line_to (%f, %f)\n", x, y); cairo_line_to (gr->cr, x, y); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoCurveTo (JNIEnv *env, jobject obj, jdouble x1, jdouble y1, jdouble x2, jdouble y2, jdouble x3, jdouble y3) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_curve_to (%f, %f), (%f, %f), (%f, %f)\n", x1, y1, x2, y2, x3, y3); cairo_curve_to (gr->cr, x1, y1, x2, y2, x3, y3); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelMoveTo (JNIEnv *env, jobject obj, jdouble dx, jdouble dy) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_rel_move_to (%f, %f)\n", dx, dy); cairo_rel_move_to (gr->cr, dx, dy); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelLineTo (JNIEnv *env, jobject obj, jdouble dx, jdouble dy) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_rel_line_to (%f, %f)\n", dx, dy); cairo_rel_line_to (gr->cr, dx, dy); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRelCurveTo (JNIEnv *env, jobject obj, jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2, jdouble dx3, jdouble dy3) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_rel_curve_to (%f, %f), (%f, %f), (%f, %f)\n", dx1, dy1, dx2, dy2, dx3, dy3); cairo_rel_curve_to (gr->cr, dx1, dy1, dx2, dy2, dx3, dy3); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRectangle (JNIEnv *env, jobject obj, jdouble x, jdouble y, jdouble width, jdouble height) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_rectangle (%f, %f) (%f, %f)\n", x, y, width, height); cairo_rectangle (gr->cr, x, y, width, height); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClosePath (JNIEnv *env, jobject obj) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_close_path\n"); cairo_close_path (gr->cr); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoStroke (JNIEnv *env, jobject obj) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_stroke\n"); begin_drawing_operation (gr); cairo_stroke (gr->cr); end_drawing_operation (gr); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoFill (JNIEnv *env, jobject obj) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_fill\n"); begin_drawing_operation (gr); cairo_fill (gr->cr); end_drawing_operation (gr); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClip (JNIEnv *env, jobject obj) { struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_clip\n"); - cairo_init_clip (gr->cr); - cairo_clip (gr->cr); + begin_drawing_operation (gr); + cairo_init_clip (gr->cr); + cairo_clip (gr->cr); + end_drawing_operation (gr); + gdk_threads_leave(); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSurfaceSetFilter (JNIEnv *env, jobject obj, jint filter) { - struct graphics2d *gr = NULL; + + gdk_threads_enter(); + if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } + gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_surface_set_filter %d\n", filter); @@ -1262,4 +1441,5 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSurfaceSetF cairo_surface_set_filter (gr->surface, CAIRO_FILTER_BEST); break; } + gdk_threads_leave(); } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c index 7f5d44a2d7c..9877a45fe58 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c @@ -96,11 +96,14 @@ Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkSetLabel void *ptr; ptr = NSA_GET_PTR (env, obj); - label = gtk_bin_get_child (GTK_BIN(ptr)); + text = (*env)->GetStringUTFChars (env, jtext, NULL); gdk_threads_enter (); + + label = gtk_bin_get_child (GTK_BIN (ptr)); gtk_label_set_text (GTK_LABEL(label), text); + gdk_threads_leave (); (*env)->ReleaseStringUTFChars (env, jtext, text); @@ -112,22 +115,20 @@ Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkSetFont { const char *font_name; void *ptr; - GtkWidget *button; GtkWidget *label; PangoFontDescription *font_desc; ptr = NSA_GET_PTR (env, obj); - button = GTK_WIDGET (ptr); - label = gtk_bin_get_child (GTK_BIN(button)); - - if (!label) - return; - font_name = (*env)->GetStringUTFChars (env, name, NULL); gdk_threads_enter(); + label = gtk_bin_get_child (GTK_BIN (ptr)); + + if (!label) + return; + font_desc = pango_font_description_from_string (font_name); pango_font_description_set_size (font_desc, size * PANGO_SCALE); @@ -173,3 +174,18 @@ Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkWidgetSetForeground gdk_threads_leave (); } + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkActivate + (JNIEnv *env, jobject obj) +{ + void *ptr; + + ptr = NSA_GET_PTR (env, obj); + + gdk_threads_enter (); + + gtk_widget_activate (GTK_WIDGET (ptr)); + + gdk_threads_leave (); +} diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c index fecaff48243..e8a918f9666 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c @@ -39,9 +39,370 @@ exception statement from your version. */ #include "gtkpeer.h" #include "gnu_java_awt_peer_gtk_GtkComponentPeer.h" #include <gtk/gtkprivate.h> +#include <gdk/gdkkeysyms.h> static GtkWidget *find_fg_color_widget (GtkWidget *widget); static GtkWidget *find_bg_color_widget (GtkWidget *widget); +static gboolean focus_in_cb (GtkWidget *widget, + GdkEventFocus *event, + jobject peer); +static gboolean focus_out_cb (GtkWidget *widget, + GdkEventFocus *event, + jobject peer); +/* + * This method returns a GDK keyval that corresponds to one of the + * keysyms in the X keymap table. The return value is only used to + * determine the keyval's corresponding hardware keycode, and doesn't + * reflect an accurate translation of a Java virtual key value to a + * GDK keyval. + */ +#ifdef __GNUC__ +__inline +#endif +static guint +awt_keycode_to_keysym (jint keyCode, jint keyLocation) +{ + /* GDK_A through GDK_Z */ + if (keyCode >= VK_A && keyCode <= VK_Z) + return gdk_keyval_to_lower (keyCode); + + /* GDK_0 through GDK_9 */ + if (keyCode >= VK_0 && keyCode <= VK_9) + return keyCode; + + switch (keyCode) + { + case VK_ENTER: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Enter : GDK_Return; + case VK_BACK_SPACE: + return GDK_BackSpace; + case VK_TAB: + return GDK_Tab; + case VK_CANCEL: + return GDK_Cancel; + case VK_CLEAR: + return GDK_Clear; + case VK_SHIFT: + return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Shift_L : GDK_Shift_R; + case VK_CONTROL: + return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Control_L : GDK_Control_R; + case VK_ALT: + return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Alt_L : GDK_Alt_R; + case VK_PAUSE: + return GDK_Pause; + case VK_CAPS_LOCK: + return GDK_Caps_Lock; + case VK_ESCAPE: + return GDK_Escape; + case VK_SPACE: + return GDK_space; + case VK_PAGE_UP: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Page_Up : GDK_Page_Up; + case VK_PAGE_DOWN: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Page_Down : GDK_Page_Down; + case VK_END: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_End : GDK_End; + case VK_HOME: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Home : GDK_Home; + case VK_LEFT: + return GDK_Left; + case VK_UP: + return GDK_Up; + case VK_RIGHT: + return GDK_Right; + case VK_DOWN: + return GDK_Down; + case VK_COMMA: + return GDK_comma; + case VK_MINUS: + return GDK_minus; + case VK_PERIOD: + return GDK_period; + case VK_SLASH: + return GDK_slash; + /* + case VK_0: + case VK_1: + case VK_2: + case VK_3: + case VK_4: + case VK_5: + case VK_6: + case VK_7: + case VK_8: + case VK_9: + */ + case VK_SEMICOLON: + return GDK_semicolon; + case VK_EQUALS: + return GDK_equal; + /* + case VK_A: + case VK_B: + case VK_C: + case VK_D: + case VK_E: + case VK_F: + case VK_G: + case VK_H: + case VK_I: + case VK_J: + case VK_K: + case VK_L: + case VK_M: + case VK_N: + case VK_O: + case VK_P: + case VK_Q: + case VK_R: + case VK_S: + case VK_T: + case VK_U: + case VK_V: + case VK_W: + case VK_X: + case VK_Y: + case VK_Z: + */ + case VK_OPEN_BRACKET: + return GDK_bracketleft; + case VK_BACK_SLASH: + return GDK_backslash; + case VK_CLOSE_BRACKET: + return GDK_bracketright; + case VK_NUMPAD0: + return GDK_KP_0; + case VK_NUMPAD1: + return GDK_KP_1; + case VK_NUMPAD2: + return GDK_KP_2; + case VK_NUMPAD3: + return GDK_KP_3; + case VK_NUMPAD4: + return GDK_KP_4; + case VK_NUMPAD5: + return GDK_KP_5; + case VK_NUMPAD6: + return GDK_KP_6; + case VK_NUMPAD7: + return GDK_KP_7; + case VK_NUMPAD8: + return GDK_KP_8; + case VK_NUMPAD9: + return GDK_KP_9; + case VK_MULTIPLY: + return GDK_KP_Multiply; + case VK_ADD: + return GDK_KP_Add; + /* + case VK_SEPARATER: + */ + case VK_SEPARATOR: + return GDK_KP_Separator; + case VK_SUBTRACT: + return GDK_KP_Subtract; + case VK_DECIMAL: + return GDK_KP_Decimal; + case VK_DIVIDE: + return GDK_KP_Divide; + case VK_DELETE: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Delete : GDK_Delete; + case VK_NUM_LOCK: + return GDK_Num_Lock; + case VK_SCROLL_LOCK: + return GDK_Scroll_Lock; + case VK_F1: + return GDK_F1; + case VK_F2: + return GDK_F2; + case VK_F3: + return GDK_F3; + case VK_F4: + return GDK_F4; + case VK_F5: + return GDK_F5; + case VK_F6: + return GDK_F6; + case VK_F7: + return GDK_F7; + case VK_F8: + return GDK_F8; + case VK_F9: + return GDK_F9; + case VK_F10: + return GDK_F10; + case VK_F11: + return GDK_F11; + case VK_F12: + return GDK_F12; + case VK_F13: + return GDK_F13; + case VK_F14: + return GDK_F14; + case VK_F15: + return GDK_F15; + case VK_F16: + return GDK_F16; + case VK_F17: + return GDK_F17; + case VK_F18: + return GDK_F18; + case VK_F19: + return GDK_F19; + case VK_F20: + return GDK_F20; + case VK_F21: + return GDK_F21; + case VK_F22: + return GDK_F22; + case VK_F23: + return GDK_F23; + case VK_F24: + return GDK_F24; + case VK_PRINTSCREEN: + return GDK_Print; + case VK_INSERT: + return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Insert : GDK_Insert; + case VK_HELP: + return GDK_Help; + case VK_META: + return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Meta_L : GDK_Meta_R; + case VK_BACK_QUOTE: + return GDK_grave; + case VK_QUOTE: + return GDK_apostrophe; + case VK_KP_UP: + return GDK_KP_Up; + case VK_KP_DOWN: + return GDK_KP_Down; + case VK_KP_LEFT: + return GDK_KP_Left; + case VK_KP_RIGHT: + return GDK_KP_Right; + case VK_DEAD_GRAVE: + return GDK_dead_grave; + case VK_DEAD_ACUTE: + return GDK_dead_acute; + case VK_DEAD_CIRCUMFLEX: + return GDK_dead_circumflex; + case VK_DEAD_TILDE: + return GDK_dead_tilde; + case VK_DEAD_MACRON: + return GDK_dead_macron; + case VK_DEAD_BREVE: + return GDK_dead_breve; + case VK_DEAD_ABOVEDOT: + return GDK_dead_abovedot; + case VK_DEAD_DIAERESIS: + return GDK_dead_diaeresis; + case VK_DEAD_ABOVERING: + return GDK_dead_abovering; + case VK_DEAD_DOUBLEACUTE: + return GDK_dead_doubleacute; + case VK_DEAD_CARON: + return GDK_dead_caron; + case VK_DEAD_CEDILLA: + return GDK_dead_cedilla; + case VK_DEAD_OGONEK: + return GDK_dead_ogonek; + case VK_DEAD_IOTA: + return GDK_dead_iota; + case VK_DEAD_VOICED_SOUND: + return GDK_dead_voiced_sound; + case VK_DEAD_SEMIVOICED_SOUND: + return GDK_dead_semivoiced_sound; + case VK_AMPERSAND: + return GDK_ampersand; + case VK_ASTERISK: + return GDK_asterisk; + case VK_QUOTEDBL: + return GDK_quotedbl; + case VK_LESS: + return GDK_less; + case VK_GREATER: + return GDK_greater; + case VK_BRACELEFT: + return GDK_braceleft; + case VK_BRACERIGHT: + return GDK_braceright; + case VK_AT: + return GDK_at; + case VK_COLON: + return GDK_colon; + case VK_CIRCUMFLEX: + return GDK_asciicircum; + case VK_DOLLAR: + return GDK_dollar; + case VK_EURO_SIGN: + return GDK_EuroSign; + case VK_EXCLAMATION_MARK: + return GDK_exclam; + case VK_INVERTED_EXCLAMATION_MARK: + return GDK_exclamdown; + case VK_LEFT_PARENTHESIS: + return GDK_parenleft; + case VK_NUMBER_SIGN: + return GDK_numbersign; + case VK_PLUS: + return GDK_plus; + case VK_RIGHT_PARENTHESIS: + return GDK_parenright; + case VK_UNDERSCORE: + return GDK_underscore; + /* + case VK_FINAL: + case VK_CONVERT: + case VK_NONCONVERT: + case VK_ACCEPT: + */ + case VK_MODECHANGE: + return GDK_Mode_switch; + /* + case VK_KANA: + */ + case VK_KANJI: + return GDK_Kanji; + /* + case VK_ALPHANUMERIC: + */ + case VK_KATAKANA: + return GDK_Katakana; + case VK_HIRAGANA: + return GDK_Hiragana; + /* + case VK_FULL_WIDTH: + case VK_HALF_WIDTH: + case VK_ROMAN_CHARACTERS: + case VK_ALL_CANDIDATES: + */ + case VK_PREVIOUS_CANDIDATE: + return GDK_PreviousCandidate; + case VK_CODE_INPUT: + return GDK_Codeinput; + /* + case VK_JAPANESE_KATAKANA: + case VK_JAPANESE_HIRAGANA: + case VK_JAPANESE_ROMAN: + */ + case VK_KANA_LOCK: + return GDK_Kana_Lock; + /* + case VK_INPUT_METHOD_ON_OFF: + case VK_CUT: + case VK_COPY: + case VK_PASTE: + case VK_UNDO: + case VK_AGAIN: + case VK_FIND: + case VK_PROPS: + case VK_STOP: + case VK_COMPOSE: + case VK_ALT_GRAPH: + */ + default: + return GDK_VoidSymbol; + } +} JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursor @@ -110,6 +471,137 @@ Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursor gdk_threads_leave (); } +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus + (JNIEnv *env, jobject obj) +{ + void *ptr; + + ptr = NSA_GET_PTR (env, obj); + + gdk_threads_enter (); + gtk_widget_grab_focus (GTK_WIDGET (ptr)); + gdk_threads_leave (); +} + +/* + * Translate a Java KeyEvent object into a GdkEventKey event, then + * pass it to the GTK main loop for processing. + */ +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetDispatchKeyEvent + (JNIEnv *env, jobject obj, jint id, jlong when, jint mods, + jint keyCode, jint keyLocation) +{ + void *ptr; + GdkEvent *event = NULL; + GdkKeymapKey *keymap_keys = NULL; + gint n_keys = 0; + guint lookup_keyval = 0; + + ptr = NSA_GET_PTR (env, obj); + + gdk_threads_enter (); + + if (id == AWT_KEY_PRESSED) + event = gdk_event_new (GDK_KEY_PRESS); + else if (id == AWT_KEY_RELEASED) + event = gdk_event_new (GDK_KEY_RELEASE); + else + { + gdk_threads_leave (); + /* Don't send AWT KEY_TYPED events to GTK. */ + return; + } + + if (GTK_IS_BUTTON (ptr)) + event->key.window = GTK_BUTTON (ptr)->event_window; + else if (GTK_IS_SCROLLED_WINDOW (ptr)) + event->key.window = GTK_WIDGET (GTK_SCROLLED_WINDOW (ptr)->container.child)->window; + else + event->key.window = GTK_WIDGET (ptr)->window; + + event->key.send_event = 0; + event->key.time = (guint32) when; + + if (mods & AWT_SHIFT_MASK) + event->key.state |= GDK_SHIFT_MASK; + if (mods & AWT_CTRL_MASK) + event->key.state |= GDK_CONTROL_MASK; + if (mods & AWT_ALT_MASK) + event->key.state |= GDK_MOD1_MASK; + + /* This hack is needed because the AWT has no notion of num lock. + It infers numlock state from the only Java virtual keys that are + affected by it. */ + if (keyCode == VK_NUMPAD9 + || keyCode == VK_NUMPAD8 + || keyCode == VK_NUMPAD7 + || keyCode == VK_NUMPAD6 + || keyCode == VK_NUMPAD5 + || keyCode == VK_NUMPAD4 + || keyCode == VK_NUMPAD3 + || keyCode == VK_NUMPAD2 + || keyCode == VK_NUMPAD1 + || keyCode == VK_NUMPAD0 + || keyCode == VK_DECIMAL) + event->key.state |= GDK_MOD2_MASK; + + /* These values don't need to be filled in since GTK doesn't use + them. */ + event->key.length = 0; + event->key.string = NULL; + + lookup_keyval = awt_keycode_to_keysym (keyCode, keyLocation); + + if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), + lookup_keyval, + &keymap_keys, + &n_keys)) + { + /* No matching keymap entry was found. */ + g_printerr ("No matching keymap entries were found\n"); + gdk_threads_leave (); + return; + } + + if (n_keys > 1) + g_printerr ("warning: using hardware keycode from first keymap entry, though multiple entries were found\n"); + + event->key.hardware_keycode = keymap_keys[0].keycode; + event->key.group = keymap_keys[0].group; + + g_free (keymap_keys); + + if (!gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (), + event->key.hardware_keycode, + event->key.state, + event->key.group, + &event->key.keyval, + NULL, NULL, NULL)) + { + /* No matching keyval was found. */ + g_printerr ("No matching keyval was found\n"); + gdk_threads_leave (); + return; + } + + /* keyevent = (GdkEventKey *) event; */ + /* g_printerr ("generated event: sent: %d time: %d state: %d keyval: %d length: %d string: %s hardware_keycode: %d group: %d\n", keyevent->send_event, keyevent->time, keyevent->state, keyevent->keyval, keyevent->length, keyevent->string, keyevent->hardware_keycode, keyevent->group); */ + + /* We already received the original key event on the window itself, + so we don't want to resend it. */ + if (!GTK_IS_WINDOW (ptr)) + { + if (GTK_IS_SCROLLED_WINDOW (ptr)) + gtk_widget_event (GTK_WIDGET (GTK_SCROLLED_WINDOW (ptr)->container.child), event); + else + gtk_widget_event (GTK_WIDGET (ptr), event); + } + + gdk_threads_leave (); +} + /* * Find the origin of a widget's window. */ @@ -734,6 +1226,12 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignal g_signal_connect (GTK_OBJECT (ptr), "event", G_CALLBACK (pre_event_handler), *gref); + g_signal_connect (G_OBJECT (ptr), "focus-in-event", + G_CALLBACK (focus_in_cb), *gref); + + g_signal_connect (G_OBJECT (ptr), "focus-out-event", + G_CALLBACK (focus_out_cb), *gref); + gdk_threads_leave (); } @@ -772,3 +1270,26 @@ find_bg_color_widget (GtkWidget *widget) return bg_color_widget; } +static gboolean +focus_in_cb (GtkWidget *widget __attribute((unused)), + GdkEventFocus *event __attribute((unused)), + jobject peer) +{ + (*gdk_env)->CallVoidMethod (gdk_env, peer, + postFocusEventID, + AWT_FOCUS_GAINED, + JNI_FALSE); + return FALSE; +} + +static gboolean +focus_out_cb (GtkWidget *widget __attribute((unused)), + GdkEventFocus *event __attribute((unused)), + jobject peer) +{ + (*gdk_env)->CallVoidMethod (gdk_env, peer, + postFocusEventID, + AWT_FOCUS_LOST, + JNI_FALSE); + return FALSE; +} diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c index efee7c8f1a2..b3858fb3970 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c @@ -806,31 +806,6 @@ keyevent_to_awt_keychar (GdkEvent *event) } } -/* Checks if keyval triggers a KEY_TYPED event on the source widget. - This function identifies special keyvals that don't trigger - GtkIMContext "commit" signals, but that do trigger Java KEY_TYPED - events. */ -static int -generates_key_typed_event (GdkEvent *event, GtkWidget *source) -{ - guint keyval; - - if (!GTK_IS_ENTRY (source) - && !GTK_IS_TEXT_VIEW (source)) - return event->key.length ? 1 : 0; - - keyval = event->key.keyval; - - return (keyval == GDK_Escape - || keyval == GDK_BackSpace - || keyval == GDK_Delete - || keyval == GDK_KP_Delete - || keyval == GDK_Return - || keyval == GDK_KP_Enter - || (keyval == GDK_Tab - && GTK_IS_TEXT_VIEW(source))) ? 1 : 0; -} - void awt_event_handler (GdkEvent *event) { @@ -1055,104 +1030,53 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) } } break; + case GDK_FOCUS_CHANGE: (*gdk_env)->CallVoidMethod (gdk_env, peer, postFocusEventID, - (jint) (event->focus_change.in) ? + (jint) (event->focus_change.in) ? AWT_FOCUS_GAINED : AWT_FOCUS_LOST, JNI_FALSE); break; case GDK_KEY_PRESS: - case GDK_KEY_RELEASE: - { - GdkWindow *obj_window; - jobject *focus_obj_ptr = NULL; - int generates_key_typed = 0; - - /* A widget with a grab will get key events */ - if (!GTK_IS_WINDOW (widget)) - focus_obj_ptr = &peer; - else - { - GtkWindow *window; - - /* Check if we have an enabled focused widget in this window. - If not don't handle the event. */ - window = GTK_WINDOW (widget); - if (!window->focus_widget - || !GTK_WIDGET_IS_SENSITIVE (window->focus_widget) - || !window->focus_widget->window) - return FALSE; - - /* TextArea peers are attached to the scrolled window - that contains the GtkTextView, not to the text view - itself. Same for List. */ - if (GTK_IS_TEXT_VIEW (window->focus_widget) - || GTK_IS_CLIST (window->focus_widget)) - { - obj_window = gtk_widget_get_parent (window->focus_widget)->window; - } - else if (GTK_IS_BUTTON (window->focus_widget)) - /* GtkButton events go to the "event_window" and this is what - we registered when the button was created. */ - obj_window = GTK_BUTTON (window->focus_widget)->event_window; - else - obj_window = window->focus_widget->window; - - gdk_property_get (obj_window, - gdk_atom_intern ("_GNU_GTKAWT_ADDR", FALSE), - gdk_atom_intern ("CARDINAL", FALSE), - 0, - sizeof (jobject), - FALSE, - NULL, - NULL, - NULL, - (guchar **)&focus_obj_ptr); - - /* If the window has no jobject attached we can't send anything */ - if (!focus_obj_ptr) - return FALSE; - - /* Should we generate an AWT_KEY_TYPED event? */ - generates_key_typed = generates_key_typed_event (event, window->focus_widget); - } - - if (event->type == GDK_KEY_PRESS) - { - (*gdk_env)->CallVoidMethod (gdk_env, *focus_obj_ptr, - postKeyEventID, - (jint) AWT_KEY_PRESSED, - (jlong) event->key.time, + if (GTK_IS_WINDOW (widget)) + { + /* GdkEventKey *keyevent = (GdkEventKey *) event; */ + /* g_printerr ("key press event: sent: %d time: %d state: %d keyval: %d length: %d string: %s hardware_keycode: %d group: %d\n", keyevent->send_event, keyevent->time, keyevent->state, keyevent->keyval, keyevent->length, keyevent->string, keyevent->hardware_keycode, keyevent->group); */ + + (*gdk_env)->CallVoidMethod (gdk_env, peer, + postKeyEventID, + (jint) AWT_KEY_PRESSED, + (jlong) event->key.time, keyevent_state_to_awt_mods (event), keysym_to_awt_keycode (event), keyevent_to_awt_keychar (event), keysym_to_awt_keylocation (event)); - - if (generates_key_typed) - { - (*gdk_env)->CallVoidMethod (gdk_env, *focus_obj_ptr, - postKeyEventID, - (jint) AWT_KEY_TYPED, - (jlong) event->key.time, - state_to_awt_mods (event->key.state), - VK_UNDEFINED, - keyevent_to_awt_keychar (event), - AWT_KEY_LOCATION_UNKNOWN); - } + /* FIXME: generation of key typed events needs to be moved + to GtkComponentPeer.postKeyEvent. If the key in a key + press event is not an "action" key + (KeyEvent.isActionKey) and is not a modifier key, then + it should generate a key typed event. */ + return TRUE; } - else /* GDK_KEY_RELEASE */ - { - (*gdk_env)->CallVoidMethod (gdk_env, *focus_obj_ptr, - postKeyEventID, - (jint) AWT_KEY_RELEASED, - (jlong) event->key.time, - keyevent_state_to_awt_mods (event), - keysym_to_awt_keycode (event), + else + return FALSE; + break; + case GDK_KEY_RELEASE: + if (GTK_IS_WINDOW (widget)) + { + (*gdk_env)->CallVoidMethod (gdk_env, peer, + postKeyEventID, + (jint) AWT_KEY_RELEASED, + (jlong) event->key.time, + keyevent_state_to_awt_mods (event), + keysym_to_awt_keycode (event), keyevent_to_awt_keychar (event), keysym_to_awt_keylocation (event)); - } - } + return TRUE; + } + else + return FALSE; break; default: break; diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImagePainter.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImagePainter.c index f4e9c3599b3..13282e2be43 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImagePainter.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImagePainter.c @@ -58,6 +58,9 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImagePainter_drawPixels g = (struct graphics *) NSA_GET_PTR (env, gc_obj); + if (!jpixels) + return; + elems = (*env)->GetIntArrayElements (env, jpixels, NULL); num_pixels = (*env)->GetArrayLength (env, jpixels); diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c index 87ecafce991..9f8301bf7d5 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c @@ -1,76 +1,109 @@ /* gtklistpeer.c -- Native implementation of GtkListPeer Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - + This file is part of GNU Classpath. + + GNU Classpath is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU Classpath is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Classpath; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. */ #include "gtkpeer.h" -#include "gnu_java_awt_peer_gtk_GtkComponentPeer.h" #include "gnu_java_awt_peer_gtk_GtkListPeer.h" -static void item_select (GtkCList *list __attribute__((unused)), - int row, int col __attribute__((unused)), - GdkEventButton *event __attribute__((unused)), - jobject peer_obj); -static void item_unselect (GtkCList *list __attribute__((unused)), - int row, - int col __attribute__((unused)), - GdkEventButton *event __attribute__((unused)), - jobject peer_obj); +enum + { + COLUMN_STRING, + N_COLUMNS + }; -#define CLIST_FROM_SW(obj) (GTK_CLIST(GTK_SCROLLED_WINDOW (obj)->container.child)) +#define TREE_VIEW_FROM_SW(obj) \ + (GTK_TREE_VIEW (GTK_SCROLLED_WINDOW (obj)->container.child)) -JNIEXPORT void JNICALL +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkListPeer_create - (JNIEnv *env, jobject obj) + (JNIEnv *env, jobject obj, jint rows) { - GtkWidget *list, *sw; + GtkWidget *sw; + GtkWidget *list; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + GtkListStore *list_store; + GtkTreeIter iter; + GtkRequisition req; + gint i; /* Create global reference and save it for future use */ NSA_SET_GLOBAL_REF (env, obj); gdk_threads_enter (); - - list = gtk_clist_new (1); - gtk_widget_show (list); + + list_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING); + /* Add the number of rows so that we can calculate the tree view's + size request. */ + for (i = 0; i < rows; i++) + { + gtk_list_store_append (list_store, &iter); + gtk_list_store_set (list_store, &iter, + COLUMN_STRING, "", + -1); + } + list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store)); + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes (NULL, + renderer, + "text", + COLUMN_STRING, + NULL); + sw = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); + + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE); + + gtk_widget_size_request (GTK_WIDGET (list), &req); + + gtk_widget_set_size_request (GTK_WIDGET (list), req.width, req.height); + gtk_container_add (GTK_CONTAINER (sw), list); + /* Remove the blank rows. */ + gtk_list_store_clear (list_store); + + gtk_widget_show (list); + gtk_widget_show (sw); + gdk_threads_leave (); NSA_SET_PTR (env, obj, sw); @@ -87,7 +120,6 @@ Java_gnu_java_awt_peer_gtk_GtkListPeer_connectJObject gdk_threads_enter (); gtk_widget_realize (GTK_WIDGET (ptr)); - connect_awt_hook (env, obj, 1, GTK_WIDGET (ptr)->window); gdk_threads_leave (); @@ -97,50 +129,98 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkListPeer_connectSignals (JNIEnv *env, jobject obj) { - GtkCList *list; - void *ptr = NSA_GET_PTR (env, obj); - jobject *gref = NSA_GET_GLOBAL_REF (env, obj); + void *ptr; + GtkTreeView *list; + jobject *gref; + + gref = NSA_GET_GLOBAL_REF (env, obj); g_assert (gref); + ptr = NSA_GET_PTR (env, obj); + gdk_threads_enter (); gtk_widget_realize (GTK_WIDGET (ptr)); + list = TREE_VIEW_FROM_SW (ptr); + g_signal_connect (G_OBJECT (list), "event", + G_CALLBACK (pre_event_handler), *gref); - /* connect selectable hook */ - - list = CLIST_FROM_SW (ptr); + gdk_threads_leave (); +} - g_signal_connect (G_OBJECT (list), "select_row", - GTK_SIGNAL_FUNC (item_select), *gref); +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_gtkSetFont + (JNIEnv *env, jobject obj, jstring name, jint style, jint size) +{ + const char *font_name; + void *ptr; + GtkWidget *list; + PangoFontDescription *font_desc; - g_signal_connect (G_OBJECT (list), "unselect_row", - GTK_SIGNAL_FUNC (item_unselect), *gref); + ptr = NSA_GET_PTR (env, obj); - /* Connect the superclass signals. */ - /* FIXME: Cannot do that here or it will get the sw and not the list. - We must a generic way of doing this. */ - /* Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals (env, peer_obj); */ - g_signal_connect (GTK_OBJECT (list), "event", - G_CALLBACK (pre_event_handler), *gref); + gdk_threads_enter(); + + list = GTK_WIDGET (TREE_VIEW_FROM_SW (ptr)); + + font_name = (*env)->GetStringUTFChars (env, name, NULL); + + font_desc = pango_font_description_from_string (font_name); + pango_font_description_set_size (font_desc, size * PANGO_SCALE); + + if (style & AWT_STYLE_BOLD) + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); + + if (style & AWT_STYLE_ITALIC) + pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE); + + gtk_widget_modify_font (GTK_WIDGET (list), font_desc); + + pango_font_description_free (font_desc); + + (*env)->ReleaseStringUTFChars (env, name, font_name); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_gtkWidgetRequestFocus + (JNIEnv *env, jobject obj) +{ + void *ptr; + GtkWidget *list; + + ptr = NSA_GET_PTR (env, obj); + + gdk_threads_enter (); + + list = GTK_WIDGET (TREE_VIEW_FROM_SW (ptr)); + gtk_widget_grab_focus (list); gdk_threads_leave (); } -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkListPeer_append +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkListPeer_append (JNIEnv *env, jobject obj, jobjectArray items) { void *ptr; - GtkCList *list; - jint count, i; + GtkTreeView *list; + GtkTreeIter iter; + GtkTreeModel *list_store; + jint count; + jint i; ptr = NSA_GET_PTR (env, obj); count = (*env)->GetArrayLength (env, items); gdk_threads_enter (); - list = CLIST_FROM_SW (ptr); - for (i = 0; i < count; i++) + + list = TREE_VIEW_FROM_SW (ptr); + list_store = gtk_tree_view_get_model (list); + + for (i = 0; i < count; i++) { const char *text; jobject item; @@ -148,11 +228,13 @@ Java_gnu_java_awt_peer_gtk_GtkListPeer_append item = (*env)->GetObjectArrayElement (env, items, i); text = (*env)->GetStringUTFChars (env, item, NULL); - gtk_clist_append (list, (char **)&text); + gtk_list_store_append (GTK_LIST_STORE (list_store), &iter); + gtk_list_store_set (GTK_LIST_STORE (list_store), &iter, + COLUMN_STRING, text, + -1); (*env)->ReleaseStringUTFChars (env, item, text); } - gtk_clist_columns_autosize (list); gdk_threads_leave (); } @@ -162,12 +244,26 @@ Java_gnu_java_awt_peer_gtk_GtkListPeer_add { void *ptr; const char *str; - + GtkTreeView *list; + GtkTreeIter iter; + GtkTreeModel *list_store; + ptr = NSA_GET_PTR (env, obj); str = (*env)->GetStringUTFChars (env, text, NULL); gdk_threads_enter (); - gtk_clist_insert (CLIST_FROM_SW (ptr), index, (char **)&str); + + list = TREE_VIEW_FROM_SW (ptr); + list_store = gtk_tree_view_get_model (list); + + if (index == -1) + gtk_list_store_append (GTK_LIST_STORE (list_store), &iter); + else + gtk_list_store_insert (GTK_LIST_STORE (list_store), &iter, index); + + gtk_list_store_set (GTK_LIST_STORE (list_store), &iter, + COLUMN_STRING, str, -1); + gdk_threads_leave (); (*env)->ReleaseStringUTFChars (env, text, str); @@ -179,22 +275,32 @@ Java_gnu_java_awt_peer_gtk_GtkListPeer_delItems (JNIEnv *env, jobject obj, jint start, jint end) { void *ptr; - GtkCList *list; + GtkTreeView *list; + GtkTreeIter iter; + GtkTreeModel *list_store; jint i; + jint num_items; ptr = NSA_GET_PTR (env, obj); gdk_threads_enter (); - list = CLIST_FROM_SW (ptr); - if (end == -1) /* special case for removing all rows */ - gtk_clist_clear (list); + list = TREE_VIEW_FROM_SW (ptr); + list_store = gtk_tree_view_get_model (list); + + /* Special case: remove all rows. */ + if (end == -1) + gtk_list_store_clear (GTK_LIST_STORE (list_store)); else { - gtk_clist_freeze (list); - for (i = end; i >= start; i--) - gtk_clist_remove (list, i); - gtk_clist_thaw (list); + i = 0; + num_items = end - start + 1; + gtk_tree_model_iter_nth_child (list_store, &iter, NULL, start); + while (i < num_items) + { + gtk_list_store_remove (GTK_LIST_STORE (list_store), &iter); + i++; + } } gdk_threads_leave (); @@ -205,11 +311,17 @@ Java_gnu_java_awt_peer_gtk_GtkListPeer_select (JNIEnv *env, jobject obj, jint index) { void *ptr; + GtkTreeView *list; + GtkTreePath *path; ptr = NSA_GET_PTR (env, obj); gdk_threads_enter (); - gtk_clist_select_row (CLIST_FROM_SW (ptr), index, 0); + + list = TREE_VIEW_FROM_SW (ptr); + path = gtk_tree_path_new_from_indices (index, -1); + gtk_tree_view_set_cursor (list, path, NULL, FALSE); + gdk_threads_leave (); } @@ -218,40 +330,61 @@ Java_gnu_java_awt_peer_gtk_GtkListPeer_deselect (JNIEnv *env, jobject obj, jint index) { void *ptr; + GtkTreeView *list; + GtkTreeSelection *selection; + GtkTreePath *path; ptr = NSA_GET_PTR (env, obj); gdk_threads_enter (); - gtk_clist_unselect_row (CLIST_FROM_SW (ptr), index, 0); + + list = TREE_VIEW_FROM_SW (ptr); + selection = gtk_tree_view_get_selection (list); + path = gtk_tree_path_new_from_indices (index, -1); + gtk_tree_selection_unselect_path (selection, path); + gdk_threads_leave (); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkListPeer_getSize - (JNIEnv *env, jobject obj, jint rows, jintArray jdims) + (JNIEnv *env, jobject obj, jint rows, jint visible_rows, jintArray jdims) { void *ptr; jint *dims; - GtkWidget *list; - GtkScrolledWindow *sw; - GtkRequisition myreq; + GtkRequisition current_req; + GtkRequisition natural_req; dims = (*env)->GetIntArrayElements (env, jdims, NULL); dims[0] = dims[1] = 0; - if (rows < 3) - rows = 3; - ptr = NSA_GET_PTR (env, obj); + gdk_threads_enter (); - list = GTK_WIDGET (CLIST_FROM_SW (ptr)); - sw = GTK_SCROLLED_WINDOW (ptr); + /* Save the widget's current size request. */ + gtk_widget_size_request (GTK_WIDGET (ptr), ¤t_req); + + /* Get the widget's "natural" size request. */ + gtk_widget_set_size_request (GTK_WIDGET (ptr), -1, -1); + gtk_widget_size_request (GTK_WIDGET (ptr), &natural_req); + + /* Reset the widget's size request. */ + gtk_widget_set_size_request (GTK_WIDGET (ptr), + current_req.width, current_req.height); + + dims[0] = natural_req.width; + + /* Calculate the final height, by comparing the number of rows + in the list to the number of rows requested by the caller. + FIXME: Is there a GTK method that counts the number of rows + in the list? If so, we don't need to bring visible_rows from + the Java peer. */ + if (rows == visible_rows) + dims[1] = natural_req.height; + else + dims[1] = natural_req.height / visible_rows * rows; - gtk_widget_size_request(GTK_WIDGET(sw), &myreq); - dims[1]=myreq.height; - dims[0]=myreq.width; - gdk_threads_leave (); (*env)->ReleaseIntArrayElements (env, jdims, dims, 0); @@ -263,31 +396,53 @@ Java_gnu_java_awt_peer_gtk_GtkListPeer_getSelectedIndexes (JNIEnv *env, jobject obj) { void *ptr; - GtkCList *list; - jintArray selection; - jint *sel; - GList *child; - jint count, i; + GtkTreeView *list; + GtkTreeSelection *selection; + jintArray result_array; + jint *result_array_iter; + GList *current_row; + GList *rows; + gint *indices; + jint count; + jint i; ptr = NSA_GET_PTR (env, obj); + gdk_threads_enter (); - list = CLIST_FROM_SW (ptr); - count = g_list_length (list->selection); + list = TREE_VIEW_FROM_SW (ptr); + selection = gtk_tree_view_get_selection (list); + count = gtk_tree_selection_count_selected_rows (selection); + if (count > 0) + { + current_row = rows = gtk_tree_selection_get_selected_rows (selection, NULL); - selection = (*env)->NewIntArray (env, count); - sel = (*env)->GetIntArrayElements (env, selection, NULL); + result_array = (*env)->NewIntArray (env, count); + result_array_iter = (*env)->GetIntArrayElements (env, result_array, NULL); - for (i = 0, child = list->selection; i < count; i++) - { - sel[i] = GPOINTER_TO_INT (child->data); - child = g_list_next (child); - } - gdk_threads_leave (); + for (i = 0; i < count; i++) + { + indices = gtk_tree_path_get_indices (current_row->data); + result_array_iter[i] = indices ? indices[0] : -1; + current_row = g_list_next (current_row); + } + + if (rows) + { + g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL); + g_list_free (rows); + } - (*env)->ReleaseIntArrayElements (env, selection, sel, 0); + gdk_threads_leave (); + + (*env)->ReleaseIntArrayElements (env, result_array, result_array_iter, 0); + + return result_array; + } + else + gdk_threads_leave (); - return selection; + return (jintArray) NULL; } JNIEXPORT void JNICALL @@ -295,11 +450,17 @@ Java_gnu_java_awt_peer_gtk_GtkListPeer_makeVisible (JNIEnv *env, jobject obj, jint index) { void *ptr; + GtkTreeView *list; + GtkTreePath *path; ptr = NSA_GET_PTR (env, obj); gdk_threads_enter (); - gtk_clist_moveto (CLIST_FROM_SW (ptr), index, 0, 0.5, 0.5); + + list = TREE_VIEW_FROM_SW (ptr); + path = gtk_tree_path_new_from_indices (index, -1); + gtk_tree_view_scroll_to_cell (list, path, NULL, FALSE, 0.0, 0.0); + gdk_threads_leave (); } @@ -308,38 +469,18 @@ Java_gnu_java_awt_peer_gtk_GtkListPeer_setMultipleMode (JNIEnv *env, jobject obj, jboolean mode) { void *ptr; - + GtkTreeView *list; + GtkTreeSelection *selection; + ptr = NSA_GET_PTR (env, obj); gdk_threads_enter (); - gtk_clist_set_selection_mode (CLIST_FROM_SW (ptr), - mode ? GTK_SELECTION_MULTIPLE : - GTK_SELECTION_SINGLE); - gdk_threads_leave (); -} -static void -item_select (GtkCList *list __attribute__((unused)), - int row, int col __attribute__((unused)), - GdkEventButton *event __attribute__((unused)), - jobject peer_obj) -{ - (*gdk_env)->CallVoidMethod (gdk_env, peer_obj, - postListItemEventID, - row, - (jint) AWT_ITEM_SELECTED); -} + list = TREE_VIEW_FROM_SW (ptr); + selection = gtk_tree_view_get_selection (list); + gtk_tree_selection_set_mode (selection, + mode ? GTK_SELECTION_MULTIPLE + : GTK_SELECTION_SINGLE); -static void -item_unselect (GtkCList *list __attribute__((unused)), - int row, - int col __attribute__((unused)), - GdkEventButton *event __attribute__((unused)), - jobject peer_obj) -{ - (*gdk_env)->CallVoidMethod (gdk_env, peer_obj, - postListItemEventID, - row, - (jint) AWT_ITEM_DESELECTED); + gdk_threads_leave (); } - diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c index e6a8851fcf2..0bb0ec52567 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c @@ -46,8 +46,11 @@ accel_attach (GtkMenuItem *menu_item, GtkAccelGroup *accel; accel = gtk_menu_get_accel_group (GTK_MENU (menu_item->submenu)); + /* FIXME: update this to use GTK-2.4 GtkActions. */ +#if 0 _gtk_accel_group_attach (accel, G_OBJECT (gtk_widget_get_toplevel (GTK_WIDGET(menu_item)))); +#endif } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuPeer_setupAccelGroup @@ -129,7 +132,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuPeer_addItem (JNIEnv *env, jobject obj, jobject menuitempeer, jint key, jboolean shift) { void *ptr1, *ptr2; - GtkMenu *menu; + GtkWidget *menu; ptr1 = NSA_GET_PTR (env, obj); ptr2 = NSA_GET_PTR (env, menuitempeer); @@ -142,7 +145,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuPeer_addItem if (key) { gtk_widget_add_accelerator (GTK_WIDGET (ptr2), "activate", - gtk_menu_get_accel_group (menu), key, + gtk_menu_get_accel_group (GTK_MENU (menu)), key, (GDK_CONTROL_MASK | ((shift) ? GDK_SHIFT_MASK : 0)), GTK_ACCEL_VISIBLE); diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkPopupMenuPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkPopupMenuPeer.c index ee12a7f77b1..2d271ea8f2b 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkPopupMenuPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkPopupMenuPeer.c @@ -93,7 +93,10 @@ Java_gnu_java_awt_peer_gtk_GtkPopupMenuPeer_setupAccelGroup gdk_threads_enter (); menu = GTK_MENU (GTK_MENU_ITEM (ptr1)->submenu); gtk_menu_set_accel_group (menu, gtk_accel_group_new ()); + /* FIXME: update this to use GTK-2.4 GtkActions. */ +#if 0 _gtk_accel_group_attach (gtk_menu_get_accel_group (menu), G_OBJECT (gtk_widget_get_toplevel (ptr2))); +#endif gdk_threads_leave (); } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c index 704273c08a3..f9baa296459 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c @@ -164,7 +164,7 @@ Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_gtkSetFont if (style & AWT_STYLE_ITALIC) pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE); - gtk_widget_modify_font (GTK_WIDGET(text), font_desc); + gtk_widget_modify_font (GTK_WIDGET (text), font_desc); pango_font_description_free (font_desc); @@ -173,6 +173,24 @@ Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_gtkSetFont (*env)->ReleaseStringUTFChars (env, name, font_name); } +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_gtkWidgetRequestFocus + (JNIEnv *env, jobject obj) +{ + void *ptr; + GtkWidget *text; + + ptr = NSA_GET_PTR (env, obj); + + gdk_threads_enter (); + + text = GTK_WIDGET (TEXT_FROM_SW (ptr)); + + gtk_widget_grab_focus (text); + + gdk_threads_leave (); +} + JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getHScrollbarHeight (JNIEnv *env, jobject obj) diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c index 0d7d55562c5..2807e6b36fc 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c @@ -40,10 +40,6 @@ exception statement from your version. */ #include "gnu_java_awt_peer_gtk_GtkComponentPeer.h" #include "gnu_java_awt_peer_gtk_GtkTextComponentPeer.h" -static void textcomponent_commit_cb (GtkIMContext *context, - const gchar *str, - jobject peer); - static void textcomponent_changed_cb (GtkEditable *editable, jobject peer); @@ -61,9 +57,6 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_connectSignals if (GTK_IS_ENTRY(ptr)) { - g_signal_connect (GTK_ENTRY (ptr)->im_context, "commit", - G_CALLBACK (textcomponent_commit_cb), *gref); - g_signal_connect (GTK_EDITABLE (ptr), "changed", G_CALLBACK (textcomponent_changed_cb), *gref); @@ -85,9 +78,6 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_connectSignals if (text) { - g_signal_connect (text->im_context, "commit", - G_CALLBACK (textcomponent_commit_cb), *gref); - buf = gtk_text_view_get_buffer (text); if (buf) g_signal_connect (buf, "changed", @@ -112,8 +102,8 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_getCaretPosition { void *ptr; int pos = 0; - GtkEditable *editable; /* type of GtkEntry (TextField) */ - GtkWidget *text = NULL; /* type of GtkTextView (TextArea) */ + GtkEditable *editable; + GtkWidget *text = NULL; GtkTextBuffer *buf; GtkTextMark *mark; GtkTextIter iter; @@ -157,8 +147,8 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_setCaretPosition (JNIEnv *env, jobject obj, jint pos) { void *ptr; - GtkEditable *editable; /* type of GtkEntry (TextField) */ - GtkWidget *text = NULL; /* type of GtkTextView (TextArea) */ + GtkEditable *editable; + GtkWidget *text = NULL; GtkTextBuffer *buf; GtkTextIter iter; @@ -198,8 +188,8 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_getSelectionStart { void *ptr; int pos = 0; - GtkEditable *editable; /* type of GtkEntry (TextField) */ - GtkWidget *text = NULL; /* type of GtkTextView (TextArea) */ + GtkEditable *editable; + GtkWidget *text = NULL; GtkTextBuffer *buf; GtkTextIter start; GtkTextIter end; @@ -255,8 +245,8 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_getSelectionEnd { void *ptr; int pos = 0; - GtkEditable *editable; /* type of GtkEntry (TextField) */ - GtkWidget *text = NULL; /* type of GtkTextView (TextArea) */ + GtkEditable *editable; + GtkWidget *text = NULL; GtkTextBuffer *buf; GtkTextIter start; GtkTextIter end; @@ -311,8 +301,8 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_select (JNIEnv *env, jobject obj, jint start, jint end) { void *ptr; - GtkEditable *editable; /* type of GtkEntry (TextField) */ - GtkWidget *text = NULL; /* type of GtkTextView (TextArea) */ + GtkEditable *editable; + GtkWidget *text = NULL; GtkTextBuffer *buf; GtkTextIter iter; @@ -357,8 +347,8 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_setEditable (JNIEnv *env, jobject obj, jboolean state) { void *ptr; - GtkEditable *editable; /* type of GtkEntry (TextField) */ - GtkWidget *text = NULL; /* type of GtkTextView (TextArea) */ + GtkEditable *editable; + GtkWidget *text = NULL; ptr = NSA_GET_PTR (env, obj); @@ -396,8 +386,8 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_getText void *ptr; char *contents = NULL; jstring jcontents; - GtkEditable *editable; /* type of GtkEntry (TextField) */ - GtkWidget *text = NULL; /* type of GtkTextView (TextArea) */ + GtkEditable *editable; + GtkWidget *text = NULL; GtkTextBuffer *buf; GtkTextIter start, end; @@ -444,7 +434,7 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_setText { void *ptr; const char *str; - GtkWidget *text = NULL; /* type of GtkTextView (TextArea) */ + GtkWidget *text = NULL; GtkTextBuffer *buf; ptr = NSA_GET_PTR (env, obj); @@ -480,28 +470,6 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_setText } static void -textcomponent_commit_cb (GtkIMContext *context __attribute__((unused)), - const gchar *str, - jobject peer) -{ - /* str is a \0-terminated UTF-8 encoded character. */ - gunichar2 *jc = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL); - GdkEvent *event = gtk_get_current_event (); - - if (jc) - (*gdk_env)->CallVoidMethod (gdk_env, peer, - postKeyEventID, - (jint) AWT_KEY_TYPED, - (jlong) event->key.time, - keyevent_state_to_awt_mods (event), - VK_UNDEFINED, - (jchar) jc[0], - AWT_KEY_LOCATION_UNKNOWN); - g_free (jc); - gdk_event_free (event); -} - -static void textcomponent_changed_cb (GtkEditable *editable __attribute__((unused)), jobject peer) { diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c index 37c36906277..6234b29c913 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c @@ -39,6 +39,8 @@ exception statement from your version. */ #include "gtkpeer.h" #include "gnu_java_awt_peer_gtk_GtkToolkit.h" +static jint gdk_color_to_java_color (GdkColor color); + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_beep (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused))) @@ -88,3 +90,70 @@ Java_gnu_java_awt_peer_gtk_GtkToolkit_getScreenResolution return res; } +#define CONVERT(type, state) \ + gdk_color_to_java_color (style->type[GTK_STATE_ ## state]) + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkToolkit_loadSystemColors + (JNIEnv *env, jobject obj __attribute__((unused)), + jintArray jcolors) +{ + jint *colors; + GtkStyle *style; + + colors = (*env)->GetIntArrayElements (env, jcolors, 0); + + gdk_threads_enter (); + + style = gtk_widget_get_default_style (); + + colors[AWT_DESKTOP] = CONVERT (bg, SELECTED); + colors[AWT_ACTIVE_CAPTION] = CONVERT (bg, SELECTED); + colors[AWT_ACTIVE_CAPTION_TEXT] = CONVERT (text, SELECTED); + colors[AWT_ACTIVE_CAPTION_BORDER] = CONVERT (fg, NORMAL); + colors[AWT_INACTIVE_CAPTION] = CONVERT (base, INSENSITIVE); + colors[AWT_INACTIVE_CAPTION_TEXT] = CONVERT (fg, INSENSITIVE); + colors[AWT_INACTIVE_CAPTION_BORDER] = CONVERT (fg, INSENSITIVE); + colors[AWT_WINDOW] = CONVERT (bg, NORMAL); + colors[AWT_WINDOW_BORDER] = CONVERT (fg, NORMAL); + colors[AWT_WINDOW_TEXT] = CONVERT (fg, NORMAL); + colors[AWT_MENU] = CONVERT (bg, NORMAL); + colors[AWT_MENU_TEXT] = CONVERT (fg, NORMAL); + colors[AWT_TEXT] = CONVERT (bg, NORMAL); + colors[AWT_TEXT_TEXT] = CONVERT (fg, NORMAL); + colors[AWT_TEXT_HIGHLIGHT] = CONVERT (bg, SELECTED); + colors[AWT_TEXT_HIGHLIGHT_TEXT] = CONVERT (fg, SELECTED); + colors[AWT_TEXT_INACTIVE_TEXT] = CONVERT (bg, INSENSITIVE); + colors[AWT_CONTROL] = CONVERT (bg, NORMAL); + colors[AWT_CONTROL_TEXT] = CONVERT (fg, NORMAL); + colors[AWT_CONTROL_HIGHLIGHT] = CONVERT (base, ACTIVE); + colors[AWT_CONTROL_LT_HIGHLIGHT] = CONVERT (bg, PRELIGHT); + colors[AWT_CONTROL_SHADOW] = CONVERT (bg, ACTIVE); + colors[AWT_CONTROL_DK_SHADOW] = CONVERT (fg, INSENSITIVE); + colors[AWT_SCROLLBAR] = CONVERT (base, INSENSITIVE); + colors[AWT_INFO] = CONVERT (bg, NORMAL); + colors[AWT_INFO_TEXT] = CONVERT (fg, NORMAL); + + gdk_threads_leave (); + + (*env)->ReleaseIntArrayElements(env, jcolors, colors, 0); +} + +#undef CONVERT + +static jint +gdk_color_to_java_color (GdkColor gdk_color) +{ + guchar red; + guchar green; + guchar blue; + float factor; + + factor = 255.0 / 65535.0; + + red = (float) gdk_color.red * factor; + green = (float) gdk_color.green * factor; + blue = (float) gdk_color.blue * factor; + + return (jint) (0xff000000 | (red << 16) | (green << 8) | blue); +} diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c index 619b48d593a..c696a3fa6a2 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c @@ -357,6 +357,20 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds gdk_threads_enter (); gtk_window_move (GTK_WINDOW(ptr), x, y); + /* The call to gdk_window_move is needed in addition to the call to + gtk_window_move. If gdk_window_move isn't called, then the + following set of operations doesn't give the expected results: + + 1. show a window + 2. manually move it to another position on the screen + 3. hide the window + 4. reposition the window with Component.setLocation + 5. show the window + + Instead of being at the position set by setLocation, the window + is reshown at the position to which it was moved manually. */ + gdk_window_move (GTK_WIDGET (ptr)->window, x, y); + /* Need to change the widget's request size. */ gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height); /* Also need to call gtk_window_resize. If the resize is requested diff --git a/libjava/jni/gtk-peer/gtkcairopeer.h b/libjava/jni/gtk-peer/gtkcairopeer.h index 90a148fa9fc..b4021f51ed9 100644 --- a/libjava/jni/gtk-peer/gtkcairopeer.h +++ b/libjava/jni/gtk-peer/gtkcairopeer.h @@ -71,7 +71,8 @@ struct graphics2d GdkWindow *win; GdkPixbuf *drawbuf; char *pattern_pixels; - cairo_surface_t *pattern; + cairo_surface_t *pattern_surface; + cairo_pattern_t *pattern; gboolean debug; }; diff --git a/libjava/jni/gtk-peer/gtkpeer.h b/libjava/jni/gtk-peer/gtkpeer.h index d552e687c9b..a913986c1db 100644 --- a/libjava/jni/gtk-peer/gtkpeer.h +++ b/libjava/jni/gtk-peer/gtkpeer.h @@ -361,8 +361,8 @@ struct graphics #define VK_ALT_GRAPH 65406 #define VK_UNDEFINED 0 -#define AWT_FOCUS_LOST 1004 -#define AWT_FOCUS_GAINED 1005 +#define AWT_FOCUS_GAINED 1004 +#define AWT_FOCUS_LOST 1005 #define AWT_WINDOW_OPENED 200 #define AWT_WINDOW_CLOSING 201 @@ -385,6 +385,35 @@ struct graphics #define AWT_STYLE_BOLD 1 #define AWT_STYLE_ITALIC 2 +/* From java.awt.SystemColor */ +#define AWT_DESKTOP 0 +#define AWT_ACTIVE_CAPTION 1 +#define AWT_ACTIVE_CAPTION_TEXT 2 +#define AWT_ACTIVE_CAPTION_BORDER 3 +#define AWT_INACTIVE_CAPTION 4 +#define AWT_INACTIVE_CAPTION_TEXT 5 +#define AWT_INACTIVE_CAPTION_BORDER 6 +#define AWT_WINDOW 7 +#define AWT_WINDOW_BORDER 8 +#define AWT_WINDOW_TEXT 9 +#define AWT_MENU 10 +#define AWT_MENU_TEXT 11 +#define AWT_TEXT 12 +#define AWT_TEXT_TEXT 13 +#define AWT_TEXT_HIGHLIGHT 14 +#define AWT_TEXT_HIGHLIGHT_TEXT 15 +#define AWT_TEXT_INACTIVE_TEXT 16 +#define AWT_CONTROL 17 +#define AWT_CONTROL_TEXT 18 +#define AWT_CONTROL_HIGHLIGHT 19 +#define AWT_CONTROL_LT_HIGHLIGHT 20 +#define AWT_CONTROL_SHADOW 21 +#define AWT_CONTROL_DK_SHADOW 22 +#define AWT_SCROLLBAR 23 +#define AWT_INFO 24 +#define AWT_INFO_TEXT 25 +#define AWT_NUM_COLORS 26 + extern jmethodID setBoundsCallbackID; extern jmethodID postActionEventID; |