summaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing')
-rw-r--r--libjava/classpath/javax/swing/AbstractButton.java123
-rw-r--r--libjava/classpath/javax/swing/AbstractSpinnerModel.java1
-rw-r--r--libjava/classpath/javax/swing/ActionMap.java9
-rw-r--r--libjava/classpath/javax/swing/BorderFactory.java2
-rw-r--r--libjava/classpath/javax/swing/BoundedRangeModel.java4
-rw-r--r--libjava/classpath/javax/swing/Box.java21
-rw-r--r--libjava/classpath/javax/swing/BoxLayout.java693
-rw-r--r--libjava/classpath/javax/swing/ButtonGroup.java5
-rw-r--r--libjava/classpath/javax/swing/ButtonModel.java260
-rw-r--r--libjava/classpath/javax/swing/CellEditor.java2
-rw-r--r--libjava/classpath/javax/swing/CellRendererPane.java38
-rw-r--r--libjava/classpath/javax/swing/ComboBoxEditor.java2
-rw-r--r--libjava/classpath/javax/swing/ComponentInputMap.java26
-rw-r--r--libjava/classpath/javax/swing/DebugGraphics.java308
-rw-r--r--libjava/classpath/javax/swing/DefaultButtonModel.java1
-rw-r--r--libjava/classpath/javax/swing/DefaultCellEditor.java7
-rw-r--r--libjava/classpath/javax/swing/DefaultComboBoxModel.java172
-rw-r--r--libjava/classpath/javax/swing/DefaultDesktopManager.java4
-rw-r--r--libjava/classpath/javax/swing/DefaultListCellRenderer.java14
-rw-r--r--libjava/classpath/javax/swing/DefaultListSelectionModel.java60
-rw-r--r--libjava/classpath/javax/swing/DesktopManager.java2
-rw-r--r--libjava/classpath/javax/swing/FocusManager.java425
-rw-r--r--libjava/classpath/javax/swing/ImageIcon.java9
-rw-r--r--libjava/classpath/javax/swing/InputMap.java12
-rw-r--r--libjava/classpath/javax/swing/InputVerifier.java1
-rw-r--r--libjava/classpath/javax/swing/JApplet.java58
-rw-r--r--libjava/classpath/javax/swing/JButton.java7
-rw-r--r--libjava/classpath/javax/swing/JCheckBox.java70
-rw-r--r--libjava/classpath/javax/swing/JCheckBoxMenuItem.java13
-rw-r--r--libjava/classpath/javax/swing/JColorChooser.java2
-rw-r--r--libjava/classpath/javax/swing/JComboBox.java115
-rw-r--r--libjava/classpath/javax/swing/JComponent.java1053
-rw-r--r--libjava/classpath/javax/swing/JDesktopPane.java3
-rw-r--r--libjava/classpath/javax/swing/JDialog.java48
-rw-r--r--libjava/classpath/javax/swing/JEditorPane.java441
-rw-r--r--libjava/classpath/javax/swing/JFileChooser.java767
-rw-r--r--libjava/classpath/javax/swing/JFrame.java57
-rw-r--r--libjava/classpath/javax/swing/JInternalFrame.java45
-rw-r--r--libjava/classpath/javax/swing/JLabel.java18
-rw-r--r--libjava/classpath/javax/swing/JLayeredPane.java137
-rw-r--r--libjava/classpath/javax/swing/JList.java850
-rw-r--r--libjava/classpath/javax/swing/JMenu.java27
-rw-r--r--libjava/classpath/javax/swing/JMenuBar.java206
-rw-r--r--libjava/classpath/javax/swing/JMenuItem.java34
-rw-r--r--libjava/classpath/javax/swing/JOptionPane.java160
-rw-r--r--libjava/classpath/javax/swing/JPanel.java132
-rw-r--r--libjava/classpath/javax/swing/JPasswordField.java1
-rw-r--r--libjava/classpath/javax/swing/JPopupMenu.java343
-rw-r--r--libjava/classpath/javax/swing/JProgressBar.java5
-rw-r--r--libjava/classpath/javax/swing/JRadioButton.java4
-rw-r--r--libjava/classpath/javax/swing/JRadioButtonMenuItem.java8
-rw-r--r--libjava/classpath/javax/swing/JRootPane.java252
-rw-r--r--libjava/classpath/javax/swing/JScrollPane.java220
-rw-r--r--libjava/classpath/javax/swing/JSeparator.java2
-rw-r--r--libjava/classpath/javax/swing/JSlider.java3
-rw-r--r--libjava/classpath/javax/swing/JSpinner.java42
-rw-r--r--libjava/classpath/javax/swing/JSplitPane.java3
-rw-r--r--libjava/classpath/javax/swing/JTabbedPane.java130
-rw-r--r--libjava/classpath/javax/swing/JTable.java1012
-rw-r--r--libjava/classpath/javax/swing/JTextArea.java61
-rw-r--r--libjava/classpath/javax/swing/JTextField.java183
-rw-r--r--libjava/classpath/javax/swing/JTextPane.java11
-rw-r--r--libjava/classpath/javax/swing/JToggleButton.java24
-rw-r--r--libjava/classpath/javax/swing/JToolBar.java4
-rw-r--r--libjava/classpath/javax/swing/JToolTip.java3
-rw-r--r--libjava/classpath/javax/swing/JTree.java4337
-rw-r--r--libjava/classpath/javax/swing/JViewport.java579
-rw-r--r--libjava/classpath/javax/swing/JWindow.java48
-rw-r--r--libjava/classpath/javax/swing/KeyStroke.java1
-rw-r--r--libjava/classpath/javax/swing/KeyboardManager.java280
-rw-r--r--libjava/classpath/javax/swing/ListCellRenderer.java8
-rw-r--r--libjava/classpath/javax/swing/ListSelectionModel.java34
-rw-r--r--libjava/classpath/javax/swing/LookAndFeel.java115
-rw-r--r--libjava/classpath/javax/swing/MenuElement.java84
-rw-r--r--libjava/classpath/javax/swing/MenuSelectionManager.java9
-rw-r--r--libjava/classpath/javax/swing/MutableComboBoxModel.java4
-rw-r--r--libjava/classpath/javax/swing/OverlayLayout.java507
-rw-r--r--libjava/classpath/javax/swing/Popup.java112
-rw-r--r--libjava/classpath/javax/swing/PopupFactory.java33
-rw-r--r--libjava/classpath/javax/swing/ProgressMonitor.java567
-rw-r--r--libjava/classpath/javax/swing/ProgressMonitorInputStream.java291
-rw-r--r--libjava/classpath/javax/swing/Renderer.java32
-rw-r--r--libjava/classpath/javax/swing/RepaintManager.java292
-rw-r--r--libjava/classpath/javax/swing/RootPaneContainer.java96
-rw-r--r--libjava/classpath/javax/swing/ScrollPaneLayout.java426
-rw-r--r--libjava/classpath/javax/swing/Scrollable.java17
-rw-r--r--libjava/classpath/javax/swing/SingleSelectionModel.java81
-rw-r--r--libjava/classpath/javax/swing/SizeRequirements.java211
-rw-r--r--libjava/classpath/javax/swing/SizeSequence.java399
-rw-r--r--libjava/classpath/javax/swing/SortingFocusTraversalPolicy.java2
-rw-r--r--libjava/classpath/javax/swing/SpinnerListModel.java415
-rw-r--r--libjava/classpath/javax/swing/Spring.java1
-rw-r--r--libjava/classpath/javax/swing/SpringLayout.java43
-rw-r--r--libjava/classpath/javax/swing/SwingUtilities.java26
-rw-r--r--libjava/classpath/javax/swing/Timer.java106
-rw-r--r--libjava/classpath/javax/swing/ToolTipManager.java219
-rw-r--r--libjava/classpath/javax/swing/TransferHandler.java57
-rw-r--r--libjava/classpath/javax/swing/UIDefaults.java10
-rw-r--r--libjava/classpath/javax/swing/UIManager.java22
-rw-r--r--libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java8
-rw-r--r--libjava/classpath/javax/swing/ViewportLayout.java5
-rw-r--r--libjava/classpath/javax/swing/WindowConstants.java43
-rw-r--r--libjava/classpath/javax/swing/border/AbstractBorder.java46
-rw-r--r--libjava/classpath/javax/swing/border/BevelBorder.java13
-rw-r--r--libjava/classpath/javax/swing/border/Border.java6
-rw-r--r--libjava/classpath/javax/swing/border/CompoundBorder.java57
-rw-r--r--libjava/classpath/javax/swing/border/EmptyBorder.java4
-rw-r--r--libjava/classpath/javax/swing/border/EtchedBorder.java45
-rw-r--r--libjava/classpath/javax/swing/border/LineBorder.java44
-rw-r--r--libjava/classpath/javax/swing/border/MatteBorder.java4
-rw-r--r--libjava/classpath/javax/swing/border/SoftBevelBorder.java12
-rw-r--r--libjava/classpath/javax/swing/border/TitledBorder.java112
-rw-r--r--libjava/classpath/javax/swing/colorchooser/AbstractColorChooserPanel.java35
-rw-r--r--libjava/classpath/javax/swing/colorchooser/ColorChooserComponentFactory.java3
-rw-r--r--libjava/classpath/javax/swing/colorchooser/DefaultSwatchChooserPanel.java3
-rw-r--r--libjava/classpath/javax/swing/event/EventListenerList.java1
-rw-r--r--libjava/classpath/javax/swing/event/InternalFrameAdapter.java147
-rw-r--r--libjava/classpath/javax/swing/event/ListDataListener.java55
-rw-r--r--libjava/classpath/javax/swing/event/MouseInputListener.java13
-rw-r--r--libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java7
-rw-r--r--libjava/classpath/javax/swing/event/TreeModelEvent.java8
-rw-r--r--libjava/classpath/javax/swing/filechooser/FileFilter.java77
-rw-r--r--libjava/classpath/javax/swing/filechooser/FileSystemView.java181
-rw-r--r--libjava/classpath/javax/swing/filechooser/FileView.java152
-rw-r--r--libjava/classpath/javax/swing/filechooser/UnixFileSystemView.java47
-rw-r--r--libjava/classpath/javax/swing/plaf/ActionMapUIResource.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/BorderUIResource.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/ButtonUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/ColorChooserUI.java3
-rw-r--r--libjava/classpath/javax/swing/plaf/ColorUIResource.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/ComboBoxUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java3
-rw-r--r--libjava/classpath/javax/swing/plaf/ComponentUI.java10
-rw-r--r--libjava/classpath/javax/swing/plaf/DesktopIconUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/DesktopPaneUI.java5
-rw-r--r--libjava/classpath/javax/swing/plaf/DimensionUIResource.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/FileChooserUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/FontUIResource.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/IconUIResource.java3
-rw-r--r--libjava/classpath/javax/swing/plaf/InputMapUIResource.java6
-rw-r--r--libjava/classpath/javax/swing/plaf/InsetsUIResource.java3
-rw-r--r--libjava/classpath/javax/swing/plaf/InternalFrameUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/LabelUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/ListUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/MenuBarUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/MenuItemUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/PanelUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/PopupMenuUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/ProgressBarUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/RootPaneUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/ScrollBarUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/ScrollPaneUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/SeparatorUI.java1
-rw-r--r--libjava/classpath/javax/swing/plaf/SliderUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/SpinnerUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/SplitPaneUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/TabbedPaneUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/TableHeaderUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/TableUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/TextUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/ToolBarUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/ToolTipUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/TreeUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/UIResource.java6
-rw-r--r--libjava/classpath/javax/swing/plaf/ViewportUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java406
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicBorders.java13
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java11
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java146
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java23
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java20
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java45
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java72
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java778
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java60
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java2
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java80
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java875
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java9
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java1
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java26
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java155
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java691
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java18
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicListUI.java671
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java170
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java105
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java673
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java88
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java81
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java28
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java7
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java47
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java417
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java4
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java35
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java119
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java335
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java418
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java73
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java51
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java16
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java1
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java72
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java1524
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java63
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java586
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java47
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java22
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java32
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java167
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java65
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java5
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java56
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java99
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java1327
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java177
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalBorders.java799
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java86
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java158
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java10
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java7
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java241
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java143
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java9
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java264
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java10
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java430
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java1386
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java325
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java120
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java10
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java422
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java10
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java101
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java130
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java13
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java430
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalScrollButton.java483
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java19
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java63
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java220
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java2
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java35
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java30
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java32
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java129
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java112
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java272
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java278
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalUtils.java103
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/OceanTheme.java209
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/package.html13
-rw-r--r--libjava/classpath/javax/swing/plaf/multi/MultiLookAndFeel.java1
-rw-r--r--libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java49
-rw-r--r--libjava/classpath/javax/swing/table/JTableHeader.java109
-rw-r--r--libjava/classpath/javax/swing/table/TableColumn.java10
-rw-r--r--libjava/classpath/javax/swing/table/TableColumnModel.java4
-rw-r--r--libjava/classpath/javax/swing/text/AbstractDocument.java326
-rw-r--r--libjava/classpath/javax/swing/text/AttributeSet.java6
-rw-r--r--libjava/classpath/javax/swing/text/BoxView.java256
-rw-r--r--libjava/classpath/javax/swing/text/ComponentView.java200
-rw-r--r--libjava/classpath/javax/swing/text/CompositeView.java66
-rw-r--r--libjava/classpath/javax/swing/text/DefaultCaret.java409
-rw-r--r--libjava/classpath/javax/swing/text/DefaultEditorKit.java45
-rw-r--r--libjava/classpath/javax/swing/text/DefaultFormatter.java15
-rw-r--r--libjava/classpath/javax/swing/text/DefaultHighlighter.java2
-rw-r--r--libjava/classpath/javax/swing/text/DefaultStyledDocument.java1032
-rw-r--r--libjava/classpath/javax/swing/text/DefaultTextUI.java61
-rw-r--r--libjava/classpath/javax/swing/text/EditorKit.java10
-rw-r--r--libjava/classpath/javax/swing/text/FieldView.java17
-rw-r--r--libjava/classpath/javax/swing/text/FlowView.java70
-rw-r--r--libjava/classpath/javax/swing/text/GapContent.java382
-rw-r--r--libjava/classpath/javax/swing/text/GlyphView.java652
-rw-r--r--libjava/classpath/javax/swing/text/IconView.java32
-rw-r--r--libjava/classpath/javax/swing/text/InternationalFormatter.java5
-rw-r--r--libjava/classpath/javax/swing/text/JTextComponent.java211
-rw-r--r--libjava/classpath/javax/swing/text/LabelView.java242
-rw-r--r--libjava/classpath/javax/swing/text/LayoutQueue.java1
-rw-r--r--libjava/classpath/javax/swing/text/ParagraphView.java30
-rw-r--r--libjava/classpath/javax/swing/text/PlainDocument.java28
-rw-r--r--libjava/classpath/javax/swing/text/PlainView.java371
-rw-r--r--libjava/classpath/javax/swing/text/Segment.java4
-rw-r--r--libjava/classpath/javax/swing/text/SimpleAttributeSet.java57
-rw-r--r--libjava/classpath/javax/swing/text/StringContent.java3
-rw-r--r--libjava/classpath/javax/swing/text/StyleConstants.java6
-rw-r--r--libjava/classpath/javax/swing/text/StyleContext.java19
-rw-r--r--libjava/classpath/javax/swing/text/StyledDocument.java191
-rw-r--r--libjava/classpath/javax/swing/text/StyledEditorKit.java24
-rw-r--r--libjava/classpath/javax/swing/text/TabSet.java3
-rw-r--r--libjava/classpath/javax/swing/text/TabStop.java3
-rw-r--r--libjava/classpath/javax/swing/text/Utilities.java410
-rw-r--r--libjava/classpath/javax/swing/text/View.java76
-rw-r--r--libjava/classpath/javax/swing/text/WrappedPlainView.java700
-rw-r--r--libjava/classpath/javax/swing/text/html/CSS.java461
-rw-r--r--libjava/classpath/javax/swing/text/html/HTML.java13
-rw-r--r--libjava/classpath/javax/swing/text/html/HTMLDocument.java215
-rw-r--r--libjava/classpath/javax/swing/text/html/HTMLEditorKit.java38
-rw-r--r--libjava/classpath/javax/swing/text/html/HTMLFrameHyperlinkEvent.java4
-rw-r--r--libjava/classpath/javax/swing/text/html/parser/ContentModel.java5
-rw-r--r--libjava/classpath/javax/swing/text/html/parser/DTD.java6
-rw-r--r--libjava/classpath/javax/swing/text/html/parser/DocumentParser.java7
-rw-r--r--libjava/classpath/javax/swing/text/html/parser/Element.java2
-rw-r--r--libjava/classpath/javax/swing/text/html/parser/Parser.java10
-rw-r--r--libjava/classpath/javax/swing/tree/DefaultMutableTreeNode.java1
-rw-r--r--libjava/classpath/javax/swing/tree/DefaultTreeCellEditor.java15
-rw-r--r--libjava/classpath/javax/swing/tree/DefaultTreeCellRenderer.java3
-rw-r--r--libjava/classpath/javax/swing/tree/DefaultTreeModel.java1
-rw-r--r--libjava/classpath/javax/swing/tree/TreeCellRenderer.java34
-rw-r--r--libjava/classpath/javax/swing/tree/TreeModel.java122
-rw-r--r--libjava/classpath/javax/swing/undo/CannotRedoException.java4
-rw-r--r--libjava/classpath/javax/swing/undo/CannotUndoException.java1
312 files changed, 32365 insertions, 12342 deletions
diff --git a/libjava/classpath/javax/swing/AbstractButton.java b/libjava/classpath/javax/swing/AbstractButton.java
index 21c4fc0a26c..376b3a056ae 100644
--- a/libjava/classpath/javax/swing/AbstractButton.java
+++ b/libjava/classpath/javax/swing/AbstractButton.java
@@ -165,6 +165,8 @@ public abstract class AbstractButton extends JComponent
*/
public void stateChanged(ChangeEvent ev)
{
+ AbstractButton.this.fireStateChanged();
+ repaint();
}
}
@@ -375,6 +377,7 @@ public abstract class AbstractButton extends JComponent
protected AccessibleAbstractButton()
{
+ // Nothing to do here yet.
}
public AccessibleStateSet getAccessibleStateSet()
@@ -509,11 +512,37 @@ public abstract class AbstractButton extends JComponent
}
/**
- * Creates a new AbstractButton object.
+ * Creates a new AbstractButton object. Subclasses should call the following
+ * sequence in their constructor in order to initialize the button correctly:
+ * <pre>
+ * super();
+ * init(text, icon);
+ * </pre>
+ *
+ * The {@link #init(String, Icon)} method is not called automatically by this
+ * constructor.
+ *
+ * @see #init(String, Icon)
*/
public AbstractButton()
{
- init("", null);
+ actionListener = createActionListener();
+ changeListener = createChangeListener();
+ itemListener = createItemListener();
+
+ horizontalAlignment = CENTER;
+ horizontalTextPosition = TRAILING;
+ verticalAlignment = CENTER;
+ verticalTextPosition = CENTER;
+ borderPainted = true;
+ contentAreaFilled = true;
+ focusPainted = true;
+ setFocusable(true);
+ setAlignmentX(CENTER_ALIGNMENT);
+ setAlignmentY(CENTER_ALIGNMENT);
+ setDisplayedMnemonicIndex(-1);
+ setOpaque(true);
+ text = "";
updateUI();
}
@@ -524,7 +553,7 @@ public abstract class AbstractButton extends JComponent
*/
public ButtonModel getModel()
{
- return model;
+ return model;
}
/**
@@ -569,25 +598,6 @@ public abstract class AbstractButton extends JComponent
if (icon != null)
default_icon = icon;
-
- actionListener = createActionListener();
- changeListener = createChangeListener();
- itemListener = createItemListener();
-
- horizontalAlignment = CENTER;
- horizontalTextPosition = TRAILING;
- verticalAlignment = CENTER;
- verticalTextPosition = CENTER;
- borderPainted = true;
- contentAreaFilled = true;
-
- focusPainted = true;
- setFocusable(true);
-
- setAlignmentX(LEFT_ALIGNMENT);
- setAlignmentY(CENTER_ALIGNMENT);
-
- setDisplayedMnemonicIndex(-1);
}
/**
@@ -615,7 +625,8 @@ public abstract class AbstractButton extends JComponent
*/
public void setActionCommand(String actionCommand)
{
- model.setActionCommand(actionCommand);
+ if (model != null)
+ model.setActionCommand(actionCommand);
}
/**
@@ -782,7 +793,10 @@ public abstract class AbstractButton extends JComponent
*/
public int getMnemonic()
{
- return getModel().getMnemonic();
+ ButtonModel mod = getModel();
+ if (mod != null)
+ return mod.getMnemonic();
+ return -1;
}
/**
@@ -810,11 +824,15 @@ public abstract class AbstractButton extends JComponent
*/
public void setMnemonic(int mne)
{
- int old = getModel().getMnemonic();
+ ButtonModel mod = getModel();
+ int old = -1;
+ if (mod != null)
+ old = mod.getMnemonic();
if (old != mne)
{
- getModel().setMnemonic(mne);
+ if (mod != null)
+ mod.setMnemonic(mne);
if (text != null && !text.equals(""))
{
@@ -907,7 +925,9 @@ public abstract class AbstractButton extends JComponent
*/
public void setSelected(boolean s)
{
- getModel().setSelected(s);
+ ButtonModel mod = getModel();
+ if (mod != null)
+ mod.setSelected(s);
}
/**
@@ -918,7 +938,10 @@ public abstract class AbstractButton extends JComponent
*/
public boolean isSelected()
{
- return getModel().isSelected();
+ ButtonModel mod = getModel();
+ if (mod != null)
+ return mod.isSelected();
+ return false;
}
/**
@@ -929,8 +952,14 @@ public abstract class AbstractButton extends JComponent
*/
public void setEnabled(boolean b)
{
+ // Do nothing if state does not change.
+ if (b == isEnabled())
+ return;
super.setEnabled(b);
- getModel().setEnabled(b);
+ setFocusable(b);
+ ButtonModel mod = getModel();
+ if (mod != null)
+ mod.setEnabled(b);
}
/**
@@ -1608,16 +1637,9 @@ public abstract class AbstractButton extends JComponent
*
* @return The new ChangeListener
*/
- protected ChangeListener createChangeListener()
+ protected ChangeListener createChangeListener()
{
- return new ChangeListener()
- {
- public void stateChanged(ChangeEvent e)
- {
- AbstractButton.this.fireStateChanged();
- AbstractButton.this.repaint();
- }
- };
+ return new ButtonChangeListener();
}
/**
@@ -1669,18 +1691,22 @@ public abstract class AbstractButton extends JComponent
*/
public void doClick(int pressTime)
{
- getModel().setArmed(true);
- getModel().setPressed(true);
- try
+ ButtonModel mod = getModel();
+ if (mod != null)
{
- java.lang.Thread.sleep(pressTime);
- }
- catch (java.lang.InterruptedException e)
- {
- // probably harmless
+ mod.setArmed(true);
+ mod.setPressed(true);
+ try
+ {
+ java.lang.Thread.sleep(pressTime);
+ }
+ catch (java.lang.InterruptedException e)
+ {
+ // probably harmless
+ }
+ mod.setPressed(false);
+ mod.setArmed(false);
}
- getModel().setPressed(false);
- getModel().setArmed(false);
}
/**
@@ -1979,6 +2005,7 @@ public abstract class AbstractButton extends JComponent
*/
public void updateUI()
{
+ // TODO: What to do here?
}
/**
diff --git a/libjava/classpath/javax/swing/AbstractSpinnerModel.java b/libjava/classpath/javax/swing/AbstractSpinnerModel.java
index d61113b0827..1a82f0a359d 100644
--- a/libjava/classpath/javax/swing/AbstractSpinnerModel.java
+++ b/libjava/classpath/javax/swing/AbstractSpinnerModel.java
@@ -61,6 +61,7 @@ public abstract class AbstractSpinnerModel implements SpinnerModel
*/
public AbstractSpinnerModel()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/ActionMap.java b/libjava/classpath/javax/swing/ActionMap.java
index c14bafdb4be..65e193d2e79 100644
--- a/libjava/classpath/javax/swing/ActionMap.java
+++ b/libjava/classpath/javax/swing/ActionMap.java
@@ -80,6 +80,7 @@ public class ActionMap
*/
public ActionMap()
{
+ // Nothing to do here.
}
/**
@@ -170,7 +171,9 @@ public class ActionMap
*/
public Object[] keys()
{
- return actionMap.keySet().toArray();
+ if (size() != 0)
+ return actionMap.keySet().toArray();
+ return null;
}
/**
@@ -187,7 +190,9 @@ public class ActionMap
set.addAll(Arrays.asList(parent.allKeys()));
set.addAll(actionMap.keySet());
- return set.toArray();
+ if (set.size() != 0)
+ return set.toArray();
+ return null;
}
/**
diff --git a/libjava/classpath/javax/swing/BorderFactory.java b/libjava/classpath/javax/swing/BorderFactory.java
index 45cf3bbe074..ca78deb1290 100644
--- a/libjava/classpath/javax/swing/BorderFactory.java
+++ b/libjava/classpath/javax/swing/BorderFactory.java
@@ -71,7 +71,7 @@ public class BorderFactory
*/
public static Border createLineBorder(Color color)
{
- return null;
+ return createLineBorder(color, 1);
}
/**
diff --git a/libjava/classpath/javax/swing/BoundedRangeModel.java b/libjava/classpath/javax/swing/BoundedRangeModel.java
index 5ca5a7e043e..54446acd5ea 100644
--- a/libjava/classpath/javax/swing/BoundedRangeModel.java
+++ b/libjava/classpath/javax/swing/BoundedRangeModel.java
@@ -165,13 +165,13 @@ public interface BoundedRangeModel
*
* @param value the value
* @param extent the extent
- * @param minnimum the minimum value
+ * @param minimum the minimum value
* @param maximum the maximum value
* @param adjusting a flag that indicates the model is being adjusted
* continuously.
*/
void setRangeProperties(int value, int extent, int minimum, int maximum,
- boolean adjusting);
+ boolean adjusting);
/**
* Adds a <code>ChangeListener</code> to this object.
diff --git a/libjava/classpath/javax/swing/Box.java b/libjava/classpath/javax/swing/Box.java
index b2cb44aceb5..57519f6fcbd 100644
--- a/libjava/classpath/javax/swing/Box.java
+++ b/libjava/classpath/javax/swing/Box.java
@@ -40,6 +40,7 @@ package javax.swing;
import java.awt.AWTError;
import java.awt.Component;
+import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
@@ -63,13 +64,13 @@ public class Box extends JComponent implements Accessible
/**
* Provides accessibility support for <code>Box</code>es.
*/
- // FIXME: disable to make libjava compile; visibility rules are broken
- protected class AccessibleBox // extends Container.AccessibleAWTContainer
+ protected class AccessibleBox extends Container.AccessibleAWTContainer
{
private static final long serialVersionUID = -7775079816389931944L;
protected AccessibleBox()
{
+ // Nothing to do here.
}
public AccessibleRole getAccessibleRole()
@@ -88,13 +89,14 @@ public class Box extends JComponent implements Accessible
/**
* Provides accessibility support for <code>Box.Filler</code>.
*/
- // FIXME: disable to make libjava compile; visibility rules are broken
- protected class AccessibleBoxFiller // extends Component.AccessibleAWTComponent
+ protected class AccessibleBoxFiller
+ extends Component.AccessibleAWTComponent
{
private static final long serialVersionUID = 164963348357479321L;
protected AccessibleBoxFiller()
{
+ // Nothing to do here.
}
public AccessibleRole getAccessibleRole()
@@ -103,8 +105,6 @@ public class Box extends JComponent implements Accessible
}
}
- protected AccessibleContext accessibleContext;
-
private transient Dimension min, pref, max;
/**
@@ -135,9 +135,8 @@ public class Box extends JComponent implements Accessible
public AccessibleContext getAccessibleContext()
{
- // FIXME: disable to make libjava compile; visibility rules are broken
- // if (accessibleContext == null)
- // accessibleContext = new AccessibleBoxFiller();
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleBoxFiller();
return accessibleContext;
}
@@ -284,8 +283,8 @@ public class Box extends JComponent implements Accessible
public AccessibleContext getAccessibleContext()
{
- // if (accessibleContext == null)
- // accessibleContext = new AccessibleBox();
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleBox();
return accessibleContext;
}
diff --git a/libjava/classpath/javax/swing/BoxLayout.java b/libjava/classpath/javax/swing/BoxLayout.java
index 28bb53928ef..ebc0b4c211c 100644
--- a/libjava/classpath/javax/swing/BoxLayout.java
+++ b/libjava/classpath/javax/swing/BoxLayout.java
@@ -45,12 +45,6 @@ import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.io.Serializable;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Vector;
-
-import gnu.java.awt.AWTUtilities;
/**
* A layout that stacks the children of a container in a Box, either
@@ -63,248 +57,6 @@ public class BoxLayout implements LayoutManager2, Serializable
{
/**
- * This is an abstraction that allows the BoxLayout algorithm to
- * be applied to both direction (X and Y) without duplicating the
- * algorithm. It defines several methods that access properties of
- * a component for a specific direction.
- */
- static interface Direction
- {
- /**
- * Returns the correct part of <code>d</code> for this direction. This will
- * be <code>d.width</code> for horizontal and <code>d.height</code> for
- * vertical direction.
- *
- * @param d the size as Dimension object
- *
- * @return the correct part of <code>d</code> for this direction
- */
- int size(Dimension d);
-
- /**
- * Returns the lower bounds of the {@link Insets} object according to this
- * direction. This will be <code>insets.top</code> for vertical direction
- * and <code>insets.left</code> for horizontal direction.
- *
- * @param the {@link Insets} object from which to return the lower bounds
- *
- * @return the lower bounds of the {@link Insets} object according to this
- * direction
- */
- int lower(Insets insets);
-
- /**
- * Returns the alignment property according to this direction.
- *
- * @param comp the Component for which to return the alignment property
- *
- * @return the alignment property according to this direction
- */
- float alignment(Component comp);
-
- /**
- * Sets the location for Component <code>c</code>. <code>coord1</code>
- * specifies the coordinate of the location in this direction,
- * <code>coord2</code> the coordinate of the location in the opposite
- * direction.
- *
- * @param c the Component for which to set the location
- * @param coord1 the coordinate in this direction
- * @param coord2 the coordinate in the opposite direction
- */
- void setLocation(Component c, int coord1, int coord2);
-
- /**
- * Sets the size for Component <code>c</code>. <code>coord1</code>
- * specifies the size in this direction,
- * <code>coord2</code> the size in the opposite
- * direction.
- *
- * @param c the Component for which to set the size
- * @param size1 the size in this direction
- * @param size2 the size in the opposite direction
- */
- void setSize(Component c, int size1, int size2);
- }
-
- /**
- * The horizontal direction.
- */
- static class Horizontal implements Direction
- {
- /**
- * Returns the correct part of <code>d</code> for this direction. This will
- * be <code>d.width</code> for horizontal and <code>d.height</code> for
- * vertical direction.
- *
- * @param d the size as Dimension object
- *
- * @return the correct part of <code>d</code> for this direction
- */
- public int size(Dimension d)
- {
- return d.width;
- }
-
- /**
- * Returns the lower bounds of the {@link Insets} object according to this
- * direction. This will be <code>insets.top</code> for vertical direction
- * and <code>insets.left</code> for horizontal direction.
- *
- * @param insets the {@link Insets} object from which to return the lower
- * bounds
- *
- * @return the lower bounds of the {@link Insets} object according to this
- * direction
- */
- public int lower(Insets insets)
- {
- return insets.left;
- }
-
- /**
- * Returns the alignment property according to this direction.
- *
- * @param comp the Component for which to return the alignment property
- *
- * @return the alignment property according to this direction
- */
- public float alignment(Component comp)
- {
- return comp.getAlignmentX();
- }
-
- /**
- * Sets the location for Component <code>c</code>. <code>coord1</code>
- * specifies the coordinate of the location in this direction,
- * <code>coord2</code> the coordinate of the location in the opposite
- * direction.
- *
- * @param c the Component for which to set the location
- * @param coord1 the coordinate in this direction
- * @param coord2 the coordinate in the opposite direction
- */
- public void setLocation(Component c, int coord1, int coord2)
- {
- c.setLocation(coord1, coord2);
- }
-
- /**
- * Sets the size for Component <code>c</code>. <code>coord1</code>
- * specifies the size in this direction,
- * <code>coord2</code> the size in the opposite
- * direction.
- *
- * @param c the Component for which to set the size
- * @param size1 the size in this direction
- * @param size2 the size in the opposite direction
- */
- public void setSize(Component c, int size1, int size2)
- {
- c.setSize(size1, size2);
- }
- }
- /**
- * The vertical direction.
- */
- static class Vertical implements Direction
- {
- /**
- * Returns the correct part of <code>d</code> for this direction. This will
- * be <code>d.width</code> for horizontal and <code>d.height</code> for
- * vertical direction.
- *
- * @param d the size as Dimension object
- *
- * @return the correct part of <code>d</code> for this direction
- */
- public int size(Dimension d)
- {
- return d.height;
- }
-
- /**
- * Returns the lower bounds of the {@link Insets} object according to this
- * direction. This will be <code>insets.top</code> for vertical direction
- * and <code>insets.left</code> for horizontal direction.
- *
- * @param insets the {@link Insets} object from which to return the lower
- * bounds
- *
- * @return the lower bounds of the {@link Insets} object according to this
- * direction
- */
- public int lower(Insets insets)
- {
- return insets.top;
- }
-
- /**
- * Returns the alignment property according to this direction.
- *
- * @param comp the Component for which to return the alignment property
- *
- * @return the alignment property according to this direction
- */
- public float alignment(Component comp)
- {
- return comp.getAlignmentY();
- }
-
- /**
- * Sets the location for Component <code>c</code>. <code>coord1</code>
- * specifies the coordinate of the location in this direction,
- * <code>coord2</code> the coordinate of the location in the opposite
- * direction.
- *
- * @param c the Component for which to set the location
- * @param coord1 the coordinate in this direction
- * @param coord2 the coordinate in the opposite direction
- */
- public void setLocation(Component c, int coord1, int coord2)
- {
- c.setLocation(coord2, coord1);
- }
-
- /**
- * Sets the size for Component <code>c</code>. <code>coord1</code>
- * specifies the size in this direction,
- * <code>coord2</code> the size in the opposite
- * direction.
- *
- * @param c the Component for which to set the size
- * @param size1 the size in this direction
- * @param size2 the size in the opposite direction
- */
- public void setSize(Component c, int size1, int size2)
- {
- c.setSize(size2, size1);
- }
- }
-
- /**
- * A helper class that temporarily stores the size specs of a component.
- */
- static class SizeReq
- {
- int size;
- int min;
- int pref;
- int max;
- float align;
- Component comp;
- SizeReq(Component comp, Direction dir)
- {
- this.min = dir.size(comp.getMinimumSize());
- this.pref = dir.size(comp.getPreferredSize());
- this.max = dir.size(comp.getMaximumSize());
- this.size = dir.size(comp.getSize());
- this.align = dir.alignment(comp);
- this.comp = comp;
- }
- }
-
- /**
* Specifies that components are laid out left to right.
*/
public static final int X_AXIS = 0;
@@ -334,16 +86,50 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
private Container container;
- /*
+ /**
* Current type of component layouting. Defaults to X_AXIS.
*/
private int way = X_AXIS;
- /** Constant for the horizontal direction. */
- private static final Direction HORIZONTAL = new Horizontal();
+ /**
+ * The size requirements of the containers children for the X direction.
+ */
+ private SizeRequirements[] xChildren;
+
+ /**
+ * The size requirements of the containers children for the Y direction.
+ */
+ private SizeRequirements[] yChildren;
+
+ /**
+ * The size requirements of the container to be laid out for the X direction.
+ */
+ private SizeRequirements xTotal;
+
+ /**
+ * The size requirements of the container to be laid out for the Y direction.
+ */
+ private SizeRequirements yTotal;
+
+ /**
+ * The offsets of the child components in the X direction.
+ */
+ private int[] offsetsX;
+
+ /**
+ * The offsets of the child components in the Y direction.
+ */
+ private int[] offsetsY;
+
+ /**
+ * The spans of the child components in the X direction.
+ */
+ private int[] spansX;
- /** Constant for the vertical direction. */
- private static final Direction VERTICAL = new Vertical();
+ /**
+ * The spans of the child components in the Y direction.
+ */
+ private int[] spansY;
/**
* Constructs a <code>BoxLayout</code> object.
@@ -355,6 +141,9 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
public BoxLayout(Container container, int way)
{
+ if (way != X_AXIS && way != Y_AXIS && way != LINE_AXIS && way != PAGE_AXIS)
+ throw new AWTError("Invalid axis");
+
int width = 0;
int height = 0;
this.container = container;
@@ -369,6 +158,7 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
public void addLayoutComponent(String name, Component component)
{
+ // Nothing to do here.
}
/**
@@ -378,6 +168,7 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
public void removeLayoutComponent(Component component)
{
+ // Nothing to do here.
}
private boolean isHorizontalIn(Container parent)
@@ -401,45 +192,16 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
public Dimension preferredLayoutSize(Container parent)
{
- if (parent != container)
- throw new AWTError("invalid parent");
-
- Insets insets = parent.getInsets();
- int x = 0;
- int y = 0;
-
- List children = AWTUtilities.getVisibleChildren(parent);
+ synchronized (container.getTreeLock())
+ {
+ if (container != parent)
+ throw new AWTError("BoxLayout can't be shared");
- if (isHorizontalIn(parent))
- {
- x = insets.left + insets.right;
- // sum up preferred widths of components, find maximum of preferred
- // heights
- for (Iterator i = children.iterator(); i.hasNext();)
- {
- Component comp = (Component) i.next();
- Dimension sz = comp.getPreferredSize();
- x += sz.width;
- y = Math.max(y, sz.height);
- }
- y += insets.bottom + insets.top;
- }
- else
- {
- y = insets.top + insets.bottom;
- // sum up preferred heights of components, find maximum of
- // preferred widths
- for (Iterator i = children.iterator(); i.hasNext();)
- {
- Component comp = (Component) i.next();
- Dimension sz = comp.getPreferredSize();
- y += sz.height;
- x = Math.max(x, sz.width);
- }
- x += insets.left + insets.right;
+ checkTotalRequirements();
+ Insets i = container.getInsets();
+ return new Dimension(xTotal.preferred + i.left + i.right,
+ yTotal.preferred + i.top + i.bottom);
}
-
- return new Dimension(x, y);
}
/**
@@ -451,41 +213,16 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
public Dimension minimumLayoutSize(Container parent)
{
- if (parent != container)
- throw new AWTError("invalid parent");
-
- Insets insets = parent.getInsets();
- int x = insets.left + insets.right;
- int y = insets.bottom + insets.top;
-
- List children = AWTUtilities.getVisibleChildren(parent);
-
- if (isHorizontalIn(parent))
+ synchronized (container.getTreeLock())
{
- // sum up preferred widths of components, find maximum of preferred
- // heights
- for (Iterator i = children.iterator(); i.hasNext();)
- {
- Component comp = (Component) i.next();
- Dimension sz = comp.getMinimumSize();
- x += sz.width;
- y = Math.max(y, sz.height);
- }
- }
- else
- {
- // sum up preferred heights of components, find maximum of
- // preferred widths
- for (Iterator i = children.iterator(); i.hasNext();)
- {
- Component comp = (Component) i.next();
- Dimension sz = comp.getMinimumSize();
- y += sz.height;
- x = Math.max(x, sz.width);
- }
+ if (container != parent)
+ throw new AWTError("BoxLayout can't be shared");
+
+ checkTotalRequirements();
+ Insets i = container.getInsets();
+ return new Dimension(xTotal.minimum + i.left + i.right,
+ yTotal.minimum + i.top + i.bottom);
}
-
- return new Dimension(x, y);
}
/**
@@ -495,12 +232,20 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
public void layoutContainer(Container parent)
{
- if (isHorizontalIn(parent))
- layoutAlgorithm(parent, HORIZONTAL, VERTICAL);
- else
- layoutAlgorithm(parent, VERTICAL, HORIZONTAL);
+ synchronized (container.getTreeLock())
+ {
+ if (container != parent)
+ throw new AWTError("BoxLayout can't be shared");
+
+ checkLayout();
+ Component[] children = container.getComponents();
+ Insets in = container.getInsets();
+ for (int i = 0; i < children.length; i++)
+ children[i].setBounds(offsetsX[i] + in.left, offsetsY[i] + in.top,
+ spansX[i], spansY[i]);
+ }
}
-
+
/**
* Adds a component to the layout. Not used in BoxLayout
*
@@ -509,6 +254,7 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
public void addLayoutComponent(Component child, Object constraints)
{
+ // Nothing to do here.
}
/**
@@ -520,10 +266,14 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
public float getLayoutAlignmentX(Container parent)
{
- if (parent != container)
- throw new AWTError("invalid parent");
-
- return 0;
+ synchronized (container.getTreeLock())
+ {
+ if (container != parent)
+ throw new AWTError("BoxLayout can't be shared");
+
+ checkTotalRequirements();
+ return xTotal.alignment;
+ }
}
/**
@@ -535,10 +285,14 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
public float getLayoutAlignmentY(Container parent)
{
- if (parent != container)
- throw new AWTError("invalid parent");
-
- return 0;
+ synchronized (container.getTreeLock())
+ {
+ if (container != parent)
+ throw new AWTError("BoxLayout can't be shared");
+
+ checkTotalRequirements();
+ return yTotal.alignment;
+ }
}
/**
@@ -548,8 +302,20 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
public void invalidateLayout(Container parent)
{
- if (parent != container)
- throw new AWTError("invalid parent");
+ if (container != parent)
+ throw new AWTError("BoxLayout can't be shared");
+
+ synchronized (container.getTreeLock())
+ {
+ xChildren = null;
+ yChildren = null;
+ xTotal = null;
+ yTotal = null;
+ offsetsX = null;
+ offsetsY = null;
+ spansX = null;
+ spansY = null;
+ }
}
/**
@@ -562,188 +328,117 @@ public class BoxLayout implements LayoutManager2, Serializable
*/
public Dimension maximumLayoutSize(Container parent)
{
- if (parent != container)
- throw new AWTError("invalid parent");
-
- Insets insets = parent.getInsets();
- int x = insets.left + insets.right;
- int y = insets.top + insets.bottom;
+ synchronized (container.getTreeLock())
+ {
+ if (container != parent)
+ throw new AWTError("BoxLayout can't be shared");
- List children = AWTUtilities.getVisibleChildren(parent);
+ checkTotalRequirements();
+ Insets i = container.getInsets();
+ return new Dimension(xTotal.maximum + i.left + i.right,
+ yTotal.maximum + i.top + i.bottom);
+ }
+ }
- if (isHorizontalIn(parent))
+ /**
+ * Makes sure that the xTotal and yTotal fields are set up correctly. A call
+ * to {@link #invalidateLayout} sets these fields to null and they have to be
+ * recomputed.
+ */
+ private void checkTotalRequirements()
+ {
+ if (xTotal == null || yTotal == null)
{
-
- // sum up preferred widths of components, find maximum of preferred
- // heights
- for (Iterator i = children.iterator(); i.hasNext();)
+ checkRequirements();
+ if (isHorizontalIn(container))
{
- Component comp = (Component) i.next();
- Dimension sz = comp.getMaximumSize();
- x += sz.width;
- // Check for overflow.
- if (x < 0)
- x = Integer.MAX_VALUE;
- y = Math.max(y, sz.height);
+ xTotal = SizeRequirements.getTiledSizeRequirements(xChildren);
+ yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren);
}
- }
- else
- {
- // sum up preferred heights of components, find maximum of
- // preferred widths
- for (Iterator i = children.iterator(); i.hasNext();)
+ else
{
- Component comp = (Component) i.next();
- Dimension sz = comp.getMaximumSize();
- y += sz.height;
- // Check for overflow
- if (y < 0)
- y = Integer.MAX_VALUE;
- x = Math.max(x, sz.width);
+ xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren);
+ yTotal = SizeRequirements.getTiledSizeRequirements(yChildren);
}
- }
- return new Dimension(x, y);
+ }
}
/**
- * Lays out the Container <code>c</code> in the layout direction
- * <code>layoutDir</code>. The direction that is crossing the layout
- * direction is specified in <code>crossDir</code>.
- *
- * @param parent
- * @param layoutDir
- * @param crossDir
+ * Makes sure that the xChildren and yChildren fields are correctly set up.
+ * A call to {@link #invalidateLayout(Container)} sets these fields to null,
+ * so they have to be set up again.
*/
- void layoutAlgorithm(Container parent, Direction layoutDir, Direction crossDir)
+ private void checkRequirements()
{
- if (parent != container)
- throw new AWTError("invalid parent");
-
- Dimension parentSize = parent.getSize();
- Insets insets = parent.getInsets();
- Dimension innerSize = new Dimension(parentSize.width - insets.left
- - insets.right, parentSize.height
- - insets.bottom - insets.top);
-
- // Set all components to their preferredSizes and sum up the allocated
- // space. Create SizeReqs for each component and store them in
- // sizeReqs. Find the maximum size in the crossing direction.
- List children = AWTUtilities.getVisibleChildren(parent);
- Vector sizeReqs = new Vector();
- int allocated = 0;
- for (Iterator i = children.iterator(); i.hasNext();)
- {
- Component c = (Component) i.next();
- SizeReq sizeReq = new SizeReq(c, layoutDir);
- int preferred = layoutDir.size(c.getPreferredSize());
- sizeReq.size = preferred;
- allocated += preferred;
- sizeReqs.add(sizeReq);
- }
-
- // Distribute remaining space (may be positive or negative) over components
- int remainder = layoutDir.size(innerSize) - allocated;
- distributeSpace(sizeReqs, remainder, layoutDir);
-
- // Resize and relocate components. If the component can be sized to
- // take the full space in the crossing direction, then do so, otherwise
- // align according to its alingnmentX or alignmentY property.
- int loc = 0;
- int offset1 = layoutDir.lower(insets);
- int offset2 = crossDir.lower(insets);
- for (Iterator i = sizeReqs.iterator(); i.hasNext();)
+ if (xChildren == null || yChildren == null)
{
- SizeReq sizeReq = (SizeReq) i.next();
- Component c = sizeReq.comp;
- int availCrossSize = crossDir.size(innerSize);
- int maxCross = crossDir.size(c.getMaximumSize());
- int crossSize = Math.min(availCrossSize, maxCross);
- int crossRemainder = availCrossSize - crossSize;
- int crossLoc = (int) (crossDir.alignment(c) * crossRemainder);
- layoutDir.setSize(c, sizeReq.size, crossSize);
- layoutDir.setLocation(c, offset1 + loc, offset2 + crossLoc);
- loc += sizeReq.size;
+ Component[] children = container.getComponents();
+ xChildren = new SizeRequirements[children.length];
+ yChildren = new SizeRequirements[children.length];
+ for (int i = 0; i < children.length; i++)
+ {
+ if (! children[i].isVisible())
+ {
+ xChildren[i] = new SizeRequirements();
+ yChildren[i] = new SizeRequirements();
+ }
+ else
+ {
+ xChildren[i] =
+ new SizeRequirements(children[i].getMinimumSize().width,
+ children[i].getPreferredSize().width,
+ children[i].getMaximumSize().width,
+ children[i].getAlignmentX());
+ yChildren[i] =
+ new SizeRequirements(children[i].getMinimumSize().height,
+ children[i].getPreferredSize().height,
+ children[i].getMaximumSize().height,
+ children[i].getAlignmentY());
+ }
+ }
}
}
/**
- * Distributes some space over a set of components. This implementation
- * tries to set the components as close as possible to their
- * <code>preferredSize</code>s, and respects the components
- * <code>minimumSize</code> and <code>maximumSize</code>.
- *
- * The algorithm is implemented as follows:
- *
- * <ul>
- * <li>The <code>remainder</code> is divided by the number of components
- * in <code>freeComponents</code>.</li>
- * <li>The result is added to (or substracted from) the size of each
- * component.</li>
- * <li>If the <code>minimumSize</code> or <code>maximumSize</code> of a
- * component is exceeded, then this component is set to its
- * <code>minimumSize</code> or <code>maximumSize</code>, it is removed from
- * <code>freeComponents</code> and the difference is added to a new
- * remainder.</li>
- * <li>Finally, if there is a new remainer != 0 and the
- * <code>freeComponents.size() != 0</code>, then this method is called
- * recursivly to distribute the newly allocated remaining space.</li>
- * </ul>
- *
- * @param freeComponents a SizeReq collection for components that have space
- * left so that they can be moved freely
- * @param remainder the space that should be distributed between the
- * components
- * @param dir the direction in which we operate
+ * Makes sure that the offsetsX, offsetsY, spansX and spansY fields are set
+ * up correctly. A call to {@link #invalidateLayout} sets these fields
+ * to null and they have to be recomputed.
*/
- void distributeSpace(Collection freeComponents, int remainder, Direction dir)
+ private void checkLayout()
{
- // Sum up total available space in components. If the remainder is negative
- // then we sum up the difference between minSize and size. If remainder
- // is positive we sum up the difference between maxSize and size.
- double totalAvailable = 0;
- for (Iterator i = freeComponents.iterator(); i.hasNext();)
- {
- SizeReq sizeReq = (SizeReq) i.next();
- if (remainder >= 0)
- totalAvailable += sizeReq.max - sizeReq.size;
- else
- totalAvailable += sizeReq.min - sizeReq.size;
- }
- if (totalAvailable == 0)
- if (remainder >= 0)
- totalAvailable = 1;
- else
- totalAvailable = -1;
-
- int newRemainder = 0;
- Vector stillFree = new Vector();
- for (Iterator i = freeComponents.iterator(); i.hasNext();)
+ if (offsetsX == null || offsetsY == null || spansX == null
+ || spansY == null)
{
- // Add/substract share to component.
- SizeReq sizeReq = (SizeReq) i.next();
- double available = 0;
- if (remainder >= 0)
- available = sizeReq.max - sizeReq.size;
+ checkRequirements();
+ checkTotalRequirements();
+ int len = container.getComponents().length;
+ offsetsX = new int[len];
+ offsetsY = new int[len];
+ spansX = new int[len];
+ spansY = new int[len];
+
+ Insets in = container.getInsets();
+ int width = container.getWidth() - in.left - in.right;
+ int height = container.getHeight() - in.top -in.bottom;
+
+ if (isHorizontalIn(container))
+ {
+ SizeRequirements.calculateTiledPositions(width,
+ xTotal, xChildren,
+ offsetsX, spansX);
+ SizeRequirements.calculateAlignedPositions(height,
+ yTotal, yChildren,
+ offsetsY, spansY);
+ }
else
- available = sizeReq.min - sizeReq.size;
- int share = (int) ((available / totalAvailable) * remainder);
- sizeReq.size += share;
- // check for min/maximumSize
- if (sizeReq.size < sizeReq.min)
- {
- newRemainder += sizeReq.size - sizeReq.min;
- sizeReq.size = sizeReq.min;
- }
- else if (sizeReq.size > sizeReq.max)
- {
- newRemainder += sizeReq.size - sizeReq.max;
- sizeReq.size = sizeReq.max;
- }
- else
- stillFree.add(sizeReq);
+ {
+ SizeRequirements.calculateAlignedPositions(width,
+ xTotal, xChildren,
+ offsetsX, spansX);
+ SizeRequirements.calculateTiledPositions(height,
+ yTotal, yChildren,
+ offsetsY, spansY);
+ }
}
- // recursivly call this method if necessary
- if (newRemainder != 0 && stillFree.size() > 0)
- distributeSpace(stillFree, newRemainder, dir);
}
}
diff --git a/libjava/classpath/javax/swing/ButtonGroup.java b/libjava/classpath/javax/swing/ButtonGroup.java
index 3de1d4b9f16..94f0109e634 100644
--- a/libjava/classpath/javax/swing/ButtonGroup.java
+++ b/libjava/classpath/javax/swing/ButtonGroup.java
@@ -79,6 +79,7 @@ public class ButtonGroup implements Serializable
*/
public ButtonGroup()
{
+ // Nothing to do here.
}
/**
@@ -89,6 +90,8 @@ public class ButtonGroup implements Serializable
public void add(AbstractButton b)
{
b.getModel().setGroup(this);
+ if (b.isSelected())
+ sel = b.getModel();
buttons.addElement(b);
}
@@ -158,7 +161,7 @@ public class ButtonGroup implements Serializable
{
ButtonModel old = sel;
sel = m;
-
+
if (old != null)
old.setSelected(false);
AbstractButton button = FindButton(old);
diff --git a/libjava/classpath/javax/swing/ButtonModel.java b/libjava/classpath/javax/swing/ButtonModel.java
index 1bdc5d1850d..03fac13d2fa 100644
--- a/libjava/classpath/javax/swing/ButtonModel.java
+++ b/libjava/classpath/javax/swing/ButtonModel.java
@@ -49,37 +49,253 @@ import javax.swing.event.ChangeListener;
*/
public interface ButtonModel extends ItemSelectable
{
- boolean isArmed();
- void setArmed(boolean b);
+ /**
+ * Returns <code>true</code> if the button is armed, <code>false</code>
+ * otherwise.
+ *
+ * A button is armed, when the user has pressed the mouse over it, but has
+ * not yet released the mouse.
+ *
+ * @return <code>true</code> if the button is armed, <code>false</code>
+ * otherwise
+ *
+ * @see #setArmed(boolean)
+ */
+ boolean isArmed();
- boolean isEnabled();
- void setEnabled(boolean b);
+ /**
+ * Sets the armed flag of the button.
+ *
+ * A button is armed, when the user has pressed the mouse over it, but has
+ * not yet released the mouse.
+ *
+ * @param b <code>true</code> if the button is armed, <code>false</code>
+ * otherwise
+ *
+ * @see #isArmed()
+ */
+ void setArmed(boolean b);
- void setPressed(boolean b);
- boolean isPressed();
+ /**
+ * Returns <code>true</code> if the button is enabled, <code>false</code>
+ * otherwise.
+ *
+ * When a button is disabled, it is usually grayed out and the user cannot
+ * change its state.
+ *
+ * @return <code>true</code> if the button is enabled, <code>false</code>
+ * otherwise
+ *
+ * @see #setEnabled(boolean)
+ */
+ boolean isEnabled();
+ /**
+ * Sets the enabled flag of the button.
+ *
+ * When a button is disabled, it is usually grayed out and the user cannot
+ * change its state.
+ *
+ * @param b <code>true</code> if the button is enabled, <code>false</code>
+ * otherwise
+ *
+ * @see #isEnabled()
+ */
+ void setEnabled(boolean b);
- void removeActionListener(ActionListener l);
- void addActionListener(ActionListener l);
+ /**
+ * Sets the pressed flag of the button.
+ *
+ * The button usually gets pressed when the user clicks on a button, it will
+ * be un-pressed when the user releases the mouse.
+ *
+ * @param b <code>true</code> if the button is pressed, <code>false</code>
+ * otherwise
+ *
+ * @see #isPressed()
+ */
+ void setPressed(boolean b);
- void addItemListener(ItemListener l);
- void removeItemListener(ItemListener l);
-
- void addChangeListener(ChangeListener l);
- void removeChangeListener(ChangeListener l);
+ /**
+ * Returns <code>true</code> if the button is pressed, <code>false</code>
+ * otherwise.
+ *
+ * The button usually gets pressed when the user clicks on a button, it will
+ * be un-pressed when the user releases the mouse.
+ *
+ * @return <code>true</code> if the button is pressed, <code>false</code>
+ * otherwise
+ *
+ * @see #setPressed(boolean)
+ */
+ boolean isPressed();
- void setRollover(boolean b);
- boolean isRollover();
+ /**
+ * Removes an {@link ActionListener} from the list of registered listeners.
+ *
+ * @param l the action listener to remove
+ *
+ * @see #addActionListener(ActionListener)
+ */
+ void removeActionListener(ActionListener l);
- int getMnemonic();
- void setMnemonic(int key);
+ /**
+ * Adds an {@link ActionListener} to the list of registered listeners.
+ *
+ * An <code>ActionEvent</code> is usually fired when the user clicks on a
+ * button.
+ *
+ * @param l the action listener to add
+ *
+ * @see #removeActionListener(ActionListener)
+ */
+ void addActionListener(ActionListener l);
- void setActionCommand(String s);
- String getActionCommand();
+ /**
+ * Adds an {@link ItemListener} to the list of registered listeners.
+ *
+ * An <code>ItemEvent</code> is usually fired when a button's selected
+ * state changes. This applies only to buttons that support the selected
+ * flag.
+ *
+ * @param l the item listener to add
+ *
+ * @see #removeItemListener(ItemListener)
+ */
+ void addItemListener(ItemListener l);
- void setGroup(ButtonGroup group);
+ /**
+ * Adds an {@link ItemListener} to the list of registered listeners.
+ *
+ * @param l the item listener to add
+ *
+ * @see #removeItemListener(ItemListener)
+ */
+ void removeItemListener(ItemListener l);
- void setSelected(boolean b);
- boolean isSelected();
+ /**
+ * Adds an {@link ChangeListener} to the list of registered listeners.
+ *
+ * A <code>ChangeEvent</code> is fired when any one of the button's flags
+ * changes.
+ *
+ * @param l the change listener to add
+ *
+ * @see #removeChangeListener(ChangeListener)
+ */
+ void addChangeListener(ChangeListener l);
+
+ /**
+ * Adds an {@link ChangeListener} to the list of registered listeners.
+ *
+ * @param l the change listener to add
+ *
+ * @see #removeChangeListener(ChangeListener)
+ */
+ void removeChangeListener(ChangeListener l);
+
+ /**
+ * Sets the rollover flag of the button.
+ *
+ * A button is rollover-ed, when the user has moved the mouse over it, but has
+ * not yet pressed the mouse.
+ *
+ * @param b <code>true</code> if the button is rollover, <code>false</code>
+ * otherwise
+ *
+ * @see #isRollover()
+ */
+ void setRollover(boolean b);
+
+ /**
+ * Returns <code>true</code> if the button is rollover-ed, <code>false</code>
+ * otherwise.
+ *
+ * A button is rollover-ed, when the user has moved the mouse over it, but has
+ * not yet pressed the mouse.
+ *
+ * @return <code>true</code> if the button is rollover, <code>false</code>
+ * otherwise
+ *
+ * @see #setRollover(boolean)
+ */
+ boolean isRollover();
+
+ /**
+ * Returns the keyboard mnemonic for the button. This specifies a shortcut
+ * or accelerator key that can be used to activate the button.
+ *
+ * @return the keyboard mnemonic for the button
+ *
+ * @see #setMnemonic(int)
+ */
+ int getMnemonic();
+
+ /**
+ * Sets the keyboard mnemonic for the button. This specifies a shortcut
+ * or accelerator key that can be used to activate the button.
+ *
+ * @param key the keyboard mnemonic for the button
+ *
+ * @see #getMnemonic()
+ */
+ void setMnemonic(int key);
+
+ /**
+ * Sets the action command for the button. This will be used in
+ * <code>ActionEvents</code> fired by the button.
+ *
+ * @param s the action command to set
+ *
+ * @see #getActionCommand()
+ */
+ void setActionCommand(String s);
+
+ /**
+ * Returns the action command of the button.
+ *
+ * @return the action command of the button
+ *
+ * @see #setActionCommand(String)
+ */
+ String getActionCommand();
+
+ /**
+ * Sets the button group for the button. Some kinds of button (e.g. radio
+ * buttons) allow only one button within a button group selected at any one
+ * time.
+ *
+ * @param group the button group to set
+ */
+ void setGroup(ButtonGroup group);
+
+ /**
+ * Sets the selected flag of the button.
+ *
+ * Some kinds of buttons (e.g. toggle buttons, check boxes, radio buttons)
+ * can be in one of two states: selected or unselected. The selected state
+ * is usually toggled by clicking on the button.
+ *
+ * @param b <code>true</code> if the button is selected, <code>false</code>
+ * otherwise
+ *
+ * @see #isSelected()
+ */
+ void setSelected(boolean b);
+
+ /**
+ * Returns <code>true</code> if the button is selected, <code>false</code>
+ * otherwise.
+ *
+ * Some kinds of buttons (e.g. toggle buttons, check boxes, radio buttons)
+ * can be in one of two states: selected or unselected. The selected state
+ * is usually toggled by clicking on the button.
+ *
+ * @return <code>true</code> if the button is selected, <code>false</code>
+ * otherwise
+ *
+ * @see #setSelected(boolean)
+ */
+ boolean isSelected();
}
diff --git a/libjava/classpath/javax/swing/CellEditor.java b/libjava/classpath/javax/swing/CellEditor.java
index bdb1665750d..3d229b26675 100644
--- a/libjava/classpath/javax/swing/CellEditor.java
+++ b/libjava/classpath/javax/swing/CellEditor.java
@@ -83,7 +83,7 @@ public interface CellEditor
/**
* addCellEditorListener
- * @param value0 TODO
+ * @param listener TODO
*/
void addCellEditorListener(CellEditorListener listener);
diff --git a/libjava/classpath/javax/swing/CellRendererPane.java b/libjava/classpath/javax/swing/CellRendererPane.java
index 886d5c5f2a8..c59afd3188a 100644
--- a/libjava/classpath/javax/swing/CellRendererPane.java
+++ b/libjava/classpath/javax/swing/CellRendererPane.java
@@ -54,9 +54,7 @@ import javax.accessibility.AccessibleRole;
*
* @author Andrew Selkirk
*/
-public class CellRendererPane
- extends Container
- implements Accessible
+public class CellRendererPane extends Container implements Accessible
{
private static final long serialVersionUID = -7642183829532984273L;
@@ -72,6 +70,7 @@ public class CellRendererPane
*/
protected AccessibleCellRendererPane()
{
+ // Nothing to do here.
}
/**
@@ -89,22 +88,13 @@ public class CellRendererPane
*/
protected AccessibleContext accessibleContext = null;
-
- //-------------------------------------------------------------
- // Initialization ---------------------------------------------
- //-------------------------------------------------------------
-
/**
* Constructs a new CellRendererPane.
*/
public CellRendererPane()
{
- } // CellRendererPane()
-
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
+ // Nothing to do here.
+ }
/**
* Should not be called.
@@ -113,7 +103,8 @@ public class CellRendererPane
*/
public void update(Graphics graphics)
{
- } // update()
+ //Nothing to do here.
+ }
/**
* Despite normal behaviour this does <em>not</em> cause the container
@@ -121,7 +112,8 @@ public class CellRendererPane
*/
public void invalidate()
{
- } // invalidate()
+ // Overridden to do nothing.
+ }
/**
* Should not be called.
@@ -130,6 +122,7 @@ public class CellRendererPane
*/
public void paint(Graphics graphics)
{
+ // Overridden to do nothing.
}
/**
@@ -147,7 +140,7 @@ public class CellRendererPane
{
super.addImpl(c, constraints, index);
}
- } // addImpl()
+ }
/**
* Paints the specified component <code>c</code> on the {@link Graphics}
@@ -175,9 +168,10 @@ public class CellRendererPane
// reparent c
addImpl(c, null, 0);
+ Rectangle oldClip = graphics.getClipBounds();
// translate to (x,y)
graphics.translate(x, y);
-
+ graphics.clipRect(0, 0, w, h);
// set bounds of c
c.setBounds(0, 0, w, h);
@@ -192,8 +186,8 @@ public class CellRendererPane
// untranslate g
graphics.translate(-x, -y);
-
- } // paintComponent()
+ graphics.setClip(oldClip);
+ }
/**
* Paints the specified component <code>c</code> on the {@link Graphics}
@@ -215,7 +209,7 @@ public class CellRendererPane
Container p, int x, int y, int w, int h)
{
paintComponent(graphics, c, p, x, y, w, h, false);
- } // paintComponent()
+ }
/**
* Paints the specified component <code>c</code> on the {@link Graphics}
@@ -233,7 +227,7 @@ public class CellRendererPane
Container p, Rectangle r)
{
paintComponent(graphics, c, p, r.x, r.y, r.width, r.height);
- } // paintComponent()
+ }
/**
* getAccessibleContext <em>TODO</em>
diff --git a/libjava/classpath/javax/swing/ComboBoxEditor.java b/libjava/classpath/javax/swing/ComboBoxEditor.java
index 4eb5fc56206..8e914e4b9fe 100644
--- a/libjava/classpath/javax/swing/ComboBoxEditor.java
+++ b/libjava/classpath/javax/swing/ComboBoxEditor.java
@@ -64,7 +64,7 @@ public interface ComboBoxEditor
* combo box list then this method should be called to change editting item
* to the new selected item.
*
- * @param selectedItem item that is currently selected in the combo box
+ * @param item item that is currently selected in the combo box
*/
void setItem(Object item);
diff --git a/libjava/classpath/javax/swing/ComponentInputMap.java b/libjava/classpath/javax/swing/ComponentInputMap.java
index f95c3104535..28aa8e22cf6 100644
--- a/libjava/classpath/javax/swing/ComponentInputMap.java
+++ b/libjava/classpath/javax/swing/ComponentInputMap.java
@@ -78,7 +78,8 @@ public class ComponentInputMap extends InputMap
public void put(KeyStroke keystroke, Object value)
{
super.put(keystroke, value);
- // FIXME: Notify component.
+ if (component != null)
+ component.updateComponentInputMap(this);
}
/**
@@ -87,7 +88,8 @@ public class ComponentInputMap extends InputMap
public void clear()
{
super.clear();
- // FIXME: Notify component.
+ if (component != null)
+ component.updateComponentInputMap(this);
}
/**
@@ -98,7 +100,8 @@ public class ComponentInputMap extends InputMap
public void remove(KeyStroke keystroke)
{
super.remove(keystroke);
- // FIXME: Notify component.
+ if (component != null)
+ component.updateComponentInputMap(this);
}
/**
@@ -111,14 +114,19 @@ public class ComponentInputMap extends InputMap
*/
public void setParent(InputMap parentMap)
{
- if (! (parentMap instanceof ComponentInputMap))
- throw new IllegalArgumentException();
-
- if (((ComponentInputMap) parentMap).getComponent() != component)
- throw new IllegalArgumentException();
+ if (parentMap != null && !(parentMap instanceof ComponentInputMap))
+ throw new IllegalArgumentException("ComponentInputMaps can only have " +
+ "ComponentInputMaps for parents");
+
+ if (parentMap != null &&
+ ((ComponentInputMap) parentMap).getComponent() != component)
+ throw new
+ IllegalArgumentException("ComponentInputMaps' parents must " +
+ "be associated with the same JComponents");
super.setParent(parentMap);
- // FIXME: Notify component.
+ if (component != null)
+ component.updateComponentInputMap(this);
}
/**
diff --git a/libjava/classpath/javax/swing/DebugGraphics.java b/libjava/classpath/javax/swing/DebugGraphics.java
index 137b82337af..126309a5844 100644
--- a/libjava/classpath/javax/swing/DebugGraphics.java
+++ b/libjava/classpath/javax/swing/DebugGraphics.java
@@ -42,6 +42,7 @@ import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
+import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.image.ImageObserver;
@@ -84,15 +85,16 @@ public class DebugGraphics extends Graphics
static PrintStream debugLogStream = System.out;
/**
- * graphics
+ * Counts the created DebugGraphics objects. This is used by the
+ * logging facility.
*/
- Graphics graphics;
+ static int counter = 0;
/**
- * color
+ * graphics
*/
- Color color = Color.BLACK;
-
+ Graphics graphics;
+
/**
* buffer
*/
@@ -123,7 +125,7 @@ public class DebugGraphics extends Graphics
*/
public DebugGraphics()
{
- // TODO
+ counter++;
}
/**
@@ -134,7 +136,7 @@ public class DebugGraphics extends Graphics
*/
public DebugGraphics(Graphics graphics, JComponent component)
{
- this.graphics = graphics;
+ this(graphics);
// FIXME: What shall we do with component ?
}
@@ -145,6 +147,7 @@ public class DebugGraphics extends Graphics
*/
public DebugGraphics(Graphics graphics)
{
+ this();
this.graphics = graphics;
}
@@ -155,7 +158,10 @@ public class DebugGraphics extends Graphics
*/
public void setColor(Color color)
{
- this.color = color;
+ if ((debugOptions & LOG_OPTION) != 0)
+ logStream().println(prefix() + " Setting color: " + color);
+
+ graphics.setColor(color);
}
/**
@@ -166,7 +172,9 @@ public class DebugGraphics extends Graphics
*/
public Graphics create()
{
- return new DebugGraphics(graphics.create());
+ DebugGraphics copy = new DebugGraphics(graphics.create());
+ copy.debugOptions = debugOptions;
+ return copy;
}
/**
@@ -182,7 +190,10 @@ public class DebugGraphics extends Graphics
*/
public Graphics create(int x, int y, int width, int height)
{
- return new DebugGraphics(graphics.create(x, y, width, height));
+ DebugGraphics copy = new DebugGraphics(graphics.create(x, y, width,
+ height));
+ copy.debugOptions = debugOptions;
+ return copy;
}
/**
@@ -282,6 +293,9 @@ public class DebugGraphics extends Graphics
*/
public void setFont(Font font)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ logStream().println(prefix() + " Setting font: " + font);
+
graphics.setFont(font);
}
@@ -292,7 +306,7 @@ public class DebugGraphics extends Graphics
*/
public Color getColor()
{
- return color;
+ return graphics.getColor();
}
/**
@@ -325,6 +339,9 @@ public class DebugGraphics extends Graphics
*/
public void translate(int x, int y)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ logStream().println(prefix() + " Translating by: " + new Point(x, y));
+
graphics.translate(x, y);
}
@@ -333,6 +350,9 @@ public class DebugGraphics extends Graphics
*/
public void setPaintMode()
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ logStream().println(prefix() + " Setting paint mode");
+
graphics.setPaintMode();
}
@@ -343,6 +363,9 @@ public class DebugGraphics extends Graphics
*/
public void setXORMode(Color color)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ logStream().println(prefix() + " Setting XOR mode: " + color);
+
graphics.setXORMode(color);
}
@@ -366,7 +389,16 @@ public class DebugGraphics extends Graphics
*/
public void clipRect(int x, int y, int width, int height)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().print(prefix() + " Setting clipRect: "
+ + new Rectangle(x, y, width, height));
+ }
+
graphics.clipRect(x, y, width, height);
+
+ if ((debugOptions & LOG_OPTION) != 0)
+ logStream().println(" Netting clipRect: " + graphics.getClipBounds());
}
/**
@@ -379,6 +411,12 @@ public class DebugGraphics extends Graphics
*/
public void setClip(int x, int y, int width, int height)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Setting new clipRect: "
+ + new Rectangle(x, y, width, height));
+ }
+
graphics.setClip(x, y, width, height);
}
@@ -399,6 +437,9 @@ public class DebugGraphics extends Graphics
*/
public void setClip(Shape shape)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ logStream().println(prefix() + " Setting new clipRect: " + shape);
+
graphics.setClip(shape);
}
@@ -424,18 +465,27 @@ public class DebugGraphics extends Graphics
*/
public void drawRect(int x, int y, int width, int height)
{
- for (int index = 0; index < (debugFlashCount - 1); ++index)
+ if ((debugOptions & LOG_OPTION) != 0)
{
- graphics.setColor(color);
- graphics.drawRect(x, y, width, height);
- sleep(debugFlashTime);
+ logStream().println(prefix() + " Drawing rect: "
+ + new Rectangle(x, y, width, height));
+ }
- graphics.setColor(debugFlashColor);
- graphics.drawRect(x, y, width, height);
- sleep(debugFlashTime);
+ if ((debugOptions & FLASH_OPTION) != 0)
+ {
+ Color color = graphics.getColor();
+ for (int index = 0; index < (debugFlashCount - 1); ++index)
+ {
+ graphics.setColor(color);
+ graphics.drawRect(x, y, width, height);
+ sleep(debugFlashTime);
+ graphics.setColor(debugFlashColor);
+ graphics.drawRect(x, y, width, height);
+ sleep(debugFlashTime);
+ }
+ graphics.setColor(color);
}
- graphics.setColor(color);
graphics.drawRect(x, y, width, height);
}
@@ -449,18 +499,27 @@ public class DebugGraphics extends Graphics
*/
public void fillRect(int x, int y, int width, int height)
{
- for (int index = 0; index < (debugFlashCount - 1); ++index)
+ if ((debugOptions & LOG_OPTION) != 0)
{
- graphics.setColor(color);
- graphics.fillRect(x, y, width, height);
- sleep(debugFlashTime);
+ logStream().println(prefix() + " Filling rect: "
+ + new Rectangle(x, y, width, height));
+ }
- graphics.setColor(debugFlashColor);
- graphics.fillRect(x, y, width, height);
- sleep(debugFlashTime);
+ if ((debugOptions & FLASH_OPTION) != 0)
+ {
+ Color color = graphics.getColor();
+ for (int index = 0; index < (debugFlashCount - 1); ++index)
+ {
+ graphics.setColor(color);
+ graphics.fillRect(x, y, width, height);
+ sleep(debugFlashTime);
+ graphics.setColor(debugFlashColor);
+ graphics.fillRect(x, y, width, height);
+ sleep(debugFlashTime);
+ }
+ graphics.setColor(color);
}
- graphics.setColor(color);
graphics.fillRect(x, y, width, height);
}
@@ -474,6 +533,12 @@ public class DebugGraphics extends Graphics
*/
public void clearRect(int x, int y, int width, int height)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Clearing rect: "
+ + new Rectangle(x, y, width, height));
+ }
+
graphics.clearRect(x, y, width, height);
}
@@ -490,6 +555,14 @@ public class DebugGraphics extends Graphics
public void drawRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing round rect: "
+ + new Rectangle(x, y, width, height)
+ + " arcWidth: " + arcWidth
+ + " arcHeight: " + arcHeight);
+ }
+
graphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
}
@@ -506,6 +579,14 @@ public class DebugGraphics extends Graphics
public void fillRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Filling round rect: "
+ + new Rectangle(x, y, width, height)
+ + " arcWidth: " + arcWidth
+ + " arcHeight: " + arcHeight);
+ }
+
graphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
}
@@ -519,6 +600,12 @@ public class DebugGraphics extends Graphics
*/
public void drawLine(int x1, int y1, int x2, int y2)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing line: from (" + x1 + ", "
+ + y1 + ") to (" + x2 + ", " + y2 + ")");
+ }
+
graphics.drawLine(x1, y1, x2, y2);
}
@@ -533,6 +620,13 @@ public class DebugGraphics extends Graphics
*/
public void draw3DRect(int x, int y, int width, int height, boolean raised)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing 3D rect: "
+ + new Rectangle(x, y, width, height)
+ + "Raised bezel: " + raised);
+ }
+
graphics.draw3DRect(x, y, width, height, raised);
}
@@ -547,6 +641,13 @@ public class DebugGraphics extends Graphics
*/
public void fill3DRect(int x, int y, int width, int height, boolean raised)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Filling 3D rect: "
+ + new Rectangle(x, y, width, height)
+ + "Raised bezel: " + raised);
+ }
+
graphics.fill3DRect(x, y, width, height, raised);
}
@@ -560,6 +661,12 @@ public class DebugGraphics extends Graphics
*/
public void drawOval(int x, int y, int width, int height)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing oval: "
+ + new Rectangle(x, y, width, height));
+ }
+
graphics.drawOval(x, y, width, height);
}
@@ -573,6 +680,12 @@ public class DebugGraphics extends Graphics
*/
public void fillOval(int x, int y, int width, int height)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Filling oval: "
+ + new Rectangle(x, y, width, height));
+ }
+
graphics.fillOval(x, y, width, height);
}
@@ -589,6 +702,14 @@ public class DebugGraphics extends Graphics
public void drawArc(int x, int y, int width, int height,
int startAngle, int arcAngle)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing arc: "
+ + new Rectangle(x, y, width, height)
+ + " startAngle: " + startAngle
+ + " arcAngle: " + arcAngle);
+ }
+
graphics.drawArc(x, y, width, height, startAngle, arcAngle);
}
@@ -605,6 +726,14 @@ public class DebugGraphics extends Graphics
public void fillArc(int x, int y, int width, int height,
int startAngle, int arcAngle)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Filling arc: "
+ + new Rectangle(x, y, width, height)
+ + " startAngle: " + startAngle
+ + " arcAngle: " + arcAngle);
+ }
+
graphics.fillArc(x, y, width, height, startAngle, arcAngle);
}
@@ -617,6 +746,12 @@ public class DebugGraphics extends Graphics
*/
public void drawPolyline(int[] xpoints, int[] ypoints, int npoints)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing polyline: nPoints: " + npoints
+ + " X's: " + xpoints + " Y's: " + ypoints);
+ }
+
graphics.drawPolyline(xpoints, ypoints, npoints);
}
@@ -629,6 +764,12 @@ public class DebugGraphics extends Graphics
*/
public void drawPolygon(int[] xpoints, int[] ypoints, int npoints)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing polygon: nPoints: " + npoints
+ + " X's: " + xpoints + " Y's: " + ypoints);
+ }
+
graphics.drawPolygon(xpoints, ypoints, npoints);
}
@@ -641,6 +782,12 @@ public class DebugGraphics extends Graphics
*/
public void fillPolygon(int[] xpoints, int[] ypoints, int npoints)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing polygon: nPoints: " + npoints
+ + " X's: " + xpoints + " Y's: " + ypoints);
+ }
+
graphics.fillPolygon(xpoints, ypoints, npoints);
}
@@ -653,6 +800,12 @@ public class DebugGraphics extends Graphics
*/
public void drawString(String string, int x, int y)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing string: \"" + string
+ + "\" at: " + new Point(x, y));
+ }
+
graphics.drawString(string, x, y);
}
@@ -666,6 +819,12 @@ public class DebugGraphics extends Graphics
public void drawString(AttributedCharacterIterator iterator,
int x, int y)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing string: \"" + iterator
+ + "\" at: " + new Point(x, y));
+ }
+
graphics.drawString(iterator, x, y);
}
@@ -681,6 +840,9 @@ public class DebugGraphics extends Graphics
public void drawBytes(byte[] data, int offset, int length,
int x, int y)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ logStream().println(prefix() + " Drawing bytes at: " + new Point(x, y));
+
graphics.drawBytes(data, offset, length, x, y);
}
@@ -696,18 +858,24 @@ public class DebugGraphics extends Graphics
public void drawChars(char[] data, int offset, int length,
int x, int y)
{
- for (int index = 0; index < (debugFlashCount - 1); ++index)
+ if ((debugOptions & LOG_OPTION) != 0)
+ logStream().println(prefix() + " Drawing chars at: " + new Point(x, y));
+
+ if ((debugOptions & FLASH_OPTION) != 0)
{
+ Color color = graphics.getColor();
+ for (int index = 0; index < (debugFlashCount - 1); ++index)
+ {
+ graphics.setColor(color);
+ graphics.drawChars(data, offset, length, x, y);
+ sleep(debugFlashTime);
+ graphics.setColor(debugFlashColor);
+ graphics.drawChars(data, offset, length, x, y);
+ sleep(debugFlashTime);
+ }
graphics.setColor(color);
- graphics.drawChars(data, offset, length, x, y);
- sleep(debugFlashTime);
-
- graphics.setColor(debugFlashColor);
- graphics.drawChars(data, offset, length, x, y);
- sleep(debugFlashTime);
}
- graphics.setColor(color);
graphics.drawChars(data, offset, length, x, y);
}
@@ -723,6 +891,12 @@ public class DebugGraphics extends Graphics
public boolean drawImage(Image image, int x, int y,
ImageObserver observer)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing image: " + image + " at: "
+ + new Point(x, y));
+ }
+
return graphics.drawImage(image, x, y, observer);
}
@@ -741,6 +915,12 @@ public class DebugGraphics extends Graphics
public boolean drawImage(Image image, int x, int y, int width,
int height, ImageObserver observer)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing image: " + image
+ + " at: " + new Rectangle(x, y, width, height));
+ }
+
return graphics.drawImage(image, x, y, width, height, observer);
}
@@ -759,6 +939,13 @@ public class DebugGraphics extends Graphics
public boolean drawImage(Image image, int x, int y,
Color background, ImageObserver observer)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing image: " + image
+ + " at: " + new Point(x, y)
+ + ", bgcolor: " + background);
+ }
+
return graphics.drawImage(image, x, y, background, observer);
}
@@ -779,6 +966,13 @@ public class DebugGraphics extends Graphics
public boolean drawImage(Image image, int x, int y, int width, int height,
Color background, ImageObserver observer)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing image: " + image
+ + " at: " + new Rectangle(x, y, width, height)
+ + ", bgcolor: " + background);
+ }
+
return graphics.drawImage(image, x, y, width, height, background, observer);
}
@@ -802,6 +996,13 @@ public class DebugGraphics extends Graphics
int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
ImageObserver observer)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing image: " + image
+ + " destination: " + new Rectangle(dx1, dy1, dx2, dy2)
+ + " source: " + new Rectangle(sx1, sy1, sx2, sy2));
+ }
+
return graphics.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
}
@@ -827,6 +1028,14 @@ public class DebugGraphics extends Graphics
int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
Color background, ImageObserver observer)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Drawing image: " + image
+ + " destination: " + new Rectangle(dx1, dy1, dx2, dy2)
+ + " source: " + new Rectangle(sx1, sy1, sx2, sy2)
+ + ", bgcolor: " + background);
+ }
+
return graphics.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, background, observer);
}
@@ -843,6 +1052,13 @@ public class DebugGraphics extends Graphics
public void copyArea(int x, int y, int width, int height,
int destx, int desty)
{
+ if ((debugOptions & LOG_OPTION) != 0)
+ {
+ logStream().println(prefix() + " Copying area from: "
+ + new Rectangle(x, y, width, height)
+ + " to: " + new Point(destx, desty));
+ }
+
graphics.copyArea(x, y, width, height, destx, desty);
}
@@ -873,6 +1089,11 @@ public class DebugGraphics extends Graphics
public void setDebugOptions(int options)
{
debugOptions = options;
+ if ((debugOptions & LOG_OPTION) != 0)
+ if (options == NONE_OPTION)
+ logStream().println(prefix() + "Disabling debug");
+ else
+ logStream().println(prefix() + "Enabling debug");
}
/**
@@ -884,4 +1105,21 @@ public class DebugGraphics extends Graphics
{
return debugOptions;
}
+
+ /**
+ * Creates and returns the prefix that should be prepended to all logging
+ * messages. The prefix is made up like this:
+ *
+ * <code>Graphics(<counter>-1)</code> where counter is an integer number
+ * saying how many DebugGraphics objects have been created so far. The second
+ * number always seem to be 1 on Sun's JDK, this has to be investigated a
+ * little more.
+ *
+ * @return the prefix that should be prepended to all logging
+ * messages
+ */
+ private String prefix()
+ {
+ return "Graphics(" + counter + "-1)";
+ }
}
diff --git a/libjava/classpath/javax/swing/DefaultButtonModel.java b/libjava/classpath/javax/swing/DefaultButtonModel.java
index f7d09d5780d..7ecf3b85fc6 100644
--- a/libjava/classpath/javax/swing/DefaultButtonModel.java
+++ b/libjava/classpath/javax/swing/DefaultButtonModel.java
@@ -145,6 +145,7 @@ public class DefaultButtonModel implements ButtonModel, Serializable
*/
public DefaultButtonModel()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/DefaultCellEditor.java b/libjava/classpath/javax/swing/DefaultCellEditor.java
index 00e00864432..39e48551efb 100644
--- a/libjava/classpath/javax/swing/DefaultCellEditor.java
+++ b/libjava/classpath/javax/swing/DefaultCellEditor.java
@@ -69,7 +69,7 @@ public class DefaultCellEditor
private static final long serialVersionUID = 3564035141373880027L;
/**
- * Delegates a couple of method calls (such as {@link #isCellEditable)
+ * Delegates a couple of method calls (such as {@link #isCellEditable}
* to the component it contains and listens for events that indicate
* that editing has stopped.
*/
@@ -88,12 +88,13 @@ public class DefaultCellEditor
*/
protected EditorDelegate()
{
+ // Nothing to do here.
}
/**
* setValue
*
- * @param event TODO
+ * @param value TODO
*/
public void setValue(Object value)
{
@@ -387,7 +388,7 @@ public class DefaultCellEditor
/**
* getTableCellEditorComponent
*
- * @param tree TODO
+ * @param table TODO
* @param value TODO
* @param isSelected TODO
* @param row TODO
diff --git a/libjava/classpath/javax/swing/DefaultComboBoxModel.java b/libjava/classpath/javax/swing/DefaultComboBoxModel.java
index b48b968d697..ea261a33bbf 100644
--- a/libjava/classpath/javax/swing/DefaultComboBoxModel.java
+++ b/libjava/classpath/javax/swing/DefaultComboBoxModel.java
@@ -1,5 +1,5 @@
/* DefaultComboBoxModel.java --
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,13 +41,14 @@ import java.io.Serializable;
import java.util.Arrays;
import java.util.Vector;
+import javax.swing.event.ListDataEvent;
+
/**
- * The default implementation of {@link MutableComboBoxModel}.
- * This model keeps track
- * of elements contained in the JComboBox as well as the current combo box
- * selection. Whenever selection in the JComboBox changes, the ComboBoxModel
- * will fire ListDataEvents to ComboBox's ListDataListeners.
+ * A model that stores a list of elements and a selected item (which may be
+ * <code>null</code>). Changes to the model are signalled to listeners using
+ * {@link ListDataEvent}. This model is designed for use by the
+ * {@link JComboBox} component.
*
* @author Andrew Selkirk
* @author Olga Rodimina
@@ -59,17 +60,17 @@ public class DefaultComboBoxModel extends AbstractListModel
private static final long serialVersionUID = 6698657703676921904L;
/**
- * List containing items in the combo box
+ * Storage for the elements in the model's list.
*/
private Vector list;
/**
- * Currently selected item in the combo box list
+ * The selected item (<code>null</code> indicates no selection).
*/
private Object selectedItem = null;
/**
- * Constructor DefaultComboBoxModel. Create empty JComboBox.
+ * Creates a new model, initially empty.
*/
public DefaultComboBoxModel()
{
@@ -77,64 +78,92 @@ public class DefaultComboBoxModel extends AbstractListModel
}
/**
- * Constructs new DefaultComboBoxModel object and initializes its item list
- * to values in the given array.
+ * Creates a new model and initializes its item list to the values in the
+ * given array. The selected item is set to the first item in the array, or
+ * <code>null</code> if the array length is zero.
*
- * @param items array containing items of the combo box.
+ * @param items an array containing items for the model (<code>null</code>
+ * not permitted).
+ *
+ * @throws NullPointerException if <code>items</code> is <code>null</code>.
*/
public DefaultComboBoxModel(Object[] items)
{
list = new Vector(Arrays.asList(items));
+ if (list.size() > 0)
+ selectedItem = list.get(0);
}
/**
- * Consturcts new DefaultComboBoxModel object and initializes its item list
- * to values in the given vector.
+ * Creates a new model and initializes its item list to the values in the
+ * given vector. The selected item is set to the first item in the vector,
+ * or <code>null</code> if the vector length is zero.
*
- * @param vector Vector containing items for this combo box.
+ * @param vector a vector containing items for the model (<code>null</code>
+ * not permitted).
+ *
+ * @throws NullPointerException if <code>vector</code> is <code>null</code>.
*/
public DefaultComboBoxModel(Vector vector)
{
this.list = vector;
+ if (vector.size() > 0)
+ selectedItem = vector.get(0);
}
/**
- * This method adds element to the combo box list. It fires ListDataEvent
- * indicating that component was added to the combo box to all of the
- * JComboBox's registered ListDataListeners.
+ * Adds an element to the model's item list and sends a {@link ListDataEvent}
+ * to all registered listeners. If the new element is the first item added
+ * to the list, it is set as the selected item.
*
- * @param object item to add to the combo box list
+ * @param object item to add to the model's item list.
*/
public void addElement(Object object)
{
list.add(object);
- fireIntervalAdded(this, list.size() - 1, list.size());
+ fireIntervalAdded(this, list.size() - 1, list.size() - 1);
+ if (list.size() == 1)
+ setSelectedItem(object);
}
/**
- * This method removes element at the specified index from the combo box
- * list. It fires ListDataEvent indicating that component was removed from
- * the combo box list to all of the JComboBox's registered
- * ListDataListeners.
+ * Removes the element at the specified index from the model's item list
+ * and sends a {@link ListDataEvent} to all registered listeners. If the
+ * element removed was the selected item, then the preceding element becomes
+ * the new selected item (or the next element, if there is no preceding
+ * element).
*
- * @param index index specifying location of the element to remove in the
- * combo box list.
+ * @param index the index of the item to remove.
+ *
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds.
*/
public void removeElementAt(int index)
{
+ int selected = getIndexOf(selectedItem);
list.remove(index);
+ if (selected == index) // choose a new selected item
+ {
+ if (selected > 0)
+ selectedItem = getElementAt(selected - 1);
+ else
+ selectedItem = getElementAt(selected);
+ }
fireIntervalRemoved(this, index, index);
}
/**
- * This method inserts given object to the combo box list at the specified
- * index. It fires ListDataEvent indicating that component was inserted to
- * the combo box list to all of the JComboBox's registered
- * ListDataListeners.
+ * Adds an element at the specified index in the model's item list
+ * and sends a {@link ListDataEvent} to all registered listeners.
*
* @param object element to insert
* @param index index specifing position in the list where given element
* should be inserted.
+ *
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds.
+ *
+ * @see #addElement(Object)
*/
public void insertElementAt(Object object, int index)
{
@@ -143,11 +172,13 @@ public class DefaultComboBoxModel extends AbstractListModel
}
/**
- * Removes given object from the combo box list. It fires ListDataEvent
- * indicating that component was removed from the combo box list to all of
- * the JComboBox's registered ListDataListeners.
+ * Removes an element from the model's item list and sends a
+ * {@link ListDataEvent} to all registered listeners. If the item to be
+ * removed is the current selected item, a new selected item will be set.
+ * If the element is not found in the model's item list, this method does
+ * nothing.
*
- * @param object Element that will be removed from the combo box list
+ * @param object the element to remove.
*/
public void removeElement(Object object)
{
@@ -157,21 +188,25 @@ public class DefaultComboBoxModel extends AbstractListModel
}
/**
- * Removes all the items from the JComboBox's item list. It fires
- * ListDataEvent indicating that all the elements were removed from the
- * combo box list to all of the JComboBox's registered ListDataListeners.
+ * Removes all the items from the model's item list, resets and selected item
+ * to <code>null</code>, and sends a {@link ListDataEvent} to all registered
+ * listeners.
*/
public void removeAllElements()
{
- list.clear();
- int listSize = getSize();
- fireIntervalAdded(this, 0, listSize);
+ selectedItem = null;
+ int size = getSize();
+ if (size > 0)
+ {
+ list.clear();
+ fireIntervalRemoved(this, 0, size - 1);
+ }
}
/**
- * Returns number of items in the combo box list
+ * Returns the number of items in the model's item list.
*
- * @return number of items in the combo box list
+ * @return The number of items in the model's item list.
*/
public int getSize()
{
@@ -179,32 +214,32 @@ public class DefaultComboBoxModel extends AbstractListModel
}
/**
- * Selects given object in the combo box list. This method fires
- * ListDataEvent to all registered ListDataListeners of the JComboBox. The
- * start and end index of the event is set to -1 to indicate combo box's
- * selection has changed, and not its contents.
- *
- * <p>If the given object is not contained in the combo box list then nothing
- * happens.</p>
+ * Sets the selected item for the model and sends a {@link ListDataEvent} to
+ * all registered listeners. The start and end index of the event is set to
+ * -1 to indicate the model's selection has changed, and not its contents.
*
- * @param object item to select in the JComboBox
+ * @param object the new selected item (<code>null</code> permitted).
*/
public void setSelectedItem(Object object)
{
-
- // Updates the selected item only if the given object
- // is null or in the list (this is how the JDK behaves).
- if(object == null || list.contains(object)) {
- selectedItem = object;
- fireContentsChanged(this, -1, -1);
- }
-
+ if (selectedItem == null)
+ {
+ if (object == null)
+ return;
+ }
+ else
+ {
+ if (selectedItem.equals(object))
+ return;
+ }
+ selectedItem = object;
+ fireContentsChanged(this, -1, -1);
}
/**
- * Returns currently selected item in the combo box list
+ * Returns the selected item.
*
- * @return currently selected item in the combo box list
+ * @return The selected item (possibly <code>null</code>).
*/
public Object getSelectedItem()
{
@@ -212,24 +247,27 @@ public class DefaultComboBoxModel extends AbstractListModel
}
/**
- * Returns element in the combo box list located at the given index
+ * Returns the element at the specified index in the model's item list.
*
- * @param index specifying location of the element in the list
+ * @param index the element index.
*
- * @return return element in the combo box list located at the given index
+ * @return The element at the specified index in the model's item list, or
+ * <code>null</code> if the <code>index</code> is outside the bounds
+ * of the list.
*/
public Object getElementAt(int index)
{
+ if (index < 0 || index >= list.size())
+ return null;
return list.elementAt(index);
}
/**
- * Returns index of the specified object in the combo box list.
+ * Returns the index of the specified element in the model's item list.
*
- * @param object element to look for in the combo box list .
+ * @param object the element.
*
- * @return Index specifying position of the specified element in combo box
- * list.
+ * @return The index of the specified element in the model's item list.
*/
public int getIndexOf(Object object)
{
diff --git a/libjava/classpath/javax/swing/DefaultDesktopManager.java b/libjava/classpath/javax/swing/DefaultDesktopManager.java
index 2b8977e9d6d..7f62c948625 100644
--- a/libjava/classpath/javax/swing/DefaultDesktopManager.java
+++ b/libjava/classpath/javax/swing/DefaultDesktopManager.java
@@ -91,6 +91,7 @@ public class DefaultDesktopManager implements DesktopManager, Serializable
*/
public DefaultDesktopManager()
{
+ // Nothing to do here.
}
/**
@@ -223,6 +224,7 @@ public class DefaultDesktopManager implements DesktopManager, Serializable
}
catch (PropertyVetoException e)
{
+ // Do nothing if attempt is vetoed.
}
}
@@ -302,6 +304,7 @@ public class DefaultDesktopManager implements DesktopManager, Serializable
}
catch (PropertyVetoException e)
{
+ // Do nothing if attempt is vetoed.
}
}
@@ -329,6 +332,7 @@ public class DefaultDesktopManager implements DesktopManager, Serializable
}
catch (PropertyVetoException e)
{
+ // Do nothing if attempt is vetoed.
}
}
}
diff --git a/libjava/classpath/javax/swing/DefaultListCellRenderer.java b/libjava/classpath/javax/swing/DefaultListCellRenderer.java
index 5a34ba7aa18..9a8e07071b5 100644
--- a/libjava/classpath/javax/swing/DefaultListCellRenderer.java
+++ b/libjava/classpath/javax/swing/DefaultListCellRenderer.java
@@ -68,6 +68,7 @@ public class DefaultListCellRenderer extends JLabel
{
public UIResource()
{
+ super();
}
}
@@ -124,62 +125,75 @@ public class DefaultListCellRenderer extends JLabel
public void validate()
{
+ // Overridden to do nothing.
}
public void revalidate()
{
+ // Overridden to do nothing.
}
public void repaint(long tm, int x, int y, int w, int h)
{
+ // Overridden to do nothing.
}
public void repaint(Rectangle rect)
{
+ // Overridden to do nothing.
}
protected void firePropertyChange(String propertyName, Object oldValue,
Object newValue)
{
+ // Overridden to do nothing.
}
public void firePropertyChange(String propertyName, byte oldValue,
byte newValue)
{
+ // Overridden to do nothing.
}
public void firePropertyChange(String propertyName, char oldValue,
char newValue)
{
+ // Overridden to do nothing.
}
public void firePropertyChange(String propertyName, short oldValue,
short newValue)
{
+ // Overridden to do nothing.
}
public void firePropertyChange(String propertyName, int oldValue,
int newValue)
{
+ // Overridden to do nothing.
}
public void firePropertyChange(String propertyName, long oldValue,
long newValue)
{
+ // Overridden to do nothing.
}
public void firePropertyChange(String propertyName, float oldValue,
float newValue)
{
+ // Overridden to do nothing.
}
public void firePropertyChange(String propertyName, double oldValue,
double newValue)
{
+ // Overridden to do nothing.
}
public void firePropertyChange(String propertyName, boolean oldValue,
boolean newValue)
{
+ // Overridden to do nothing.
}
}
diff --git a/libjava/classpath/javax/swing/DefaultListSelectionModel.java b/libjava/classpath/javax/swing/DefaultListSelectionModel.java
index f8d544d9b20..ce1dfdd79c5 100644
--- a/libjava/classpath/javax/swing/DefaultListSelectionModel.java
+++ b/libjava/classpath/javax/swing/DefaultListSelectionModel.java
@@ -238,14 +238,32 @@ public class DefaultListSelectionModel implements Cloneable,
*/
public void setLeadSelectionIndex(int leadIndex)
{
+ // Only set the lead selection index to < 0 if anchorSelectionIndex < 0.
+ if (leadIndex < 0)
+ {
+ if (anchorSelectionIndex < 0)
+ leadSelectionIndex = -1;
+ else
+ return;
+ }
+
+ // Only touch the lead selection index if the anchor is >= 0.
+ if (anchorSelectionIndex < 0)
+ return;
+
+ if (selectionMode == SINGLE_SELECTION)
+ setSelectionInterval (leadIndex, leadIndex);
+
int oldLeadIndex = leadSelectionIndex;
+ if (oldLeadIndex == -1)
+ oldLeadIndex = leadIndex;
if (setLeadCalledFromAdd == false)
oldSel = sel.clone();
leadSelectionIndex = leadIndex;
if (anchorSelectionIndex == -1)
- return;
-
+ return;
+
int R1 = Math.min(anchorSelectionIndex, oldLeadIndex);
int R2 = Math.max(anchorSelectionIndex, oldLeadIndex);
int S1 = Math.min(anchorSelectionIndex, leadIndex);
@@ -254,8 +272,6 @@ public class DefaultListSelectionModel implements Cloneable,
int lo = Math.min(R1, S1);
int hi = Math.max(R2, S2);
- BitSet oldRange = sel.get(lo, hi+1);
-
if (isSelectedIndex(anchorSelectionIndex))
{
sel.clear(R1, R2+1);
@@ -265,10 +281,7 @@ public class DefaultListSelectionModel implements Cloneable,
{
sel.set(R1, R2+1);
sel.clear(S1, S2+1);
- }
-
- BitSet newRange = sel.get(lo, hi+1);
- newRange.xor(oldRange);
+ }
int beg = sel.nextSetBit(0), end = -1;
for(int i=beg; i >= 0; i=sel.nextSetBit(i+1))
@@ -278,6 +291,27 @@ public class DefaultListSelectionModel implements Cloneable,
}
/**
+ * Moves the lead selection index to <code>leadIndex</code> without
+ * changing the selection values.
+ *
+ * If leadAnchorNotificationEnabled is true, send a notification covering the
+ * old and new lead cells.
+ *
+ * @param leadIndex the new lead selection index
+ * @since 1.5
+ */
+ public void moveLeadSelectionIndex (int leadIndex)
+ {
+ if (leadSelectionIndex == leadIndex)
+ return;
+
+ leadSelectionIndex = leadIndex;
+ if (isLeadAnchorNotificationEnabled())
+ fireValueChanged(Math.min(leadSelectionIndex, leadIndex),
+ Math.max(leadSelectionIndex, leadIndex));
+ }
+
+ /**
* Gets the value of the {@link #leadAnchorNotificationEnabled} property.
*
* @return The current property value
@@ -388,6 +422,9 @@ public class DefaultListSelectionModel implements Cloneable,
*/
public boolean isSelectedIndex(int a)
{
+ // TODO: Probably throw an exception here?
+ if (a >= sel.length() || a < 0)
+ return false;
return sel.get(a);
}
@@ -415,7 +452,7 @@ public class DefaultListSelectionModel implements Cloneable,
oldSel = sel.clone();
if (selectionMode == SINGLE_SELECTION)
- sel.clear();
+ setSelectionInterval(index0, index1);
// COMPAT: Like Sun (but not like IBM), we allow calls to
// addSelectionInterval when selectionMode is
@@ -426,10 +463,7 @@ public class DefaultListSelectionModel implements Cloneable,
isSelectedIndex(index1) ||
isSelectedIndex(Math.max(lo-1,0)) ||
isSelectedIndex(Math.min(hi+1,sel.size()))))
- sel.clear();
-
- if (selectionMode == SINGLE_SELECTION)
- index0 = index1;
+ sel.clear();
// We have to update the anchorSelectionIndex and leadSelectionIndex
// variables
diff --git a/libjava/classpath/javax/swing/DesktopManager.java b/libjava/classpath/javax/swing/DesktopManager.java
index 300d66517ba..620c7ffb857 100644
--- a/libjava/classpath/javax/swing/DesktopManager.java
+++ b/libjava/classpath/javax/swing/DesktopManager.java
@@ -95,7 +95,7 @@ public interface DesktopManager
* This method should give focus to the JInternalFrame and its default focus
* owner.
*
- * @param frame The JInternalFrame to activate.
+ * @param vframe The JInternalFrame to activate.
*/
void activateFrame(JInternalFrame vframe);
diff --git a/libjava/classpath/javax/swing/FocusManager.java b/libjava/classpath/javax/swing/FocusManager.java
index 179fa6f82d2..a2109ee06c6 100644
--- a/libjava/classpath/javax/swing/FocusManager.java
+++ b/libjava/classpath/javax/swing/FocusManager.java
@@ -38,10 +38,19 @@ exception statement from your version. */
package javax.swing;
+import java.awt.AWTEvent;
import java.awt.Component;
+import java.awt.Container;
import java.awt.DefaultKeyboardFocusManager;
+import java.awt.FocusTraversalPolicy;
+import java.awt.KeyEventDispatcher;
+import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager;
+import java.awt.Window;
import java.awt.event.KeyEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.VetoableChangeListener;
+import java.util.Set;
/**
* This class has been obsoleted by the new
@@ -54,46 +63,409 @@ public abstract class FocusManager
extends DefaultKeyboardFocusManager
{
/**
- * DisabledFocusManager
+ * A FocusManager that wraps an AWT KeyboardFocusManager and forwards all
+ * method calls to it. This is used for compatibility with the new focus
+ * system.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
*/
- static class DisabledFocusManager
+ private static class WrappingFocusManager
extends FocusManager
{
+ /**
+ * The wrapped KeyboardFocusManager.
+ */
+ private KeyboardFocusManager wrapped;
+
+ /**
+ * Creates a new instance of WrappedFocusManager.
+ *
+ * @param fm the focus manager to wrap
+ */
+ WrappingFocusManager(KeyboardFocusManager fm)
+ {
+ wrapped = fm;
+ }
+
+ /**
+ * Wraps {@link DefaultKeyboardFocusManager#dispatchEvent(AWTEvent)}.
+ *
+ * @param ev the event to dispatch
+ *
+ * @return <code>true</code> if the event has been dispatched,
+ * <code>false</code> otherwise
+ */
+ public boolean dispatchEvent(AWTEvent ev)
+ {
+ return wrapped.dispatchEvent(ev);
+ }
+
+ /**
+ * Wraps {@link DefaultKeyboardFocusManager#dispatchKeyEvent(KeyEvent)}.
+ *
+ * @param ev the event to dispatch
+ *
+ * @return <code>true</code> if the event has been dispatched,
+ * <code>false</code> otherwise
+ */
+ public boolean dispatchKeyEvent(KeyEvent ev)
+ {
+ return wrapped.dispatchKeyEvent(ev);
+ }
+
+ /**
+ * Wraps {@link DefaultKeyboardFocusManager#downFocusCycle(Container)}.
+ *
+ * @param c the container
+ */
+ public void downFocusCycle(Container c)
+ {
+ wrapped.downFocusCycle(c);
+ }
+
+ /**
+ * Wraps {@link DefaultKeyboardFocusManager#upFocusCycle(Container)}.
+ *
+ * @param c the container
+ */
+ public void upFocusCycle(Container c)
+ {
+ wrapped.upFocusCycle(c);
+ }
+
+ /**
+ * Wraps {@link DefaultKeyboardFocusManager#focusNextComponent(Component)}.
+ *
+ * @param c the component
+ */
+ public void focusNextComponent(Component c)
+ {
+ wrapped.focusNextComponent(c);
+ }
+
+ /**
+ * Wraps
+ * {@link DefaultKeyboardFocusManager#focusPreviousComponent(Component)}.
+ *
+ * @param c the component
+ */
+ public void focusPreviousComponent(Component c)
+ {
+ wrapped.focusPreviousComponent(c);
+ }
+
+ /**
+ * Wraps {@link DefaultKeyboardFocusManager#postProcessKeyEvent(KeyEvent)}.
+ *
+ * @param e the key event
+ *
+ * @return a boolead
+ */
+ public boolean postProcessKeyEvent(KeyEvent e)
+ {
+ return wrapped.postProcessKeyEvent(e);
+ }
+
+ /**
+ * Wraps
+ * {@link DefaultKeyboardFocusManager#processKeyEvent(Component, KeyEvent)}.
+ *
+ * @param c the component
+ * @param e the key event
+ */
+ public void processKeyEvent(Component c, KeyEvent e)
+ {
+ wrapped.processKeyEvent(c, e);
+ }
+
+ /**
+ * Wraps
+ * {@link KeyboardFocusManager#addKeyEventDispatcher(KeyEventDispatcher)}.
+ *
+ * @param d the dispatcher
+ */
+ public void addKeyEventDispatcher(KeyEventDispatcher d)
+ {
+ wrapped.addKeyEventDispatcher(d);
+ }
+
+ /**
+ * Wraps
+ * {@link KeyboardFocusManager#addKeyEventPostProcessor(KeyEventPostProcessor)}.
+ *
+ * @param p the post processor
+ */
+ public void addKeyEventPostProcessor(KeyEventPostProcessor p)
+ {
+ wrapped.addKeyEventPostProcessor(p);
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#addPropertyChangeListener(PropertyChangeListener)}.
+ *
+ * @param l the property change listener
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ wrapped.addPropertyChangeListener(l);
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#addPropertyChangeListener(String, PropertyChangeListener)}.
+ *
+ * @param p the property name
+ * @param l the property change listener
+ */
+ public void addPropertyChangeListener(String p, PropertyChangeListener l)
+ {
+ wrapped.addPropertyChangeListener(p, l);
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#addVetoableChangeListener(String, VetoableChangeListener)}.
+ *
+ * @param p the property name
+ * @param l the vetoable change listener
+ */
+ public void addVetoableChangeListener(String p, VetoableChangeListener l)
+ {
+ wrapped.addVetoableChangeListener(p, l);
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#addVetoableChangeListener(VetoableChangeListener)}.
+ *
+ * @param l the vetoable change listener
+ */
+ public void addVetoableChangeListener(VetoableChangeListener l)
+ {
+ wrapped.addVetoableChangeListener(l);
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#clearGlobalFocusOwner()}.
+ */
+ public void clearGlobalFocusOwner()
+ {
+ wrapped.clearGlobalFocusOwner();
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#getActiveWindow()}.
+ *
+ * @return the active window
+ */
+ public Window getActiveWindow()
+ {
+ return wrapped.getActiveWindow();
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#getCurrentFocusCycleRoot()}.
+ *
+ * @return the focus cycle root
+ */
+ public Container getCurrentFocusCycleRoot()
+ {
+ return wrapped.getCurrentFocusCycleRoot();
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#getDefaultFocusTraversalKeys(int)}.
+ *
+ * @param i the ID
+ *
+ * @return the focus traversal keys
+ */
+ public Set getDefaultFocusTraversalKeys(int i)
+ {
+ return wrapped.getDefaultFocusTraversalKeys(i);
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#getDefaultFocusTraversalPolicy()}.
+ *
+ * @return the focus traversal policy
+ */
+ public FocusTraversalPolicy getDefaultFocusTraversalPolicy()
+ {
+ return wrapped.getDefaultFocusTraversalPolicy();
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#getFocusedWindow()}.
+ *
+ * @return the focused window
+ */
+ public Window getFocusedWindow()
+ {
+ return wrapped.getFocusedWindow();
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#getFocusOwner()}.
+ *
+ * @return the focus owner
+ */
+ public Component getFocusOwner()
+ {
+ return wrapped.getFocusOwner();
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#getPermanentFocusOwner()}.
+ *
+ * @return the focus owner
+ */
+ public Component getPermanentFocusOwner()
+ {
+ return wrapped.getPermanentFocusOwner();
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#getPropertyChangeListeners()}.
+ *
+ * @return the property change listeners
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners()
+ {
+ return wrapped.getPropertyChangeListeners();
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#getPropertyChangeListeners(String)}.
+ *
+ * @param n the property name
+ *
+ * @return the property change listeners
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners(String n)
+ {
+ return wrapped.getPropertyChangeListeners(n);
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#getVetoableChangeListeners()}.
+ *
+ * @return the vetoable change listeners
+ */
+ public VetoableChangeListener[] getVetoableChangeListeners()
+ {
+ return wrapped.getVetoableChangeListeners();
+ }
+
+ /**
+ * Wraps {@link KeyboardFocusManager#getVetoableChangeListeners(String)}.
+ *
+ * @param n the property name
+ *
+ * @return the vetoable change listeners
+ */
+ public VetoableChangeListener[] getVetoableChangeListeners(String n)
+ {
+ return wrapped.getVetoableChangeListeners(n);
+ }
+
+
+ /**
+ * Wraps
+ * {@link KeyboardFocusManager#removeKeyEventDispatcher(KeyEventDispatcher)}.
+ *
+ * @param d the key event dispatcher to remove
+ */
+ public void removeKeyEventDispatcher(KeyEventDispatcher d)
+ {
+ wrapped.removeKeyEventDispatcher(d);
+ }
+
+ /**
+ * Wraps
+ * {@link KeyboardFocusManager#removeKeyEventPostProcessor(KeyEventPostProcessor)}.
+ *
+ * @param p the post processor
+ */
+ public void removeKeyEventPostProcessor(KeyEventPostProcessor p)
+ {
+ wrapped.removeKeyEventPostProcessor(p);
+ }
+
+ /**
+ * Wraps
+ * {@link KeyboardFocusManager#removePropertyChangeListener(PropertyChangeListener)}.
+ *
+ * @param l the listener
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ wrapped.removePropertyChangeListener(l);
+ }
+
+ /**
+ * Wraps
+ * {@link KeyboardFocusManager#removePropertyChangeListener(String, PropertyChangeListener)}.
+ *
+ * @param n the property name
+ * @param l the listener
+ */
+ public void removePropertyChangeListener(String n, PropertyChangeListener l)
+ {
+ wrapped.removePropertyChangeListener(n, l);
+ }
+
+ /**
+ * Wraps
+ * {@link KeyboardFocusManager#removeVetoableChangeListener(VetoableChangeListener)}.
+ *
+ * @param l the listener
+ */
+ public void removeVetoableChangeListener(VetoableChangeListener l)
+ {
+ wrapped.removeVetoableChangeListener(l);
+ }
/**
- * Constructor DisabledFocusManager
+ * Wraps
+ * {@link KeyboardFocusManager#removeVetoableChangeListener(String, VetoableChangeListener)}.
+ *
+ * @param n the property name
+ * @param l the listener
*/
- DisabledFocusManager()
+ public void removeVetoableChangeListener(String n, VetoableChangeListener l)
{
- // TODO
+ wrapped.removeVetoableChangeListener(n, l);
}
/**
- * processKeyEvent
- * @param component TODO
- * @param event TODO
+ * Wraps
+ * {@link KeyboardFocusManager#setDefaultFocusTraversalKeys(int, Set)}.
+ *
+ * @param id the ID
+ * @param k the keystrokes
*/
- public void processKeyEvent(Component component, KeyEvent event)
+ public void setDefaultFocusTraversalKeys(int id, Set k)
{
- // TODO
+ wrapped.setDefaultFocusTraversalKeys(id, k);
}
/**
- * focusNextComponent
- * @param component TODO
+ * Wraps {@link KeyboardFocusManager#setDefaultFocusTraversalPolicy(FocusTraversalPolicy)}.
+ *
+ * @param p the focus traversal policy
*/
- public void focusNextComponent(Component component)
+ public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy p)
{
- // TODO
+ wrapped.setDefaultFocusTraversalPolicy(p);
}
/**
- * focusPreviousComponent
- * @param value0 TODO
+ * Wraps
+ * {@link KeyboardFocusManager#setGlobalCurrentFocusCycleRoot(Container)}.
+ *
+ * @param r the focus cycle root
*/
- public void focusPreviousComponent(Component value0)
+ public void setGlobalCurrentFocusCycleRoot(Container r)
{
- // TODO
+ wrapped.setGlobalCurrentFocusCycleRoot(r);
}
}
@@ -117,20 +489,9 @@ public abstract class FocusManager
*/
public static FocusManager getCurrentManager()
{
- KeyboardFocusManager fm =
- KeyboardFocusManager.getCurrentKeyboardFocusManager();
- if (fm instanceof FocusManager)
- return (FocusManager) fm;
- else
- {
- System.err.println("The Swing FocusManager API has been obsoleted by");
- System.err.println("the new KeyboardFocusManager system.");
- System.err.println("You should either not use the Swing FocusManager");
- System.err.println("API or set the system property");
- System.err.println
- ("gnu.java.awt.FocusManager=javax.swing.FocusManager");
- }
- return null;
+ KeyboardFocusManager m =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ return new WrappingFocusManager(m);
}
/**
diff --git a/libjava/classpath/javax/swing/ImageIcon.java b/libjava/classpath/javax/swing/ImageIcon.java
index b650cd81f23..b6ed949d8dc 100644
--- a/libjava/classpath/javax/swing/ImageIcon.java
+++ b/libjava/classpath/javax/swing/ImageIcon.java
@@ -73,6 +73,7 @@ public class ImageIcon
*/
protected AccessibleImageIcon()
{
+ // Nothing to do here.
}
/**
@@ -204,7 +205,10 @@ public class ImageIcon
private static final long serialVersionUID = 532615968316031794L;
/** A dummy Component that is used in the MediaTracker. */
- protected static Component component = new Component(){};
+ protected static Component component = new Component()
+ {
+ // No need to implement this.
+ };
/** The MediaTracker used to monitor the loading of images. */
protected static MediaTracker tracker = new MediaTracker(component);
@@ -227,6 +231,7 @@ public class ImageIcon
*/
public ImageIcon()
{
+ // Nothing to do here.
}
/**
@@ -417,7 +422,7 @@ public class ImageIcon
}
catch (InterruptedException ex)
{
- ; // ignore this for now
+ // Ignore this for now.
}
finally
{
diff --git a/libjava/classpath/javax/swing/InputMap.java b/libjava/classpath/javax/swing/InputMap.java
index a7ec38c4117..cc65dfeed3e 100644
--- a/libjava/classpath/javax/swing/InputMap.java
+++ b/libjava/classpath/javax/swing/InputMap.java
@@ -171,8 +171,12 @@ public class InputMap
*/
public KeyStroke[] keys()
{
- KeyStroke[] array = new KeyStroke[size()];
- return (KeyStroke[]) inputMap.keySet().toArray(array);
+ if (size() != 0)
+ {
+ KeyStroke[] array = new KeyStroke[size()];
+ return (KeyStroke[]) inputMap.keySet().toArray(array);
+ }
+ return null;
}
/**
@@ -189,7 +193,9 @@ public class InputMap
set.addAll(Arrays.asList(parent.allKeys()));
set.addAll(inputMap.keySet());
- KeyStroke[] array = new KeyStroke[size()];
+ if (set.size() == 0)
+ return null;
+ KeyStroke[] array = new KeyStroke[set.size()];
return (KeyStroke[]) set.toArray(array);
}
diff --git a/libjava/classpath/javax/swing/InputVerifier.java b/libjava/classpath/javax/swing/InputVerifier.java
index 8e02ab813a3..eeb81b5d503 100644
--- a/libjava/classpath/javax/swing/InputVerifier.java
+++ b/libjava/classpath/javax/swing/InputVerifier.java
@@ -53,6 +53,7 @@ public abstract class InputVerifier
*/
public InputVerifier()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/JApplet.java b/libjava/classpath/javax/swing/JApplet.java
index cafb2dabbb8..3ee1046c802 100644
--- a/libjava/classpath/javax/swing/JApplet.java
+++ b/libjava/classpath/javax/swing/JApplet.java
@@ -47,6 +47,7 @@ import java.awt.Graphics;
import java.awt.LayoutManager;
import java.awt.event.KeyEvent;
+import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
/**
@@ -55,8 +56,28 @@ import javax.accessibility.AccessibleContext;
* @author original author unknown
*/
public class JApplet extends Applet
- implements RootPaneContainer
+ implements RootPaneContainer, Accessible
{
+ /**
+ * Provides accessibility support for <code>JApplet</code>.
+ */
+ protected class AccessibleJApplet extends Applet.AccessibleApplet
+ {
+ /**
+ * Creates a new instance of <code>AccessibleJApplet</code>.
+ */
+ public AccessibleJApplet()
+ {
+ super();
+ // Nothing to do here.
+ }
+ }
+
+ /**
+ * The accessible context for this <code>JApplet</code>.
+ */
+ protected AccessibleContext accessibleContext;
+
private static final long serialVersionUID = 7269359214497372587L;
protected JRootPane rootPane;
@@ -64,20 +85,13 @@ public class JApplet extends Applet
/**
* @specnote rootPaneCheckingEnabled is false to comply with J2SE 5.0
*/
- protected boolean rootPaneCheckingEnabled=false;
-
- /**
- * Tells us if we're in the initialization stage.
- * If so, adds go to top-level Container, otherwise they go
- * to the content pane for this container
- */
- private boolean initStageDone = false;
+ protected boolean rootPaneCheckingEnabled = false;
public JApplet()
{
super.setLayout(new BorderLayout(1, 1));
getRootPane(); // Will do set/create.
- initStageDone = true; // Init stage is now over.
+ setRootPaneCheckingEnabled(true); // Init stage is now over.
}
public Dimension getPreferredSize()
@@ -89,13 +103,8 @@ public class JApplet extends Applet
{
// Check if we're in initialization stage. If so, call super.setLayout
// otherwise, valid calls go to the content pane
- if (initStageDone)
- {
- if (isRootPaneCheckingEnabled())
- throw new Error("Cannot set layout. Use getContentPane().setLayout()"
- + "instead.");
- getContentPane().setLayout(manager);
- }
+ if (isRootPaneCheckingEnabled())
+ getContentPane().setLayout(manager);
else
super.setLayout(manager);
}
@@ -155,20 +164,17 @@ public class JApplet extends Applet
{
// If we're adding in the initialization stage use super.add.
// Otherwise pass the add onto the content pane.
- if (!initStageDone)
- super.addImpl(comp, constraints, index);
+ if (isRootPaneCheckingEnabled())
+ getContentPane().add(comp, constraints, index);
else
- {
- if (isRootPaneCheckingEnabled())
- throw new Error("Do not use add() on JApplet directly. Use "
- + "getContentPane().add() instead");
- getContentPane().add(comp, constraints, index);
- }
+ super.addImpl(comp, constraints, index);
}
public AccessibleContext getAccessibleContext()
{
- return null;
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJApplet();
+ return accessibleContext;
}
public JMenuBar getJMenuBar()
diff --git a/libjava/classpath/javax/swing/JButton.java b/libjava/classpath/javax/swing/JButton.java
index 5653fbf42f1..ff0ecfccfd4 100644
--- a/libjava/classpath/javax/swing/JButton.java
+++ b/libjava/classpath/javax/swing/JButton.java
@@ -75,9 +75,6 @@ public class JButton extends AbstractButton
boolean def;
boolean is_def;
- /** The AccessibleContext for this JButton. */
- AccessibleJButton accessibleContext;
-
public JButton()
{
this(null, null);
@@ -166,6 +163,10 @@ public class JButton extends AbstractButton
*/
public void removeNotify()
{
+ JRootPane root = SwingUtilities.getRootPane(this);
+ if (root != null && root.getDefaultButton() == this)
+ root.setDefaultButton(null);
+ super.removeNotify();
}
public void setDefaultCapable(boolean defaultCapable)
diff --git a/libjava/classpath/javax/swing/JCheckBox.java b/libjava/classpath/javax/swing/JCheckBox.java
index a743308dcca..74fda8f6dbe 100644
--- a/libjava/classpath/javax/swing/JCheckBox.java
+++ b/libjava/classpath/javax/swing/JCheckBox.java
@@ -38,7 +38,9 @@ exception statement from your version. */
package javax.swing;
+import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
/**
* A small box that displays a check or not, depending on it's
@@ -54,8 +56,32 @@ import javax.accessibility.AccessibleContext;
*
* @author Ronald Veldema (rveldema@cs.vu.nl)
*/
-public class JCheckBox extends JToggleButton
+public class JCheckBox extends JToggleButton implements Accessible
{
+
+ /**
+ * Provides accessibility support for <code>JCheckBox</code>.
+ */
+ protected class AccessibleJCheckBox extends AccessibleJToggleButton
+ {
+ /**
+ * Creates a new instance of <code>AccessibleJCheckBox</code>.
+ */
+ public AccessibleJCheckBox()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the accessble role of <code>JCheckBox</code>,
+ * {@link AccessibleRole#CHECK_BOX}.
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.CHECK_BOX;
+ }
+ }
+
private static final long serialVersionUID = -5246739313864538930L;
public static final String BORDER_PAINTED_FLAT_CHANGED_PROPERTY =
@@ -71,61 +97,47 @@ public class JCheckBox extends JToggleButton
public JCheckBox()
{
- super();
- init();
+ this(null, null, false);
}
public JCheckBox(Action action)
{
super(action);
- init();
}
public JCheckBox(Icon icon)
{
- super(icon);
- init();
+ this(null, icon, false);
}
public JCheckBox(Icon icon, boolean selected)
{
- super(icon, selected);
- init();
+ this(null, icon, selected);
}
public JCheckBox(String text)
{
- super(text);
- init();
+ this(text, null, false);
}
public JCheckBox(String text, boolean selected)
{
- super(text, selected);
- init();
+ this(text, null, selected);
}
public JCheckBox(String text, Icon icon)
{
- super(text, icon);
- init();
+ this(text, icon, false);
}
public JCheckBox(String text, Icon icon, boolean selected)
{
super(text, icon, selected);
- init();
+ setHorizontalAlignment(LEADING);
+ setBorderPainted(false);
}
/**
- * Gets the AccessibleContext associated with this JCheckBox.
- */
- public AccessibleContext getAccessibleContext()
- {
- return null;
- }
-
- /**
* Returns a string that specifies the name of the Look and Feel class
* that renders this component.
*/
@@ -149,4 +161,16 @@ public class JCheckBox extends JToggleButton
firePropertyChange("borderPaintedFlat", borderPaintedFlat, newValue);
borderPaintedFlat = newValue;
}
+
+ /**
+ * Returns the accessible context for this <code>JCheckBox</code>.
+ *
+ * @return the accessible context for this <code>JCheckBox</code>
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJCheckBox();
+ return accessibleContext;
+ }
}
diff --git a/libjava/classpath/javax/swing/JCheckBoxMenuItem.java b/libjava/classpath/javax/swing/JCheckBoxMenuItem.java
index f9dd56500fe..815244259be 100644
--- a/libjava/classpath/javax/swing/JCheckBoxMenuItem.java
+++ b/libjava/classpath/javax/swing/JCheckBoxMenuItem.java
@@ -38,9 +38,6 @@ exception statement from your version. */
package javax.swing;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
@@ -48,8 +45,9 @@ import javax.accessibility.AccessibleRole;
/**
* A menu item that displays a checkbox. Its behaviour is very similar
* to {@link JCheckBox}. Just like the <code>JCheckBox</code>, user can check
- * and uncheck this menu item by clicking on it. Also {@link #setSelected()}
- * and {@link #setState()} can be use used for the same purpose.
+ * and uncheck this menu item by clicking on it. Also
+ * {@link AbstractButton#setSelected} and {@link #setState} can be use used
+ * for the same purpose.
* <code>JCheckBoxMenuItem</code> uses
* <code>ToggleButtonModel</code> to keep track of its selection.
*
@@ -152,10 +150,6 @@ public class JCheckBoxMenuItem extends JMenuItem implements SwingConstants,
this.setVisible(true);
}
- private void writeObject(ObjectOutputStream stream) throws IOException
- {
- }
-
/**
* This method returns a name to identify which look and feel class will be
* the UI delegate for the menuItem.
@@ -248,6 +242,7 @@ public class JCheckBoxMenuItem extends JMenuItem implements SwingConstants,
*/
protected AccessibleJCheckBoxMenuItem()
{
+ // Nothing to do here.
}
public AccessibleRole getAccessibleRole()
diff --git a/libjava/classpath/javax/swing/JColorChooser.java b/libjava/classpath/javax/swing/JColorChooser.java
index 4016b82f3fd..a9650ffb7e0 100644
--- a/libjava/classpath/javax/swing/JColorChooser.java
+++ b/libjava/classpath/javax/swing/JColorChooser.java
@@ -87,6 +87,7 @@ public class JColorChooser extends JComponent implements Accessible
*/
protected AccessibleJColorChooser()
{
+ // Nothing to do here.
}
/**
@@ -247,6 +248,7 @@ public class JColorChooser extends JComponent implements Accessible
}
catch (InterruptedException e)
{
+ // TODO: Should this be handled?
}
}
diff --git a/libjava/classpath/javax/swing/JComboBox.java b/libjava/classpath/javax/swing/JComboBox.java
index 47d18323a25..cd30840a6aa 100644
--- a/libjava/classpath/javax/swing/JComboBox.java
+++ b/libjava/classpath/javax/swing/JComboBox.java
@@ -46,8 +46,6 @@ import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
import java.util.Vector;
import javax.accessibility.Accessible;
@@ -58,6 +56,7 @@ import javax.accessibility.AccessibleSelection;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.PopupMenuListener;
+import javax.swing.event.PopupMenuEvent;
import javax.swing.plaf.ComboBoxUI;
/**
@@ -212,10 +211,6 @@ public class JComboBox extends JComponent implements ItemSelectable,
this(new DefaultComboBoxModel());
}
- private void writeObject(ObjectOutputStream stream) throws IOException
- {
- }
-
/**
* This method returns true JComboBox is editable and false otherwise
*
@@ -310,7 +305,8 @@ public class JComboBox extends JComponent implements ItemSelectable,
// Stores old data model for event notification.
ComboBoxModel oldDataModel = dataModel;
dataModel = newDataModel;
-
+ selectedItemReminder = newDataModel.getSelectedItem();
+
// Notifies the listeners of the model change.
firePropertyChange("model", oldDataModel, dataModel);
}
@@ -551,14 +547,37 @@ public class JComboBox extends JComponent implements ItemSelectable,
return -1;
}
+ /**
+ * Returns an object that is used as the display value when calculating the
+ * preferred size for the combo box. This value is, of course, never
+ * displayed anywhere.
+ *
+ * @return The prototype display value (possibly <code>null</code>).
+ *
+ * @since 1.4
+ * @see #setPrototypeDisplayValue(Object)
+ */
public Object getPrototypeDisplayValue()
{
return prototypeDisplayValue;
}
- public void setPrototypeDisplayValue(Object newPrototypeDisplayValue)
+ /**
+ * Sets the object that is assumed to be the displayed item when calculating
+ * the preferred size for the combo box. A {@link PropertyChangeEvent} (with
+ * the name <code>prototypeDisplayValue</code>) is sent to all registered
+ * listeners.
+ *
+ * @param value the new value (<code>null</code> permitted).
+ *
+ * @since 1.4
+ * @see #getPrototypeDisplayValue()
+ */
+ public void setPrototypeDisplayValue(Object value)
{
- prototypeDisplayValue = newPrototypeDisplayValue;
+ Object oldValue = prototypeDisplayValue;
+ prototypeDisplayValue = value;
+ firePropertyChange("prototypeDisplayValue", oldValue, value);
}
/**
@@ -820,6 +839,47 @@ public class JComboBox extends JComponent implements ItemSelectable,
}
/**
+ * Fires a popupMenuCanceled() event to all <code>PopupMenuListeners</code>.
+ *
+ * Note: This method is intended for use by plaf classes only.
+ */
+ public void firePopupMenuCanceled()
+ {
+ PopupMenuListener[] listeners = getPopupMenuListeners();
+ PopupMenuEvent e = new PopupMenuEvent(this);
+ for(int i = 0; i < listeners.length; i++)
+ listeners[i].popupMenuCanceled(e);
+ }
+
+ /**
+ * Fires a popupMenuWillBecomeInvisible() event to all
+ * <code>PopupMenuListeners</code>.
+ *
+ * Note: This method is intended for use by plaf classes only.
+ */
+ public void firePopupMenuWillBecomeInvisible()
+ {
+ PopupMenuListener[] listeners = getPopupMenuListeners();
+ PopupMenuEvent e = new PopupMenuEvent(this);
+ for(int i = 0; i < listeners.length; i++)
+ listeners[i].popupMenuWillBecomeInvisible(e);
+ }
+
+ /**
+ * Fires a popupMenuWillBecomeVisible() event to all
+ * <code>PopupMenuListeners</code>.
+ *
+ * Note: This method is intended for use by plaf classes only.
+ */
+ public void firePopupMenuWillBecomeVisible()
+ {
+ PopupMenuListener[] listeners = getPopupMenuListeners();
+ PopupMenuEvent e = new PopupMenuEvent(this);
+ for(int i = 0; i < listeners.length; i++)
+ listeners[i].popupMenuWillBecomeVisible(e);
+ }
+
+ /**
* This method is invoked whenever selected item changes in the combo box's
* data model. It fires ItemEvent and ActionEvent to all registered
* ComboBox's ItemListeners and ActionListeners respectively, indicating
@@ -836,8 +896,9 @@ public class JComboBox extends JComponent implements ItemSelectable,
// Fire ItemEvent to indicate that new item is selected
Object newSelection = getSelectedItem();
- fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED,
- newSelection, ItemEvent.SELECTED));
+ if (newSelection != null)
+ fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED,
+ newSelection, ItemEvent.SELECTED));
// Fire Action Event to JComboBox's registered listeners
fireActionEvent();
@@ -961,19 +1022,19 @@ public class JComboBox extends JComponent implements ItemSelectable,
*/
public void processKeyEvent(KeyEvent e)
{
- }
-
- /**
- * This method always returns false to indicate that JComboBox itself is
- * not focus traversable.
- *
- * @return false to indicate that JComboBox itself is not focus traversable.
- *
- * @deprecated
- */
- public boolean isFocusTraversable()
- {
- return false;
+ if (e.getKeyCode() == KeyEvent.VK_TAB)
+ setPopupVisible(false);
+ else if (keySelectionManager != null)
+ {
+ int i = keySelectionManager.selectionForKey(e.getKeyChar(),
+ getModel());
+ if (i >= 0)
+ setSelectedIndex(i);
+ else
+ super.processKeyEvent(e);
+ }
+ else
+ super.processKeyEvent(e);
}
/**
@@ -983,6 +1044,7 @@ public class JComboBox extends JComponent implements ItemSelectable,
*/
public void setKeySelectionManager(KeySelectionManager aManager)
{
+ keySelectionManager = aManager;
}
/**
@@ -1147,6 +1209,7 @@ public class JComboBox extends JComponent implements ItemSelectable,
protected AccessibleJComboBox()
{
+ // Nothing to do here.
}
public int getAccessibleChildrenCount()
@@ -1206,18 +1269,22 @@ public class JComboBox extends JComponent implements ItemSelectable,
public void addAccessibleSelection(int value0)
{
+ // TODO: Implement this properly.
}
public void removeAccessibleSelection(int value0)
{
+ // TODO: Implement this properly.
}
public void clearAccessibleSelection()
{
+ // TODO: Implement this properly.
}
public void selectAllAccessibleSelection()
{
+ // TODO: Implement this properly.
}
}
}
diff --git a/libjava/classpath/javax/swing/JComponent.java b/libjava/classpath/javax/swing/JComponent.java
index dc7689b0930..021a2a34080 100644
--- a/libjava/classpath/javax/swing/JComponent.java
+++ b/libjava/classpath/javax/swing/JComponent.java
@@ -44,6 +44,7 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
+import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.FocusTraversalPolicy;
import java.awt.Font;
@@ -53,6 +54,7 @@ import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
+import java.awt.Shape;
import java.awt.Window;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
@@ -64,7 +66,6 @@ import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
-import java.awt.image.ImageObserver;
import java.awt.peer.LightweightPeer;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
@@ -83,6 +84,8 @@ import javax.accessibility.AccessibleKeyBinding;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleStateSet;
import javax.swing.border.Border;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.TitledBorder;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.EventListenerList;
@@ -121,9 +124,18 @@ public abstract class JComponent extends Container implements Serializable
protected class AccessibleFocusHandler
implements FocusListener
{
- protected AccessibleFocusHandler(){}
- public void focusGained(FocusEvent event){}
- public void focusLost(FocusEvent valevent){}
+ protected AccessibleFocusHandler()
+ {
+ // TODO: Implement this properly.
+ }
+ public void focusGained(FocusEvent event)
+ {
+ // TODO: Implement this properly.
+ }
+ public void focusLost(FocusEvent valevent)
+ {
+ // TODO: Implement this properly.
+ }
}
/**
@@ -132,9 +144,18 @@ public abstract class JComponent extends Container implements Serializable
protected class AccessibleContainerHandler
implements ContainerListener
{
- protected AccessibleContainerHandler() {}
- public void componentAdded(ContainerEvent event) {}
- public void componentRemoved(ContainerEvent valevent) {}
+ protected AccessibleContainerHandler()
+ {
+ // TODO: Implement this properly.
+ }
+ public void componentAdded(ContainerEvent event)
+ {
+ // TODO: Implement this properly.
+ }
+ public void componentRemoved(ContainerEvent valevent)
+ {
+ // TODO: Implement this properly.
+ }
}
private static final long serialVersionUID = -7047089700479897799L;
@@ -142,39 +163,217 @@ public abstract class JComponent extends Container implements Serializable
protected ContainerListener accessibleContainerHandler;
protected FocusListener accessibleFocusHandler;
- protected AccessibleJComponent() {}
- 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; }
- public String getToolTipText() { return null; }
- public String getTitledBorderText() { return null; }
- public AccessibleKeyBinding getAccessibleKeyBinding() { return null; }
+ /**
+ * Manages the property change listeners;
+ */
+ private SwingPropertyChangeSupport changeSupport;
+
+ protected AccessibleJComponent()
+ {
+ changeSupport = new SwingPropertyChangeSupport(this);
+ }
+
+ /**
+ * Adds a property change listener to the list of registered listeners.
+ *
+ * @param listener the listener to add
+ */
+ public void addPropertyChangeListener(PropertyChangeListener listener)
+ {
+ changeSupport.addPropertyChangeListener(listener);
+ }
+
+ /**
+ * Removes a propery change listener from the list of registered listeners.
+ *
+ * @param listener the listener to remove
+ */
+ public void removePropertyChangeListener(PropertyChangeListener listener)
+ {
+ changeSupport.removePropertyChangeListener(listener);
+ }
+
+ /**
+ * Returns the number of accessible children of this object.
+ *
+ * @return the number of accessible children of this object
+ */
+ public int getAccessibleChildrenCount()
+ {
+ int count = 0;
+ Component[] children = getComponents();
+ for (int i = 0; i < children.length; ++i)
+ {
+ if (children[i] instanceof Accessible)
+ count++;
+ }
+ return count;
+ }
+
+ /**
+ * Returns the accessible child component at index <code>i</code>.
+ *
+ * @param i the index of the accessible child to return
+ *
+ * @return the accessible child component at index <code>i</code>
+ */
+ public Accessible getAccessibleChild(int i)
+ {
+ int index = 0;
+ Component[] children = getComponents();
+ Accessible found = null;
+ for (int j = 0; index != i; j++)
+ {
+ if (children[j] instanceof Accessible)
+ index++;
+ if (index == i)
+ found = (Accessible) children[index];
+ }
+ // TODO: Figure out what to do when i is not a valid index.
+ return found;
+ }
+
+ /**
+ * Returns the accessible state set of this component.
+ *
+ * @return the accessible state set of this component
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ // FIXME: Figure out which states should be set here, and which are
+ // inherited from the super class.
+ return super.getAccessibleStateSet();
+ }
+
+ /**
+ * Returns the localized name for this object. Generally this should
+ * almost never return {@link Component#getName()} since that is not
+ * a localized name. If the object is some kind of text component (like
+ * a menu item), then the value of the object may be returned. Also, if
+ * the object has a tooltip, the value of the tooltip may also be
+ * appropriate.
+ *
+ * @return the localized name for this object or <code>null</code> if this
+ * object has no name
+ */
+ public String getAccessibleName()
+ {
+ // TODO: Figure out what exactly to return here. It's possible that this
+ // method simply should return null.
+ return null;
+ }
+
+ /**
+ * Returns the localized description of this object.
+ *
+ * @return the localized description of this object or <code>null</code>
+ * if this object has no description
+ */
+ public String getAccessibleDescription()
+ {
+ // TODO: Figure out what exactly to return here. It's possible that this
+ // method simply should return null.
+ return null;
+ }
+
+ /**
+ * Returns the accessible role of this component.
+ *
+ * @return the accessible role of this component
+ *
+ * @see AccessibleRole
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ // TODO: Check if this is correct.
+ return AccessibleRole.SWING_COMPONENT;
+ }
+
+ /**
+ * Recursivly searches a border hierarchy (starting at <code>border) for
+ * a titled border and returns the title if one is found, <code>null</code>
+ * otherwise.
+ *
+ * @param border the border to start search from
+ *
+ * @return the border title of a possibly found titled border
+ */
+ protected String getBorderTitle(Border border)
+ {
+ String title = null;
+ if (border instanceof CompoundBorder)
+ {
+ CompoundBorder compound = (CompoundBorder) border;
+ Border inner = compound.getInsideBorder();
+ title = getBorderTitle(inner);
+ if (title == null)
+ {
+ Border outer = compound.getOutsideBorder();
+ title = getBorderTitle(outer);
+ }
+ }
+ else if (border instanceof TitledBorder)
+ {
+ TitledBorder titled = (TitledBorder) border;
+ title = titled.getTitle();
+ }
+ return title;
+ }
+
+ /**
+ * Returns the tooltip text for this accessible component.
+ *
+ * @return the tooltip text for this accessible component
+ */
+ public String getToolTipText()
+ {
+ return JComponent.this.getToolTipText();
+ }
+
+ /**
+ * Returns the title of the border of this accessible component if
+ * this component has a titled border, otherwise returns <code>null</code>.
+ *
+ * @return the title of the border of this accessible component if
+ * this component has a titled border, otherwise returns
+ * <code>null</code>
+ */
+ public String getTitledBorderText()
+ {
+ return getBorderTitle(getBorder());
+ }
+
+ /**
+ * Returns the keybindings associated with this accessible component or
+ * <code>null</code> if the component does not support key bindings.
+ *
+ * @return the keybindings associated with this accessible component
+ */
+ public AccessibleKeyBinding getAccessibleKeyBinding()
+ {
+ // TODO: Implement this properly.
+ 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.
+ * 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.
+ * 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.
+ * ComponentUI#getMaximumSize} method on the {@link #ui} property.
*/
Dimension maximumSize;
@@ -191,7 +390,7 @@ public abstract class JComponent extends Container implements Serializable
* @see javax.swing.OverlayLayout
* @see javax.swing.BoxLayout
*/
- float alignmentX = 0.5f;
+ float alignmentX = -1.0F;
/**
* A value between 0.0 and 1.0 indicating the preferred vertical
@@ -206,7 +405,7 @@ public abstract class JComponent extends Container implements Serializable
* @see javax.swing.OverlayLayout
* @see javax.swing.BoxLayout
*/
- float alignmentY = 0.5f;
+ float alignmentY = -1.0F;
/**
* The border painted around this component.
@@ -219,14 +418,14 @@ public abstract class JComponent extends Container implements Serializable
* The text to show in the tooltip associated with this component.
*
* @see #setToolTipText
- * @see #getToolTipText
+ * @see #getToolTipText()
*/
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>
+ * should generally be <code>true</code>, to ensure good painting
+ * performance.</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
@@ -234,22 +433,21 @@ public abstract class JComponent extends Container implements Serializable
*
* @see #setDoubleBuffered
* @see #isDoubleBuffered
- * @see #paintLock
* @see #paint
*/
- boolean doubleBuffered = false;
+ boolean doubleBuffered = true;
/**
* 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}.
+ * {@link DebugGraphics#NONE_OPTION}, {@link DebugGraphics#LOG_OPTION},
+ * {@link DebugGraphics#FLASH_OPTION}, or {@link
+ * DebugGraphics#BUFFERED_OPTION}.
*
- * @see setDebugGraphicsOptions
- * @see getDebugGraphicsOptions
+ * @see #setDebugGraphicsOptions
+ * @see #getDebugGraphicsOptions
* @see DebugGraphics
- * @see getComponentGraphics
+ * @see #getComponentGraphics
*/
int debugGraphicsOptions;
@@ -299,7 +497,7 @@ public abstract class JComponent extends Container implements Serializable
* try to request focus, but the request might fail. Thus it is only
* a hint guiding swing's behavior.
*
- * @see #requestFocus
+ * @see #requestFocus()
* @see #isRequestFocusEnabled
* @see #setRequestFocusEnabled
*/
@@ -312,12 +510,18 @@ public abstract class JComponent extends Container implements Serializable
* 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
+ * @see #setAutoscrolls
+ * @see #getAutoscrolls
*/
boolean autoscrolls = false;
/**
+ * Indicates whether the current paint call is already double buffered or
+ * not.
+ */
+ static boolean isPaintingDoubleBuffered = false;
+
+ /**
* Listeners for events other than {@link PropertyChangeEvent} are
* handled by this listener list. PropertyChangeEvents are handled in
* {@link #changeSupport}.
@@ -342,7 +546,7 @@ public abstract class JComponent extends Container implements Serializable
private InputMap inputMap_whenFocused;
private InputMap inputMap_whenAncestorOfFocused;
- private InputMap inputMap_whenInFocusedWindow;
+ private ComponentInputMap inputMap_whenInFocusedWindow;
private ActionMap actionMap;
/** @since 1.3 */
private boolean verifyInputWhenFocusTarget;
@@ -350,16 +554,17 @@ public abstract class JComponent extends Container implements Serializable
private TransferHandler transferHandler;
- /**
- * 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
+ /**
+ * Indicates if this component is currently painting a tile or not.
+ */
+ private boolean paintingTile;
+
+ /**
+ * A cached Rectangle object to be reused. Be careful when you use that,
+ * so that it doesn't get modified in another context within the same
+ * method call chain.
*/
- private static final Object paintLock = new Object();
+ private static transient Rectangle rectCache;
/**
* The default locale of the component.
@@ -404,6 +609,13 @@ public abstract class JComponent extends Container implements Serializable
public static final int WHEN_IN_FOCUSED_WINDOW = 2;
/**
+ * Indicates if this component is completely dirty or not. This is used
+ * by the RepaintManager's
+ * {@link RepaintManager#isCompletelyDirty(JComponent)} method.
+ */
+ boolean isCompletelyDirty = false;
+
+ /**
* Creates a new <code>JComponent</code> instance.
*/
public JComponent()
@@ -452,7 +664,9 @@ public abstract class JComponent extends Container implements Serializable
/**
* 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.
+ * associated with <code>key</code>, it will be replaced. A
+ * {@link PropertyChangeEvent} is sent to registered listeners (with the
+ * name of the property being <code>key.toString()</code>).
*
* @param key The key of the client property association to add
* @param value The value of the client property association to add
@@ -463,10 +677,13 @@ public abstract class JComponent extends Container implements Serializable
*/
public final void putClientProperty(Object key, Object value)
{
+ Hashtable t = getClientProperties();
+ Object old = t.get(key);
if (value != null)
- getClientProperties().put(key, value);
+ t.put(key, value);
else
- getClientProperties().remove(key);
+ t.remove(key);
+ firePropertyChange(key.toString(), old, value);
}
/**
@@ -771,7 +988,8 @@ public abstract class JComponent extends Container implements Serializable
{
VetoableChangeListener[] listeners = getVetoableChangeListeners();
- PropertyChangeEvent evt = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
+ PropertyChangeEvent evt =
+ new PropertyChangeEvent(this, propertyName, oldValue, newValue);
for (int i = 0; i < listeners.length; i++)
listeners[i].vetoableChange(evt);
@@ -797,7 +1015,12 @@ public abstract class JComponent extends Container implements Serializable
*/
public float getAlignmentX()
{
- return alignmentX;
+ float ret = alignmentX;
+ if (alignmentX < 0)
+ // alignment has not been set explicitly.
+ ret = super.getAlignmentX();
+
+ return ret;
}
/**
@@ -810,7 +1033,12 @@ public abstract class JComponent extends Container implements Serializable
*/
public float getAlignmentY()
{
- return alignmentY;
+ float ret = alignmentY;
+ if (alignmentY < 0)
+ // alignment has not been set explicitly.
+ ret = super.getAlignmentY();
+
+ return ret;
}
/**
@@ -832,9 +1060,13 @@ public abstract class JComponent extends Container implements Serializable
*/
public void setBorder(Border newBorder)
{
- Border oldBorder = border;
+ Border oldBorder = getBorder();
+ if (oldBorder == newBorder)
+ return;
+
border = newBorder;
firePropertyChange("border", oldBorder, newBorder);
+ repaint();
}
/**
@@ -885,10 +1117,19 @@ public abstract class JComponent extends Container implements Serializable
* @see #paint
*/
protected Graphics getComponentGraphics(Graphics g)
- {
- g.setFont (this.getFont());
- g.setColor (this.getForeground());
- return g;
+ {
+ Graphics g2 = g;
+ int options = getDebugGraphicsOptions();
+ if (options != DebugGraphics.NONE_OPTION)
+ {
+ if (!(g2 instanceof DebugGraphics))
+ g2 = new DebugGraphics(g);
+ DebugGraphics dg = (DebugGraphics) g2;
+ dg.setDebugOptions(dg.getDebugOptions() | options);
+ }
+ g2.setFont(this.getFont());
+ g2.setColor(this.getForeground());
+ return g2;
}
/**
@@ -901,7 +1142,19 @@ public abstract class JComponent extends Container implements Serializable
*/
public int getDebugGraphicsOptions()
{
- return 0;
+ String option = System.getProperty("gnu.javax.swing.DebugGraphics");
+ int options = debugGraphicsOptions;
+ if (option != null && option.length() != 0)
+ {
+ if (options < 0)
+ options = 0;
+
+ if (option.equals("LOG"))
+ options |= DebugGraphics.LOG_OPTION;
+ else if (option.equals("FLASH"))
+ options |= DebugGraphics.FLASH_OPTION;
+ }
+ return options;
}
/**
@@ -1298,6 +1551,7 @@ public abstract class JComponent extends Container implements Serializable
*/
public void grabFocus()
{
+ // TODO: Implement this properly.
}
/**
@@ -1366,13 +1620,16 @@ public abstract class JComponent extends Container implements Serializable
}
/**
- * Return <code>true</code> if this component is currently painting a tile.
+ * Return <code>true</code> if this component is currently painting a tile,
+ * this means that paint() is called again on another child component. This
+ * method returns <code>false</code> if this component does not paint a tile
+ * or if the last tile is currently painted.
*
- * @return Whether the component is painting a tile
+ * @return whether the component is painting a tile
*/
public boolean isPaintingTile()
{
- return false;
+ return paintingTile;
}
/**
@@ -1406,16 +1663,6 @@ public abstract class JComponent extends Container implements Serializable
* 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
@@ -1431,32 +1678,30 @@ public abstract class JComponent extends Container implements Serializable
*/
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)
+ // We do a little stunt act here to switch on double buffering if it's
+ // not already on. If we are not already doublebuffered, then we jump
+ // into the method paintDoubleBuffered, which turns on the double buffer
+ // and then calls paint(g) again. In the second call we go into the else
+ // branch of this if statement and actually paint things to the double
+ // buffer. When this method completes, the call stack unwinds back to
+ // paintDoubleBuffered, where the buffer contents is finally drawn to the
+ // screen.
+ if (!isPaintingDoubleBuffered && isDoubleBuffered()
+ && rm.isDoubleBufferingEnabled())
+ paintDoubleBuffered(g);
+ else
{
- if (doubleBuffer != null)
- {
- g2 = doubleBuffer.getGraphics();
- g2.setClip(g.getClipBounds());
- }
-
- g2 = getComponentGraphics(g2);
+ if (g.getClip() == null)
+ g.setClip(0, 0, getWidth(), getHeight());
+ Graphics g2 = getComponentGraphics(g);
paintComponent(g2);
paintBorder(g2);
paintChildren(g2);
-
- if (doubleBuffer != null)
- g.drawImage(doubleBuffer, 0, 0, (ImageObserver) null);
+ Rectangle clip = g2.getClipBounds();
+ if (clip.x == 0 && clip.y == 0 && clip.width == getWidth()
+ && clip.height == getHeight())
+ RepaintManager.currentManager(this).markCompletelyClean(this);
}
}
@@ -1495,7 +1740,69 @@ public abstract class JComponent extends Container implements Serializable
*/
protected void paintChildren(Graphics g)
{
- super.paint(g);
+ Shape originalClip = g.getClip();
+ Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache);
+ g.clipRect(inner.x, inner.y, inner.width, inner.height);
+ Component[] children = getComponents();
+
+ // Find the bottommost component that needs to be painted. This is a
+ // component that completely covers the current clip and is opaque. In
+ // this case we don't need to paint the components below it.
+ int startIndex = children.length - 1;
+ // No need to check for overlapping components when this component is
+ // optimizedDrawingEnabled (== it tiles its children).
+ if (! isOptimizedDrawingEnabled())
+ {
+ Rectangle clip = g.getClipBounds();
+ for (int i = 0; i < children.length; i++)
+ {
+ Rectangle childBounds = children[i].getBounds();
+ if (children[i].isOpaque()
+ && SwingUtilities.isRectangleContainingRectangle(childBounds,
+ g.getClipBounds()))
+ {
+ startIndex = i;
+ break;
+ }
+ }
+ }
+ // paintingTile becomes true just before we start painting the component's
+ // children.
+ paintingTile = true;
+ for (int i = startIndex; i >= 0; --i)
+ {
+ // paintingTile must be set to false before we begin to start painting
+ // the last tile.
+ if (i == 0)
+ paintingTile = false;
+
+ if (!children[i].isVisible())
+ continue;
+
+ Rectangle bounds = children[i].getBounds(rectCache);
+ Rectangle oldClip = g.getClipBounds();
+ if (oldClip == null)
+ oldClip = bounds;
+
+ if (!g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height))
+ continue;
+
+ boolean translated = false;
+ try
+ {
+ g.clipRect(bounds.x, bounds.y, bounds.width, bounds.height);
+ g.translate(bounds.x, bounds.y);
+ translated = true;
+ children[i].paint(g);
+ }
+ finally
+ {
+ if (translated)
+ g.translate(-bounds.x, -bounds.y);
+ g.setClip(oldClip);
+ }
+ }
+ g.setClip(originalClip);
}
/**
@@ -1518,7 +1825,7 @@ public abstract class JComponent extends Container implements Serializable
Graphics g2 = g;
if (!(g instanceof Graphics2D))
g2 = g.create();
- ui.update(getComponentGraphics(g2), this);
+ ui.update(g2, this);
if (!(g instanceof Graphics2D))
g2.dispose();
}
@@ -1544,24 +1851,93 @@ public abstract class JComponent extends Container implements Serializable
* that root pane. This method is called from the {@link RepaintManager}
* and should always be called within the painting thread.
*
+ * <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>
+ *
* @param r The dirty rectangle to paint
*/
public void paintImmediately(Rectangle r)
{
- Component root = SwingUtilities.getRoot(this);
- if (root == null || ! root.isShowing())
+ // Try to find a root pane for this component.
+ //Component root = findPaintRoot(r);
+ Component root = findPaintRoot(r);
+ // If no paint root is found, then this component is completely overlapped
+ // by another component and we don't need repainting.
+ if (root == null)
return;
- Graphics g = root.getGraphics();
- if (g == null)
+ if (root == null || !root.isShowing())
return;
- Rectangle clip = SwingUtilities.convertRectangle(this, r, root);
- g.setClip(clip);
- root.paint(g);
+ Rectangle rootClip = SwingUtilities.convertRectangle(this, r, root);
+ if (root instanceof JComponent)
+ ((JComponent) root).paintImmediately2(rootClip);
+ else
+ root.repaint(rootClip.x, rootClip.y, rootClip.width, rootClip.height);
+ }
+
+ /**
+ * Performs the actual work of paintImmediatly on the repaint root.
+ *
+ * @param r the area to be repainted
+ */
+ void paintImmediately2(Rectangle r)
+ {
+ RepaintManager rm = RepaintManager.currentManager(this);
+ Graphics g = getGraphics();
+ g.setClip(r.x, r.y, r.width, r.height);
+ if (rm.isDoubleBufferingEnabled() && isDoubleBuffered())
+ paintDoubleBuffered(g);
+ else
+ paintSimple(g);
g.dispose();
}
/**
+ * Performs double buffered repainting.
+ *
+ * @param g the graphics context to paint to
+ */
+ void paintDoubleBuffered(Graphics g)
+ {
+
+ Rectangle r = g.getClipBounds();
+ if (r == null)
+ r = new Rectangle(0, 0, getWidth(), getHeight());
+ RepaintManager rm = RepaintManager.currentManager(this);
+
+ // Paint on the offscreen buffer.
+ Image buffer = rm.getOffscreenBuffer(this, getWidth(), getHeight());
+ Graphics g2 = buffer.getGraphics();
+ g2 = getComponentGraphics(g2);
+ g2.setClip(r.x, r.y, r.width, r.height);
+ isPaintingDoubleBuffered = true;
+ paint(g2);
+ isPaintingDoubleBuffered = false;
+ g2.dispose();
+
+ // Paint the buffer contents on screen.
+ g.drawImage(buffer, 0, 0, this);
+ }
+
+ /**
+ * Performs normal painting without double buffering.
+ *
+ * @param g the graphics context to use
+ */
+ void paintSimple(Graphics g)
+ {
+ Graphics g2 = getComponentGraphics(g);
+ paint(g2);
+ }
+
+ /**
* Return a string representation for this component, for use in
* debugging.
*
@@ -1685,7 +2061,11 @@ public abstract class JComponent extends Container implements Serializable
break;
case WHEN_IN_FOCUSED_WINDOW:
- inputMap_whenInFocusedWindow = map;
+ if (map != null && !(map instanceof ComponentInputMap))
+ throw new
+ IllegalArgumentException("WHEN_IN_FOCUSED_WINDOW " +
+ "InputMap must be a ComponentInputMap");
+ inputMap_whenInFocusedWindow = (ComponentInputMap)map;
break;
case UNDEFINED_CONDITION:
@@ -1711,7 +2091,7 @@ public abstract class JComponent extends Container implements Serializable
case WHEN_IN_FOCUSED_WINDOW:
if (inputMap_whenInFocusedWindow == null)
- inputMap_whenInFocusedWindow = new InputMap();
+ inputMap_whenInFocusedWindow = new ComponentInputMap(this);
return inputMap_whenInFocusedWindow;
case UNDEFINED_CONDITION:
@@ -1797,6 +2177,7 @@ public abstract class JComponent extends Container implements Serializable
*/
protected void processComponentKeyEvent(KeyEvent e)
{
+ // This method does nothing, it is meant to be overridden by subclasses.
}
/**
@@ -1825,40 +2206,56 @@ public abstract class JComponent extends Container implements Serializable
// 4. The WHEN_IN_FOCUSED_WINDOW maps of all the enabled components in
// the focused window are searched.
- if (processKeyBinding(KeyStroke.getKeyStrokeForEvent(e),
- e, WHEN_FOCUSED, e.getID() == KeyEvent.KEY_PRESSED))
- // This is step 1 from above comment.
- e.consume();
- else if (processKeyBinding(KeyStroke.getKeyStrokeForEvent(e),
- e, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
- e.getID() == KeyEvent.KEY_PRESSED))
- // This is step 2 from above comment.
- e.consume();
- else
+ KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e);
+ boolean pressed = e.getID() == KeyEvent.KEY_PRESSED;
+
+ if (processKeyBinding(keyStroke, e, WHEN_FOCUSED, pressed))
{
- // This is step 3 from above comment.
- Container current = this;
- while ((current = current.getParent()) instanceof JComponent)
+ // This is step 1 from above comment.
+ e.consume();
+ return;
+ }
+ else if (processKeyBinding
+ (keyStroke, e, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
+ {
+ // This is step 2 from above comment.
+ e.consume();
+ return;
+ }
+
+ // This is step 3 from above comment.
+ Container current = getParent();
+ while (current != null)
+ {
+ // If current is a JComponent, see if it handles the event in its
+ // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps.
+ if ((current instanceof JComponent) &&
+ ((JComponent)current).processKeyBinding
+ (keyStroke, e,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
{
- if (((JComponent)current).processKeyBinding
- (KeyStroke.getKeyStrokeForEvent(e), e,
- WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
- e.getID() == KeyEvent.KEY_PRESSED))
- {
- e.consume();
- break;
- }
- if (current instanceof Window || current instanceof Applet
- || current instanceof JInternalFrame)
- break;
- }
- if (e.isConsumed())
- return;
+ e.consume();
+ return;
+ }
+
+ // Stop when we've tried a top-level container and it didn't handle it
+ if (current instanceof Window || current instanceof Applet)
+ break;
- // This is step 4 from above comment.
- // FIXME: Implement. Note, should use ComponentInputMaps rather
- // than walking the entire containment hierarchy.
+ // Move up the hierarchy
+ current = current.getParent();
}
+
+ // Current being null means the JComponent does not currently have a
+ // top-level ancestor, in which case we don't need to check
+ // WHEN_IN_FOCUSED_WINDOW bindings.
+ if (current == null || e.isConsumed())
+ return;
+
+ // This is step 4 from above comment. KeyboardManager maintains mappings
+ // related to WHEN_IN_FOCUSED_WINDOW bindings so that we don't have to
+ // traverse the containment hierarchy each time.
+ if (KeyboardManager.getManager().processKeyStroke(current, keyStroke, e))
+ e.consume();
}
protected boolean processKeyBinding(KeyStroke ks,
@@ -1975,8 +2372,19 @@ public abstract class JComponent extends Container implements Serializable
*/
public void revalidate()
{
- invalidate();
- RepaintManager.currentManager(this).addInvalidComponent(this);
+ if (! EventQueue.isDispatchThread())
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ revalidate();
+ }
+ });
+ else
+ {
+ invalidate();
+ RepaintManager.currentManager(this).addInvalidComponent(this);
+ }
}
/**
@@ -1999,7 +2407,12 @@ public abstract class JComponent extends Container implements Serializable
*/
public void setAlignmentX(float a)
{
- alignmentX = a;
+ if (a < 0.0F)
+ alignmentX = 0.0F;
+ else if (a > 1.0)
+ alignmentX = 1.0F;
+ else
+ alignmentX = a;
}
/**
@@ -2009,7 +2422,12 @@ public abstract class JComponent extends Container implements Serializable
*/
public void setAlignmentY(float a)
{
- alignmentY = a;
+ if (a < 0.0F)
+ alignmentY = 0.0F;
+ else if (a > 1.0)
+ alignmentY = 1.0F;
+ else
+ alignmentY = a;
}
/**
@@ -2049,9 +2467,11 @@ public abstract class JComponent extends Container implements Serializable
*/
public void setEnabled(boolean enable)
{
- boolean oldEnabled = isEnabled();
+ if (enable == isEnabled())
+ return;
super.setEnabled(enable);
- firePropertyChange("enabled", oldEnabled, enable);
+ firePropertyChange("enabled", !enable, enable);
+ repaint();
}
/**
@@ -2061,7 +2481,11 @@ public abstract class JComponent extends Container implements Serializable
*/
public void setFont(Font f)
{
+ if (f == getFont())
+ return;
super.setFont(f);
+ revalidate();
+ repaint();
}
/**
@@ -2071,7 +2495,10 @@ public abstract class JComponent extends Container implements Serializable
*/
public void setBackground(Color bg)
{
+ if (bg == getBackground())
+ return;
super.setBackground(bg);
+ repaint();
}
/**
@@ -2081,42 +2508,51 @@ public abstract class JComponent extends Container implements Serializable
*/
public void setForeground(Color fg)
{
+ if (fg == getForeground())
+ return;
super.setForeground(fg);
+ repaint();
}
/**
- * Set the value of the {@link #maximumSize} property.
+ * Set the value of the {@link #maximumSize} property. The passed value is
+ * copied, the later direct changes on the argument have no effect on the
+ * property value.
*
* @param max The new value of the property
*/
public void setMaximumSize(Dimension max)
{
Dimension oldMaximumSize = maximumSize;
- maximumSize = max;
+ maximumSize = new Dimension(max);
firePropertyChange("maximumSize", oldMaximumSize, maximumSize);
}
/**
- * Set the value of the {@link #minimumSize} property.
+ * Set the value of the {@link #minimumSize} property. The passed value is
+ * copied, the later direct changes on the argument have no effect on the
+ * property value.
*
* @param min The new value of the property
*/
public void setMinimumSize(Dimension min)
{
Dimension oldMinimumSize = minimumSize;
- minimumSize = min;
+ minimumSize = new Dimension(min);
firePropertyChange("minimumSize", oldMinimumSize, minimumSize);
}
/**
- * Set the value of the {@link #preferredSize} property.
+ * Set the value of the {@link #preferredSize} property. The passed value is
+ * copied, the later direct changes on the argument have no effect on the
+ * property value.
*
* @param pref The new value of the property
*/
public void setPreferredSize(Dimension pref)
{
Dimension oldPreferredSize = preferredSize;
- preferredSize = pref;
+ preferredSize = new Dimension(pref);
firePropertyChange("preferredSize", oldPreferredSize, preferredSize);
}
@@ -2131,6 +2567,7 @@ public abstract class JComponent extends Container implements Serializable
*/
public void setNextFocusableComponent(Component aComponent)
{
+ // TODO: Implement this properly.
}
/**
@@ -2191,11 +2628,29 @@ public abstract class JComponent extends Container implements Serializable
/**
* Set the value of the visible property.
*
+ * If the value is changed, then the AncestorListeners of this component
+ * and all its children (recursivly) are notified.
+ *
* @param v The new value of the property
*/
public void setVisible(boolean v)
{
+ // No need to do anything if the actual value doesn't change.
+ if (isVisible() == v)
+ return;
+
super.setVisible(v);
+
+ // Notify AncestorListeners.
+ if (v == true)
+ fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
+ else
+ fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
+
+ Container parent = getParent();
+ if (parent != null)
+ parent.repaint(getX(), getY(), getWidth(), getHeight());
+ revalidate();
}
/**
@@ -2248,7 +2703,8 @@ public abstract class JComponent extends Container implements Serializable
ui.installUI(this);
firePropertyChange("UI", oldUI, newUI);
-
+ revalidate();
+ repaint();
}
/**
@@ -2427,47 +2883,22 @@ public abstract class JComponent extends Container implements Serializable
*/
public void addNotify()
{
+ // Register the WHEN_IN_FOCUSED_WINDOW keyboard bindings
+ // Note that here we unregister all bindings associated with
+ // this component and then re-register them. This may be more than
+ // necessary if the top-level ancestor hasn't changed. Should
+ // maybe improve this.
+ KeyboardManager km = KeyboardManager.getManager();
+ km.clearBindingsForComp(this);
+ km.registerEntireMap((ComponentInputMap)
+ this.getInputMap(WHEN_IN_FOCUSED_WINDOW));
super.addNotify();
- // let parents inherit the keybord mapping
- InputMap input = getInputMap();
- ActionMap actions = getActionMap();
-
- Container parent = getParent();
- while ((parent != null) && (parent instanceof JComponent))
- {
- JComponent jParent = (JComponent) parent;
- InputMap parentInput = jParent.getInputMap();
- ActionMap parentAction = jParent.getActionMap();
-
- KeyStroke[] ikeys = input.keys();
- for (int i = 0; i < ikeys.length; i++)
- {
- Object o = input.get(ikeys[i]);
- parentInput.put(ikeys[i], o);
- }
-
- Object[] akeys = actions.keys();
- for (int i = 0; i < akeys.length; i++)
- {
- Action a = actions.get(akeys[i]);
- parentAction.put(akeys[i], a);
- }
-
- parent = jParent.getParent();
- }
-
- // notify ancestor listeners
- AncestorListener[] ls = getAncestorListeners();
- AncestorEvent ev = new AncestorEvent(this, AncestorEvent.ANCESTOR_ADDED,
- this, parent);
- for (int i = 0; i < ls.length; i++)
- {
- ls[i].ancestorAdded(ev);
- }
+ // Notify AncestorListeners.
+ fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
// fire property change event for 'ancestor'
- firePropertyChange("ancestor", null, parent);
+ firePropertyChange("ancestor", null, getParent());
}
/**
@@ -2490,43 +2921,14 @@ public abstract class JComponent extends Container implements Serializable
{
super.removeNotify();
- // let parents inherit the keybord mapping
- InputMap input = getInputMap();
- ActionMap actions = getActionMap();
-
- Container parent = getParent();
- while ((parent != null) && (parent instanceof JComponent))
- {
- JComponent jParent = (JComponent) parent;
- InputMap parentInput = jParent.getInputMap();
- ActionMap parentAction = jParent.getActionMap();
-
- KeyStroke[] ikeys = input.allKeys();
- for (int i = 0; i < ikeys.length; i++)
- {
- parentInput.remove(ikeys[i]);
- }
-
- Object[] akeys = actions.allKeys();
- for (int i = 0; i < akeys.length; i++)
- {
- parentAction.remove(akeys[i]);
- }
-
- parent = jParent.getParent();
- }
-
- // notify ancestor listeners
- AncestorListener[] ls = getAncestorListeners();
- AncestorEvent ev = new AncestorEvent(this, AncestorEvent.ANCESTOR_ADDED,
- this, parent);
- for (int i = 0; i < ls.length; i++)
- {
- ls[i].ancestorAdded(ev);
- }
+ // FIXME: remove the WHEN_IN_FOCUSED_WINDOW bindings from the
+ // KeyboardManager
+
+ // Notify ancestor listeners.
+ fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
// fire property change event for 'ancestor'
- firePropertyChange("ancestor", parent, null);
+ firePropertyChange("ancestor", getParent(), null);
}
/**
@@ -2733,6 +3135,215 @@ public abstract class JComponent extends Container implements Serializable
*/
public void reshape(int x, int y, int w, int h)
{
+ int oldX = getX();
+ int oldY = getY();
super.reshape(x, y, w, h);
+ // Notify AncestorListeners.
+ if (oldX != getX() || oldY != getY())
+ fireAncestorEvent(this, AncestorEvent.ANCESTOR_MOVED);
+ }
+
+ /**
+ * Fires an AncestorEvent to this component's and all of its child
+ * component's AncestorListeners.
+ *
+ * @param ancestor the component that triggered the event
+ * @param id the kind of ancestor event that should be fired
+ */
+ void fireAncestorEvent(JComponent ancestor, int id)
+ {
+ // Fire event for registered ancestor listeners of this component.
+ AncestorListener[] listeners = getAncestorListeners();
+ if (listeners.length > 0)
+ {
+ AncestorEvent ev = new AncestorEvent(this, id,
+ ancestor, ancestor.getParent());
+ for (int i = 0; i < listeners.length; i++)
+ {
+ switch (id)
+ {
+ case AncestorEvent.ANCESTOR_MOVED:
+ listeners[i].ancestorMoved(ev);
+ break;
+ case AncestorEvent.ANCESTOR_ADDED:
+ listeners[i].ancestorAdded(ev);
+ break;
+ case AncestorEvent.ANCESTOR_REMOVED:
+ listeners[i].ancestorRemoved(ev);
+ break;
+ }
+ }
+ }
+ // Dispatch event to all children.
+ Component[] children = getComponents();
+ for (int i = 0; i < children.length; i++)
+ {
+ if (!(children[i] instanceof JComponent))
+ continue;
+ JComponent jc = (JComponent) children[i];
+ jc.fireAncestorEvent(ancestor, id);
+ }
+ }
+
+ /**
+ * Finds a suitable paint root for painting this component. This method first
+ * checks if this component is overlapped using
+ * {@link #findOverlapFreeParent(Rectangle)}. The returned paint root is then
+ * feeded to {@link #findOpaqueParent(Component)} to find the nearest opaque
+ * component for this paint root. If no paint is necessary, then we return
+ * <code>null</code>.
+ *
+ * @param c the clip of this component
+ *
+ * @return the paint root or <code>null</code> if no painting is necessary
+ */
+ private Component findPaintRoot(Rectangle c)
+ {
+ Component p = findOverlapFreeParent(c);
+ if (p == null)
+ return null;
+ Component root = findOpaqueParent(p);
+ return root;
+ }
+
+ /**
+ * Scans the containment hierarchy upwards for components that overlap the
+ * this component in the specified clip. This method returns
+ * <code>this</code>, if no component overlaps this component. It returns
+ * <code>null</code> if another component completely covers this component
+ * in the specified clip (no repaint necessary). If another component partly
+ * overlaps this component in the specified clip, then the parent of this
+ * component is returned (this is the component that must be used as repaint
+ * root). For efficient lookup, the method
+ * {@link #isOptimizedDrawingEnabled()} is used.
+ *
+ * @param clip the clip of this component
+ *
+ * @return the paint root, or <code>null</code> if no paint is necessary
+ */
+ private Component findOverlapFreeParent(Rectangle clip)
+ {
+ Rectangle currentClip = clip;
+ Component found = this;
+ Container parent = this;
+ while (parent != null && !(parent instanceof Window))
+ {
+ Container newParent = parent.getParent();
+ if (newParent == null)
+ break;
+ // If the parent is optimizedDrawingEnabled, then its children are
+ // tiled and cannot have an overlapping child. Go directly to next
+ // parent.
+ if (newParent instanceof JComponent
+ && ((JComponent) newParent).isOptimizedDrawingEnabled())
+ {
+ parent = newParent;
+ continue;
+ }
+
+ // First we must check if the new parent itself somehow clips the
+ // target rectangle. This can happen in JViewports.
+ Rectangle parRect = new Rectangle(0, 0, newParent.getWidth(),
+ newParent.getHeight());
+ Rectangle target = SwingUtilities.convertRectangle(found,
+ currentClip,
+ newParent);
+ if (target.contains(parRect) || target.intersects(parRect))
+ {
+ found = newParent;
+ currentClip = target;
+ parent = newParent;
+ continue;
+ }
+
+ // Otherwise we must check if one of the children of this parent
+ // overlaps with the current component.
+ Component[] children = newParent.getComponents();
+ // This flag is used to skip components that are 'below' the component
+ // in question.
+ boolean skip = true;
+ for (int i = children.length - 1; i >= 0; i--)
+ {
+ if (children[i] == parent)
+ skip = false;
+ if (skip)
+ continue;
+ Component c = children[i];
+ Rectangle compBounds = c.getBounds();
+ // If the component completely overlaps the clip in question, we
+ // don't need to repaint. Return null.
+ if (compBounds.contains(target))
+ return null;
+ if (compBounds.intersects(target))
+ {
+ // We found a parent whose children overlap with our current
+ // component. Make this the current component.
+ found = newParent;
+ currentClip = target;
+ break;
+ }
+ }
+ parent = newParent;
+ }
+ return found;
+ }
+
+ /**
+ * Finds the nearest component to <code>c</code> (upwards in the containment
+ * hierarchy), that is opaque. If <code>c</code> itself is opaque,
+ * this returns <code>c</code> itself.
+ *
+ * @param c the start component for the search
+ * @return the nearest component to <code>c</code> (upwards in the containment
+ * hierarchy), that is opaque; If <code>c</code> itself is opaque,
+ * this returns <code>c</code> itself
+ */
+ private Component findOpaqueParent(Component c)
+ {
+ Component found = c;
+ while (true)
+ {
+ if ((found instanceof JComponent) && ((JComponent) found).isOpaque())
+ break;
+ else if (!(found instanceof JComponent))
+ break;
+ Container p = found.getParent();
+ if (p == null)
+ break;
+ else
+ found = p;
+ }
+ return found;
+ }
+
+ /**
+ * This is the method that gets called when the WHEN_IN_FOCUSED_WINDOW map
+ * is changed.
+ *
+ * @param changed the JComponent associated with the WHEN_IN_FOCUSED_WINDOW
+ * map
+ */
+ void updateComponentInputMap(ComponentInputMap changed)
+ {
+ // Since you can change a component's input map via
+ // setInputMap, we have to check if <code>changed</code>
+ // is still in our WHEN_IN_FOCUSED_WINDOW map hierarchy
+ InputMap curr = getInputMap(WHEN_IN_FOCUSED_WINDOW);
+ while (curr != null && curr != changed)
+ curr = curr.getParent();
+
+ // If curr is null then changed is not in the hierarchy
+ if (curr == null)
+ return;
+
+ // Now we have to update the keyboard manager's hashtable
+ KeyboardManager km = KeyboardManager.getManager();
+
+ // This is a poor strategy, should be improved. We currently
+ // delete all the old bindings for the component and then register
+ // the current bindings.
+ km.clearBindingsForComp(changed.getComponent());
+ km.registerEntireMap((ComponentInputMap)
+ getInputMap(WHEN_IN_FOCUSED_WINDOW));
}
}
diff --git a/libjava/classpath/javax/swing/JDesktopPane.java b/libjava/classpath/javax/swing/JDesktopPane.java
index f4c80eca7d6..43ab71e7e9f 100644
--- a/libjava/classpath/javax/swing/JDesktopPane.java
+++ b/libjava/classpath/javax/swing/JDesktopPane.java
@@ -97,6 +97,7 @@ public class JDesktopPane extends JLayeredPane implements Accessible
*/
protected AccessibleJDesktopPane()
{
+ // Nothing to do here.
}
/**
@@ -246,6 +247,7 @@ public class JDesktopPane extends JLayeredPane implements Accessible
}
catch (PropertyVetoException e)
{
+ // We do nothing when the attempt is vetoed.
}
}
selectedFrame = null;
@@ -259,6 +261,7 @@ public class JDesktopPane extends JLayeredPane implements Accessible
}
catch (PropertyVetoException e)
{
+ // We do nothing when the attempt is vetoed.
}
}
diff --git a/libjava/classpath/javax/swing/JDialog.java b/libjava/classpath/javax/swing/JDialog.java
index 0f528ab1b45..b3f7c011f68 100644
--- a/libjava/classpath/javax/swing/JDialog.java
+++ b/libjava/classpath/javax/swing/JDialog.java
@@ -66,6 +66,21 @@ import javax.accessibility.AccessibleContext;
public class JDialog extends Dialog implements Accessible, WindowConstants,
RootPaneContainer
{
+ /**
+ * Provides accessibility support for <code>JDialog</code>s.
+ */
+ protected class AccessibleJDialog extends Dialog.AccessibleAWTDialog
+ {
+ /**
+ * Creates a new instance of <code>AccessibleJDialog</code>.
+ */
+ public AccessibleJDialog()
+ {
+ super();
+ // Nothing to do here.
+ }
+ }
+
private static final long serialVersionUID = -864070866424508218L;
/** DOCUMENT ME! */
@@ -87,13 +102,6 @@ public class JDialog extends Dialog implements Accessible, WindowConstants,
/** Whether JDialogs are decorated by the Look and Feel. */
private static boolean decorated;
- /**
- * Whether we're in the init stage or not.
- * If so, adds and layouts are for top-level, otherwise they're for the
- * content pane
- */
- private boolean initStageDone = false;
-
/* Creates a new non-modal JDialog with no title
* using a shared Frame as the owner.
*/
@@ -244,7 +252,7 @@ public class JDialog extends Dialog implements Accessible, WindowConstants,
invalidate();
// Now that initStageDone is true, adds and layouts apply to contentPane,
// not top-level.
- initStageDone = true;
+ setRootPaneCheckingEnabled(true);
}
/**
@@ -315,13 +323,8 @@ public class JDialog extends Dialog implements Accessible, WindowConstants,
{
// Check if we're in initialization stage. If so, call super.setLayout
// otherwise, valid calls go to the content pane.
- if (initStageDone)
- {
- if (isRootPaneCheckingEnabled())
- throw new Error("Cannot set top-level layout. Use"
- + " getConentPane().setLayout instead.");
- getContentPane().setLayout(manager);
- }
+ if (isRootPaneCheckingEnabled())
+ getContentPane().setLayout(manager);
else
super.setLayout(manager);
}
@@ -445,15 +448,10 @@ public class JDialog extends Dialog implements Accessible, WindowConstants,
{
// If we're adding in the initialization stage use super.add.
// Otherwise pass the add onto the content pane.
- if (!initStageDone)
- super.addImpl(comp, constraints, index);
+ if (isRootPaneCheckingEnabled())
+ getContentPane().add(comp, constraints, index);
else
- {
- if (isRootPaneCheckingEnabled())
- throw new Error("Do not add directly to JDialog."
- + " Use getContentPane().add instead.");
- getContentPane().add(comp, constraints, index);
- }
+ super.addImpl(comp, constraints, index);
}
/**
@@ -588,6 +586,8 @@ public class JDialog extends Dialog implements Accessible, WindowConstants,
*/
public AccessibleContext getAccessibleContext()
{
- return null;
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJDialog();
+ return accessibleContext;
}
}
diff --git a/libjava/classpath/javax/swing/JEditorPane.java b/libjava/classpath/javax/swing/JEditorPane.java
index e2f1319a2a7..9ddf970deea 100644
--- a/libjava/classpath/javax/swing/JEditorPane.java
+++ b/libjava/classpath/javax/swing/JEditorPane.java
@@ -41,15 +41,27 @@ package javax.swing;
import java.awt.Dimension;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.MalformedURLException;
import java.net.URL;
import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleHyperlink;
+import javax.accessibility.AccessibleHypertext;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleText;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultEditorKit;
+import javax.swing.text.Document;
import javax.swing.text.EditorKit;
+import javax.swing.text.Element;
import javax.swing.text.JTextComponent;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.HTMLEditorKit;
/**
* A powerful text editor component that can handle different types of
@@ -76,6 +88,384 @@ import javax.swing.text.JTextComponent;
*/
public class JEditorPane extends JTextComponent
{
+ /**
+ * Provides accessibility support for <code>JEditorPane</code>.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ protected class AccessibleJEditorPane extends AccessibleJTextComponent
+ {
+
+ /**
+ * Creates a new <code>AccessibleJEditorPane</code> object.
+ */
+ protected AccessibleJEditorPane()
+ {
+ super();
+ }
+
+ /**
+ * Returns a description of this <code>AccessibleJEditorPane</code>. If
+ * this property is not set, then this returns the content-type of the
+ * editor pane.
+ *
+ * @return a description of this AccessibleJEditorPane
+ */
+ public String getAccessibleDescription()
+ {
+ String descr = super.getAccessibleDescription();
+ if (descr == null)
+ return getContentType();
+ else
+ return descr;
+ }
+
+ /**
+ * Returns the accessible state of this <code>AccessibleJEditorPane</code>.
+ *
+ * @return the accessible state of this <code>AccessibleJEditorPane</code>
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet state = super.getAccessibleStateSet();
+ // TODO: Figure out what state must be added here to the super's state.
+ return state;
+ }
+ }
+
+ /**
+ * Provides accessibility support for <code>JEditorPane</code>s, when the
+ * editor kit is an instance of {@link HTMLEditorKit}.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ protected class AccessibleJEditorPaneHTML extends AccessibleJEditorPane
+ {
+ /**
+ * Returns the accessible text of the <code>JEditorPane</code>. This will
+ * be an instance of
+ * {@link JEditorPaneAccessibleHypertextSupport}.
+ *
+ * @return the accessible text of the <code>JEditorPane</code>
+ */
+ public AccessibleText getAccessibleText()
+ {
+ return new JEditorPaneAccessibleHypertextSupport();
+ }
+ }
+
+ /**
+ * This is the accessible text that is returned by
+ * {@link AccessibleJEditorPaneHTML#getAccessibleText()}.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ protected class JEditorPaneAccessibleHypertextSupport
+ extends AccessibleJEditorPane implements AccessibleHypertext
+ {
+
+ /**
+ * The accessible representation of a HTML link.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ public class HTMLLink extends AccessibleHyperlink
+ {
+
+ /**
+ * The element in the document that represents the link.
+ */
+ Element element;
+
+ /**
+ * Creates a new <code>HTMLLink</code>.
+ *
+ * @param el the link element
+ */
+ public HTMLLink(Element el)
+ {
+ this.element = el;
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>HTMLLink</code> is still
+ * valid. A <code>HTMLLink</code> can become invalid when the document
+ * changes.
+ *
+ * @return <code>true</code> if this <code>HTMLLink</code> is still
+ * valid
+ */
+ public boolean isValid()
+ {
+ // I test here if the element at our element's start offset is the
+ // same as the element in the document at this offset. If this is true,
+ // I consider the link valid, if not, then this link no longer
+ // represented by this HTMLLink and therefor invalid.
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ return doc.getCharacterElement(element.getStartOffset()) == element;
+ }
+
+ /**
+ * Returns the number of AccessibleActions in this link object. In
+ * general, link have 1 AccessibleAction associated with them. There are
+ * special cases where links can have multiple actions associated, like
+ * in image maps.
+ *
+ * @return the number of AccessibleActions in this link object
+ */
+ public int getAccessibleActionCount()
+ {
+ // TODO: Implement the special cases.
+ return 1;
+ }
+
+ /**
+ * Performs the specified action on the link object. This ususally means
+ * activating the link.
+ *
+ * @return <code>true</code> if the action has been performed
+ * successfully, <code>false</code> otherwise
+ */
+ public boolean doAccessibleAction(int i)
+ {
+ String href = (String) element.getAttributes().getAttribute("href");
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ try
+ {
+ URL url = new URL(doc.getBase(), href);
+ setPage(url);
+ String desc = doc.getText(element.getStartOffset(),
+ element.getEndOffset() - element.getStartOffset());
+ HyperlinkEvent ev =
+ new HyperlinkEvent(JEditorPane.this,
+ HyperlinkEvent.EventType.ACTIVATED, url, desc,
+ element);
+ fireHyperlinkUpdate(ev);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the description of the action at action index <code>i</code>.
+ * This method returns the text within the element associated with this
+ * link.
+ *
+ * @param i the action index
+ *
+ * @return the description of the action at action index <code>i</code>
+ */
+ public String getAccessibleActionDescription(int i)
+ {
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ try
+ {
+ return doc.getText(element.getStartOffset(),
+ element.getEndOffset() - element.getStartOffset());
+ }
+ catch (BadLocationException ex)
+ {
+ throw (AssertionError)
+ new AssertionError("BadLocationException must not be thrown "
+ + "here.")
+ .initCause(ex);
+ }
+ }
+
+ /**
+ * Returns an {@link URL} object, that represents the action at action
+ * index <code>i</code>.
+ *
+ * @param i the action index
+ *
+ * @return an {@link URL} object, that represents the action at action
+ * index <code>i</code>
+ */
+ public Object getAccessibleActionObject(int i)
+ {
+ String href = (String) element.getAttributes().getAttribute("href");
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ try
+ {
+ URL url = new URL(doc.getBase(), href);
+ return url;
+ }
+ catch (MalformedURLException ex)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns an object that represents the link anchor. For examples, if
+ * the link encloses a string, then a <code>String</code> object is
+ * returned, if the link encloses an &lt;img&gt; tag, then an
+ * <code>ImageIcon</code> object is returned.
+ *
+ * @return an object that represents the link anchor
+ */
+ public Object getAccessibleActionAnchor(int i)
+ {
+ // TODO: This is only the String case. Implement all cases.
+ return getAccessibleActionDescription(i);
+ }
+
+ /**
+ * Returns the start index of the hyperlink element.
+ *
+ * @return the start index of the hyperlink element
+ */
+ public int getStartIndex()
+ {
+ return element.getStartOffset();
+ }
+
+ /**
+ * Returns the end index of the hyperlink element.
+ *
+ * @return the end index of the hyperlink element
+ */
+ public int getEndIndex()
+ {
+ return element.getEndOffset();
+ }
+
+ }
+
+ /**
+ * Returns the number of hyperlinks in the document.
+ *
+ * @return the number of hyperlinks in the document
+ */
+ public int getLinkCount()
+ {
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
+ int count = 0;
+ while (linkIter.isValid())
+ {
+ count++;
+ linkIter.next();
+ }
+ return count;
+ }
+
+ /**
+ * Returns the <code>i</code>-th hyperlink in the document or
+ * <code>null</code> if there is no hyperlink with the specified index.
+ *
+ * @param i the index of the hyperlink to return
+ *
+ * @return the <code>i</code>-th hyperlink in the document or
+ * <code>null</code> if there is no hyperlink with the specified
+ * index
+ */
+ public AccessibleHyperlink getLink(int i)
+ {
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
+ int count = 0;
+ while (linkIter.isValid())
+ {
+ count++;
+ if (count == i)
+ break;
+ linkIter.next();
+ }
+ if (linkIter.isValid())
+ {
+ int offset = linkIter.getStartOffset();
+ // TODO: I fetch the element for the link via getCharacterElement().
+ // I am not sure that this is correct, maybe we must use
+ // getParagraphElement()?
+ Element el = doc.getCharacterElement(offset);
+ HTMLLink link = new HTMLLink(el);
+ return link;
+ }
+ else
+ return null;
+ }
+
+ /**
+ * Returns the index of the link element at the character position
+ * <code>c</code> within the document, or <code>-1</code> if there is no
+ * link at the specified position.
+ *
+ * @param c the character index from which to fetch the link index
+ *
+ * @return the index of the link element at the character position
+ * <code>c</code> within the document, or <code>-1</code> if there
+ * is no link at the specified position
+ */
+ public int getLinkIndex(int c)
+ {
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
+ int count = 0;
+ while (linkIter.isValid())
+ {
+ if (linkIter.getStartOffset() <= c && linkIter.getEndOffset() > c)
+ break;
+ count++;
+ linkIter.next();
+ }
+ if (linkIter.isValid())
+ return count;
+ else
+ return -1;
+ }
+
+ /**
+ * Returns the link text of the link at index <code>i</code>, or
+ * <code>null</code>, if there is no link at the specified position.
+ *
+ * @param i the index of the link
+ *
+ * @return the link text of the link at index <code>i</code>, or
+ * <code>null</code>, if there is no link at the specified
+ * position
+ */
+ public String getLinkText(int i)
+ {
+ HTMLDocument doc = (HTMLDocument) getDocument();
+ HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
+ int count = 0;
+ while (linkIter.isValid())
+ {
+ count++;
+ if (count == i)
+ break;
+ linkIter.next();
+ }
+ if (linkIter.isValid())
+ {
+ int offset = linkIter.getStartOffset();
+ // TODO: I fetch the element for the link via getCharacterElement().
+ // I am not sure that this is correct, maybe we must use
+ // getParagraphElement()?
+ Element el = doc.getCharacterElement(offset);
+ try
+ {
+ String text = doc.getText(el.getStartOffset(),
+ el.getEndOffset() - el.getStartOffset());
+ return text;
+ }
+ catch (BadLocationException ex)
+ {
+ throw (AssertionError)
+ new AssertionError("BadLocationException must not be thrown "
+ + "here.")
+ .initCause(ex);
+ }
+ }
+ else
+ return null;
+ }
+ }
+
private static final long serialVersionUID = 3140472492599046285L;
private URL page;
@@ -128,9 +518,21 @@ public class JEditorPane extends JTextComponent
listeners[index].hyperlinkUpdate(event);
}
+ /**
+ * Returns the accessible context associated with this editor pane.
+ *
+ * @return the accessible context associated with this editor pane
+ */
public AccessibleContext getAccessibleContext()
{
- return null;
+ if (accessibleContext == null)
+ {
+ if (getEditorKit() instanceof HTMLEditorKit)
+ accessibleContext = new AccessibleJEditorPaneHTML();
+ else
+ accessibleContext = new AccessibleJEditorPane();
+ }
+ return accessibleContext;
}
public final String getContentType()
@@ -169,12 +571,18 @@ public class JEditorPane extends JTextComponent
public boolean getScrollableTracksViewportHeight()
{
- return false;
+ /* Container parent = getParent();
+ return (parent instanceof JViewport &&
+ parent.isValid());*/
+ return isValid();
}
public boolean getScrollableTracksViewportWidth()
{
- return false;
+ /*Container parent = getParent();
+ return (parent instanceof JViewport &&
+ parent.isValid());*/
+ return isValid();
}
public URL getPage()
@@ -211,9 +619,26 @@ public class JEditorPane extends JTextComponent
/**
* This method initializes from a stream.
*/
- public void read(InputStream in, Object desc)
- throws IOException
+ public void read(InputStream in, Object desc) throws IOException
{
+ EditorKit kit = getEditorKit();
+ if (kit instanceof HTMLEditorKit && desc instanceof HTMLDocument)
+ {
+ Document doc = (Document) desc;
+ try
+ {
+ kit.read(in, doc, 0);
+ }
+ catch (BadLocationException ex)
+ {
+ assert false : "BadLocationException must not be thrown here.";
+ }
+ }
+ else
+ {
+ Reader inRead = new InputStreamReader(in);
+ super.read(inRead, desc);
+ }
}
/**
@@ -222,6 +647,7 @@ public class JEditorPane extends JTextComponent
public static void registerEditorKitForContentType(String type,
String classname)
{
+ // TODO: Implement this properly.
}
/**
@@ -231,6 +657,7 @@ public class JEditorPane extends JTextComponent
String classname,
ClassLoader loader)
{
+ // TODO: Implement this properly.
}
/**
@@ -239,6 +666,7 @@ public class JEditorPane extends JTextComponent
*/
public void replaceSelection(String content)
{
+ // TODO: Implement this properly.
}
/**
@@ -247,6 +675,7 @@ public class JEditorPane extends JTextComponent
*/
public void scrollToReference(String reference)
{
+ // TODO: Implement this properly.
}
public final void setContentType(String type)
@@ -281,6 +710,8 @@ public class JEditorPane extends JTextComponent
firePropertyChange("editorKit", oldValue, newValue);
invalidate();
repaint();
+ // Reset the accessibleContext since this depends on the editorKit.
+ accessibleContext = null;
}
public void setEditorKitForContentType(String type, EditorKit k)
diff --git a/libjava/classpath/javax/swing/JFileChooser.java b/libjava/classpath/javax/swing/JFileChooser.java
index 7569061ab2e..1598641f1b9 100644
--- a/libjava/classpath/javax/swing/JFileChooser.java
+++ b/libjava/classpath/javax/swing/JFileChooser.java
@@ -42,10 +42,13 @@ import java.awt.Frame;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
import java.io.File;
import java.util.ArrayList;
+
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
import javax.swing.JDialog;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileSystemView;
@@ -70,171 +73,324 @@ public class JFileChooser extends JComponent implements Accessible
{
private static final long serialVersionUID = 3162921138695327837L;
- /** DOCUMENT ME! */
+ /**
+ * A dialog type for selecting a file to open.
+ * @see #setDialogType(int)
+ */
public static final int OPEN_DIALOG = 0;
- /** DOCUMENT ME! */
+ /**
+ * A dialog type for selecting a file to save.
+ * @see #setDialogType(int)
+ */
public static final int SAVE_DIALOG = 1;
- /** DOCUMENT ME! */
+ /**
+ * A dialog type for some custom purpose.
+ * @see #setDialogType(int)
+ */
public static final int CUSTOM_DIALOG = 2;
- /** DOCUMENT ME! */
+ /**
+ * A return value indicating the file chooser has been closed by cancelling.
+ *
+ * @see #showOpenDialog(Component)
+ * @see #showSaveDialog(Component)
+ */
public static final int CANCEL_OPTION = 1;
- /** DOCUMENT ME! */
+ /**
+ * A return value indicating the file chooser has been closed by approving
+ * the selection.
+ * @see #showOpenDialog(Component)
+ * @see #showSaveDialog(Component)
+ */
public static final int APPROVE_OPTION = 0;
- /** DOCUMENT ME! */
+ /**
+ * A return value indicating the file chooser has been closed by some error.
+ * @see #showOpenDialog(Component)
+ * @see #showSaveDialog(Component)
+ */
public static final int ERROR_OPTION = -1;
- /** DOCUMENT ME! */
+ /**
+ * A selection mode constant indicating acceptance of files only.
+ * @see #setFileSelectionMode(int)
+ */
public static final int FILES_ONLY = 0;
- /** DOCUMENT ME! */
+ /**
+ * A selection mode constant indicating acceptance of directories only.
+ * @see #setFileSelectionMode(int)
+ */
public static final int DIRECTORIES_ONLY = 1;
- /** DOCUMENT ME! */
+ /**
+ * A selection mode constant indicating acceptance of files and directories.
+ * @see #setFileSelectionMode(int)
+ */
public static final int FILES_AND_DIRECTORIES = 2;
- /** DOCUMENT ME! */
+ /**
+ * Action command string for cancelling the current selection.
+ * @see #cancelSelection()
+ */
public static final String CANCEL_SELECTION = "CancelSelection";
- /** DOCUMENT ME! */
+ /**
+ * Action command string for approving the current selection.
+ * @see #cancelSelection()
+ */
public static final String APPROVE_SELECTION = "ApproveSelection";
- /** DOCUMENT ME! */
+ /**
+ * The name of the property for the approve button text.
+ * @see #setApproveButtonText(String)
+ */
public static final String APPROVE_BUTTON_TEXT_CHANGED_PROPERTY =
"ApproveButtonTextChangedProperty";
- /** DOCUMENT ME! */
+ /**
+ * The name of the property for the approve button tool tip text.
+ * @see #setApproveButtonToolTipText(String)
+ */
public static final String APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY =
"ApproveButtonToolTipTextChangedProperty";
- /** DOCUMENT ME! */
+ /**
+ * The name of the property for the approve button mnemonic.
+ * @see #setApproveButtonMnemonic(int)
+ */
public static final String APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY =
"ApproveButtonMnemonicChangedProperty";
- /** DOCUMENT ME! */
+ /**
+ * The name of the property for control button visibility.
+ * @see #setControlButtonsAreShown(boolean)
+ */
public static final String CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY =
"ControlButtonsAreShownChangedProperty";
- /** DOCUMENT ME! */
+ /**
+ * The name of the property for the current directory.
+ * @see #setCurrentDirectory(File)
+ */
public static final String DIRECTORY_CHANGED_PROPERTY = "directoryChanged";
- /** DOCUMENT ME! */
+ /**
+ * The name of the property for the selected file.
+ * @see #setSelectedFile(File)
+ */
public static final String SELECTED_FILE_CHANGED_PROPERTY =
"SelectedFileChangedProperty";
- /** DOCUMENT ME! */
+ /**
+ * The name of the property for the selected files.
+ * @see #setSelectedFiles(File[])
+ */
public static final String SELECTED_FILES_CHANGED_PROPERTY =
"SelectedFilesChangedProperty";
- /** DOCUMENT ME! */
+ /**
+ * The name of the property for multi-selection.
+ * @see #setMultiSelectionEnabled(boolean)
+ */
public static final String MULTI_SELECTION_ENABLED_CHANGED_PROPERTY =
"MultiSelectionEnabledChangedProperty";
- /** DOCUMENT ME! */
+ /**
+ * The name of the 'file system view' property.
+ * @see #setFileSystemView(FileSystemView)
+ */
public static final String FILE_SYSTEM_VIEW_CHANGED_PROPERTY =
"FileSystemViewChanged";
- /** DOCUMENT ME! */
+ /**
+ * The name of the 'file view' property.
+ * @see #setFileView(FileView)
+ */
public static final String FILE_VIEW_CHANGED_PROPERTY = "fileViewChanged";
- /** DOCUMENT ME! */
+ /**
+ * The name of the 'file hiding enabled' property.
+ * @see #setFileHidingEnabled(boolean)
+ */
public static final String FILE_HIDING_CHANGED_PROPERTY =
"FileHidingChanged";
- /** DOCUMENT ME! */
+ /**
+ * The name of the 'file filter' property.
+ * @see #setFileFilter(FileFilter)
+ */
public static final String FILE_FILTER_CHANGED_PROPERTY =
"fileFilterChanged";
- /** DOCUMENT ME! */
+ /**
+ * The name of the 'file selection mode' property.
+ * @see #setFileSelectionMode(int)
+ */
public static final String FILE_SELECTION_MODE_CHANGED_PROPERTY =
"fileSelectionChanged";
- /** DOCUMENT ME! */
+ /**
+ * The name of the 'accessory' property.
+ * @see #setAccessory(JComponent)
+ */
public static final String ACCESSORY_CHANGED_PROPERTY =
"AccessoryChangedProperty";
- /** DOCUMENT ME! */
+ /**
+ * The name of the 'accept all file filter used' property.
+ * @see #setAcceptAllFileFilterUsed(boolean)
+ */
public static final String ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY =
"acceptAllFileFilterUsedChanged";
- /** DOCUMENT ME! */
+ /**
+ * The name of the 'dialog title' property.
+ * @see #setDialogTitle(String)
+ */
public static final String DIALOG_TITLE_CHANGED_PROPERTY =
"DialogTitleChangedProperty";
- /** DOCUMENT ME! */
+ /**
+ * The name of the 'dialog type' property.
+ * @see #setDialogType(int)
+ */
public static final String DIALOG_TYPE_CHANGED_PROPERTY =
"DialogTypeChangedProperty";
- /** DOCUMENT ME! */
+ /**
+ * The name of the 'choosable file filters' property.
+ * @see #addChoosableFileFilter(FileFilter)
+ */
public static final String CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY =
"ChoosableFileFilterChangedProperty";
- /** DOCUMENT ME! */
+ /**
+ * The accessible context.
+ * @see #getAccessibleContext()
+ */
protected AccessibleContext accessibleContext;
- /** DOCUMENT ME! */
+ /**
+ * The file system view.
+ * @see #setFileSystemView(FileSystemView)
+ */
private FileSystemView fsv;
- /** DOCUMENT ME! */
+ /**
+ * The accessory component.
+ * @see #setAccessory(JComponent)
+ */
private JComponent accessory;
- /** DOCUMENT ME! */
+ /**
+ * The approve button mnemonic.
+ * @see #setApproveButtonMnemonic(int)
+ */
private int approveButtonMnemonic = 0;
- /** DOCUMENT ME! */
+ /**
+ * The approve button text.
+ * @see #setApproveButtonText(String)
+ */
private String approveButtonText;
- /** DOCUMENT ME! */
+ /**
+ * The approve button tool tip text.
+ * @see #setApproveButtonToolTipText(String)
+ */
private String approveButtonToolTipText;
- /** DOCUMENT ME! */
+ /**
+ * The choosable file filters.
+ * @see #addChoosableFileFilter(FileFilter)
+ */
private ArrayList choosableFilters = new ArrayList();
- /** DOCUMENT ME! */
+ /**
+ * A flag controlling whether the accept all file filter is used.
+ * @see #setAcceptAllFileFilterUsed(boolean)
+ */
private boolean isAcceptAll = true;
- /** DOCUMENT ME! */
+ /**
+ * The dialog title.
+ * @see #setDialogTitle(String)
+ */
private String dialogTitle;
- /** DOCUMENT ME! */
+ /**
+ * The dialog type.
+ * @see #setDialogType(int)
+ */
private int dialogType = OPEN_DIALOG;
- /** DOCUMENT ME! */
+ /**
+ * The return value for the dialog.
+ * @see #showOpenDialog(Component)
+ * @see #showSaveDialog(Component)
+ */
private int retval = ERROR_OPTION;
- /** DOCUMENT ME! */
+ /**
+ * A flag indicating whether the file chooser allows multiple selection.
+ * @see #isMultiSelectionEnabled()
+ */
private boolean multiSelection = false;
- /** DOCUMENT ME! */
+ /**
+ * A flag indicating whether file hiding is enabled.
+ * @see #isFileHidingEnabled()
+ */
private boolean fileHiding = true;
- /** DOCUMENT ME! */
+ /**
+ * The file selection mode.
+ * @see #setFileSelectionMode(int)
+ */
private int fileSelectionMode = FILES_AND_DIRECTORIES;
- /** DOCUMENT ME! */
+ /**
+ * The file view.
+ * @see #setFileView(FileView)
+ */
private FileView fv = null;
- /** DOCUMENT ME! */
+ /**
+ * A flag controlling whether or not the control buttons are visible.
+ * @see #setControlButtonsAreShown(boolean)
+ */
private boolean controlButtonsShown = true;
- /** DOCUMENT ME! */
+ /**
+ * The current directory.
+ * @see #setCurrentDirectory(File)
+ */
private File currentDir = null;
- /** DOCUMENT ME! */
+ /**
+ * The current file filter.
+ * @see #setFileFilter(FileFilter)
+ */
private FileFilter currentFilter = null;
- /** DOCUMENT ME! */
+ /**
+ * An array of selected files.
+ * @see #setSelectedFiles(File[])
+ */
private File[] selectedFiles;
- /** DOCUMENT ME! */
+ /**
+ * The selected file.
+ * @see #setSelectedFile(File)
+ */
private File selectedFile;
/**
- * Creates a new JFileChooser object.
+ * Creates a new <code>JFileChooser</code> object.
*/
public JFileChooser()
{
@@ -243,9 +399,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * Creates a new JFileChooser object.
+ * Creates a new <code>JFileChooser</code> object.
*
- * @param currentDirectoryPath DOCUMENT ME!
+ * @param currentDirectoryPath the directory that should initially be
+ * shown in the filechooser (if <code>null</code>, the user's home
+ * directory is used).
*/
public JFileChooser(String currentDirectoryPath)
{
@@ -254,12 +412,14 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * Creates a new JFileChooser object with the specified directory and
- * FileSystemView.
+ * Creates a new <code>JFileChooser</code> object with the specified
+ * directory and {@link FileSystemView}.
*
- * @param currentDirectoryPath the directory that should initially be
- * shown the filechooser
- * @param fsv the FileSystemView object to use
+ * @param currentDirectoryPath the directory that should initially be
+ * shown in the filechooser (if <code>null</code>, the user's home
+ * directory is used).
+ * @param fsv the file system view (if <code>null</code>, the default file
+ * system view is used).
*/
public JFileChooser(String currentDirectoryPath, FileSystemView fsv)
{
@@ -268,9 +428,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * Creates a new JFileChooser object.
+ * Creates a new <code>JFileChooser</code> object.
*
- * @param currentDirectory DOCUMENT ME!
+ * @param currentDirectory the directory that should initially be
+ * shown in the filechooser (if <code>null</code>, the user's home
+ * directory is used).
*/
public JFileChooser(File currentDirectory)
{
@@ -279,9 +441,10 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * Creates a new JFileChooser object.
+ * Creates a new <code>JFileChooser</code> object.
*
- * @param fsv DOCUMENT ME!
+ * @param fsv the file system view (if <code>null</code>, the default file
+ * system view is used).
*/
public JFileChooser(FileSystemView fsv)
{
@@ -290,10 +453,13 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * Creates a new JFileChooser object.
+ * Creates a new <code>JFileChooser</code> object.
*
- * @param currentDirectory DOCUMENT ME!
- * @param fsv DOCUMENT ME!
+ * @param currentDirectory the directory that should initially be
+ * shown in the filechooser (if <code>null</code>, the user's home
+ * directory is used).
+ * @param fsv the file system view (if <code>null</code>, the default file
+ * system view is used).
*/
public JFileChooser(File currentDirectory, FileSystemView fsv)
{
@@ -302,9 +468,12 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets up the file chooser. This method is called by all the constructors.
*
- * @param view DOCUMENT ME!
+ * @param view the file system view (if <code>null</code>, the default file
+ * system view is used).
+ *
+ * @see FileSystemView#getFileSystemView()
*/
protected void setup(FileSystemView view)
{
@@ -336,9 +505,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the selected file, if there is one.
*
- * @return DOCUMENT ME!
+ * @return The selected file (possibly <code>null</code>).
+ *
+ * @see #setSelectedFile(File)
*/
public File getSelectedFile()
{
@@ -346,9 +517,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the selected file and sends a {@link PropertyChangeEvent} to all
+ * registered listeners. The property name is
+ * {@link #SELECTED_FILE_CHANGED_PROPERTY}.
*
- * @param file DOCUMENT ME!
+ * @param file the file (<code>null</code> permitted).
*/
public void setSelectedFile(File file)
{
@@ -361,9 +534,10 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the selected file or files.
*
- * @return DOCUMENT ME!
+ * @return An array of the selected files, or <code>null</code> if there are
+ * no selected files.
*/
public File[] getSelectedFiles()
{
@@ -375,9 +549,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the selected files and sends a {@link PropertyChangeEvent} (with the
+ * name {@link #SELECTED_FILES_CHANGED_PROPERTY}) to all registered
+ * listeners.
*
- * @param selectedFiles DOCUMENT ME!
+ * @param selectedFiles the selected files (<code>null</code> permitted).
*/
public void setSelectedFiles(File[] selectedFiles)
{
@@ -393,9 +569,9 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the current directory.
*
- * @return DOCUMENT ME!
+ * @return The current directory.
*/
public File getCurrentDirectory()
{
@@ -403,9 +579,15 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the current directory and fires a {@link PropertyChangeEvent} (with
+ * the property name {@link #DIRECTORY_CHANGED_PROPERTY}) to all registered
+ * listeners. If <code>dir</code> is <code>null</code>, the current
+ * directory is set to the default directory returned by the file system
+ * view.
*
- * @param dir DOCUMENT ME!
+ * @param dir the new directory (<code>null</code> permitted).
+ *
+ * @see FileSystemView#getDefaultDirectory()
*/
public void setCurrentDirectory(File dir)
{
@@ -421,7 +603,7 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Called by the UI delegate when the parent directory is changed.
*/
public void changeToParentDirectory()
{
@@ -430,7 +612,7 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Rescans the current directory (this is handled by the UI delegate).
*/
public void rescanCurrentDirectory()
{
@@ -438,9 +620,10 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Ensures the the specified file is visible (this is handled by the
+ * UI delegate).
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*/
public void ensureFileIsVisible(File f)
{
@@ -448,11 +631,14 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Displays the file chooser in a modal dialog using the
+ * {@link #OPEN_DIALOG} type.
*
- * @param parent DOCUMENT ME!
+ * @param parent the parent component.
*
- * @return DOCUMENT ME!
+ * @return A return value indicating how the dialog was closed (one of
+ * {@link #APPROVE_OPTION}, {@link #CANCEL_OPTION} and
+ * {@link #ERROR_OPTION}).
*
* @throws HeadlessException DOCUMENT ME!
*/
@@ -472,11 +658,14 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Displays the file chooser in a modal dialog using the
+ * {@link #SAVE_DIALOG} type.
*
- * @param parent DOCUMENT ME!
+ * @param parent the parent component.
*
- * @return DOCUMENT ME!
+ * @return A return value indicating how the dialog was closed (one of
+ * {@link #APPROVE_OPTION}, {@link #CANCEL_OPTION} and
+ * {@link #ERROR_OPTION}).
*
* @throws HeadlessException DOCUMENT ME!
*/
@@ -493,12 +682,14 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Displays the file chooser in a modal dialog using the
+ * {@link #CUSTOM_DIALOG} type.
*
- * @param parent DOCUMENT ME!
- * @param approveButtonText DOCUMENT ME!
+ * @param parent the parent component.
*
- * @return DOCUMENT ME!
+ * @return A return value indicating how the dialog was closed (one of
+ * {@link #APPROVE_OPTION}, {@link #CANCEL_OPTION} and
+ * {@link #ERROR_OPTION}).
*
* @throws HeadlessException DOCUMENT ME!
*/
@@ -517,11 +708,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Creates a modal dialog in which to display the file chooser.
*
- * @param parent DOCUMENT ME!
+ * @param parent the parent component.
*
- * @return DOCUMENT ME!
+ * @return The dialog.
*
* @throws HeadlessException DOCUMENT ME!
*/
@@ -542,9 +733,12 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the flag that controls whether or not the control buttons are
+ * shown on the file chooser.
*
- * @return DOCUMENT ME!
+ * @return A boolean.
+ *
+ * @see #setControlButtonsAreShown(boolean)
*/
public boolean getControlButtonsAreShown()
{
@@ -552,9 +746,12 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the flag that controls whether or not the control buttons are
+ * shown and, if it changes, sends a {@link PropertyChangeEvent} (with the
+ * property name {@link #CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY}) to
+ * all registered listeners.
*
- * @param b DOCUMENT ME!
+ * @param b the new value for the flag.
*/
public void setControlButtonsAreShown(boolean b)
{
@@ -567,9 +764,12 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the type of file chooser.
*
- * @return DOCUMENT ME!
+ * @return {@link #OPEN_DIALOG}, {@link #SAVE_DIALOG} or
+ * {@link #CUSTOM_DIALOG}.
+ *
+ * @see #setDialogType(int)
*/
public int getDialogType()
{
@@ -577,9 +777,14 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the dialog type and fires a {@link PropertyChangeEvent} (with the
+ * property name {@link #DIALOG_TYPE_CHANGED_PROPERTY}) to all
+ * registered listeners.
*
- * @param dialogType DOCUMENT ME!
+ * @param dialogType the dialog type (one of: {@link #OPEN_DIALOG},
+ * {@link #SAVE_DIALOG}, {@link #CUSTOM_DIALOG}).
+ *
+ * @throws IllegalArgumentException if <code>dialogType</code> is not valid.
*/
public void setDialogType(int dialogType)
{
@@ -596,9 +801,13 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the dialog title and sends a {@link PropertyChangeEvent} (with the
+ * property name {@link #DIALOG_TITLE_CHANGED_PROPERTY}) to all
+ * registered listeners.
*
- * @param dialogTitle DOCUMENT ME!
+ * @param dialogTitle the dialog title (<code>null</code> permitted).
+ *
+ * @see #getDialogTitle()
*/
public void setDialogTitle(String dialogTitle)
{
@@ -611,9 +820,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the dialog title.
*
- * @return DOCUMENT ME!
+ * @return The dialog title (possibly <code>null</code>).
+ *
+ * @see #setDialogTitle(String)
*/
public String getDialogTitle()
{
@@ -621,9 +832,12 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the tool tip text for the approve button and sends a
+ * {@link PropertyChangeEvent} (with the property name
+ * {@link #APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY}) to all
+ * registered listeners.
*
- * @param toolTipText DOCUMENT ME!
+ * @param toolTipText the text.
*/
public void setApproveButtonToolTipText(String toolTipText)
{
@@ -637,9 +851,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the tool tip text for the approve button.
*
- * @return DOCUMENT ME!
+ * @return The tool tip text for the approve button.
+ *
+ * @see #setApproveButtonToolTipText(String)
*/
public String getApproveButtonToolTipText()
{
@@ -647,9 +863,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the approve button mnemonic, or zero if no mnemonic has been set.
*
- * @return DOCUMENT ME!
+ * @return The approve button mnemonic.
+ *
+ * @see #setApproveButtonMnemonic(int)
*/
public int getApproveButtonMnemonic()
{
@@ -657,9 +875,14 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the mnemonic for the approve button and sends a
+ * {@link PropertyChangeEvent} (with the property name
+ * {@link #APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY}) to all registered
+ * listeners.
*
- * @param mnemonic DOCUMENT ME!
+ * @param mnemonic the mnemonic.
+ *
+ * @see #setApproveButtonMnemonic(char)
*/
public void setApproveButtonMnemonic(int mnemonic)
{
@@ -673,9 +896,14 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the mnemonic for the approve button and sends a
+ * {@link PropertyChangeEvent} (with the property name
+ * {@link #APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY}) to all registered
+ * listeners.
*
- * @param mnemonic DOCUMENT ME!
+ * @param mnemonic the mnemonic.
+ *
+ * @see #setApproveButtonMnemonic(int)
*/
public void setApproveButtonMnemonic(char mnemonic)
{
@@ -683,9 +911,13 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the approve button text and fires a {@link PropertyChangeEvent}
+ * (with the property name {@link #APPROVE_BUTTON_TEXT_CHANGED_PROPERTY}) to
+ * all registered listeners.
*
- * @param approveButtonText DOCUMENT ME!
+ * @param approveButtonText the text (<code>null</code> permitted).
+ *
+ * @see #getApproveButtonText()
*/
public void setApproveButtonText(String approveButtonText)
{
@@ -699,9 +931,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the approve button text.
*
- * @return DOCUMENT ME!
+ * @return The approve button text (possibly <code>null</code>).
+ *
+ * @see #setApproveButtonText(String)
*/
public String getApproveButtonText()
{
@@ -709,19 +943,22 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the available file filters for this file chooser.
*
- * @return DOCUMENT ME!
+ * @return The available file filters.
*/
public FileFilter[] getChoosableFileFilters()
{
- return (FileFilter[]) choosableFilters.toArray(new FileFilter[0]);
+ return (FileFilter[]) choosableFilters.toArray(new FileFilter[choosableFilters.size()]);
}
/**
- * DOCUMENT ME!
+ * Adds a file filter to the list of available filters and sends a
+ * {@link PropertyChangeEvent} (with the property name
+ * {@link #CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY}) to all registered
+ * listeners.
*
- * @param filter DOCUMENT ME!
+ * @param filter the filter.
*/
public void addChoosableFileFilter(FileFilter filter)
{
@@ -732,11 +969,15 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Removes a file filter from the list of available filters and sends a
+ * {@link PropertyChangeEvent} (with the property name
+ * {@link #CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY}) to all registered
+ * listeners.
*
- * @param f DOCUMENT ME!
+ * @param f the file filter.
*
- * @return DOCUMENT ME!
+ * @return <code>true</code> if the filter was removed and
+ * <code>false</code> otherwise.
*/
public boolean removeChoosableFileFilter(FileFilter f)
{
@@ -749,7 +990,8 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Clears the list of choosable file filters and installs the 'accept all'
+ * filter from the UI delegate.
*/
public void resetChoosableFileFilters()
{
@@ -759,9 +1001,9 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the 'accept all' file filter from the UI delegate.
*
- * @return DOCUMENT ME!
+ * @return The 'accept all' file filter.
*/
public FileFilter getAcceptAllFileFilter()
{
@@ -769,9 +1011,12 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the flag that controls whether or not the 'accept all' file
+ * filter is included in the list of filters.
*
- * @return DOCUMENT ME!
+ * @return A boolean.
+ *
+ * @see #setAcceptAllFileFilterUsed(boolean)
*/
public boolean isAcceptAllFileFilterUsed()
{
@@ -779,9 +1024,13 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the flag that controls whether or not the 'accept all' file filter
+ * is included in the list of filters, and sends a
+ * {@link PropertyChangeEvent} (with the property name
+ * {@link #ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY}) to all registered
+ * listeners.
*
- * @param b DOCUMENT ME!
+ * @param b the new value of the flag.
*/
public void setAcceptAllFileFilterUsed(boolean b)
{
@@ -794,9 +1043,12 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the accessory component for the file chooser. The default
+ * value is <code>null</code>.
*
- * @return DOCUMENT ME!
+ * @return The accessory component (possibly <code>null</code>).
+ *
+ * @see #setAccessory(JComponent)
*/
public JComponent getAccessory()
{
@@ -804,9 +1056,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the accessory component for the file chooser and sends a
+ * {@link PropertyChangeEvent} to all registered listeners. The property
+ * name is {@link #ACCESSORY_CHANGED_PROPERTY}.
*
- * @param newAccessory DOCUMENT ME!
+ * @param newAccessory the accessory component.
*/
public void setAccessory(JComponent newAccessory)
{
@@ -819,9 +1073,14 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the file selection mode and sends a {@link PropertyChangeEvent}
+ * to all registered listeners. The property name is
+ * {@link #FILE_SELECTION_MODE_CHANGED_PROPERTY}.
*
- * @param mode DOCUMENT ME!
+ * @param mode the mode ({@link #FILES_ONLY}, {@link #DIRECTORIES_ONLY} or
+ * {@link #FILES_AND_DIRECTORIES}).
+ *
+ * @throws IllegalArgumentException if the mode is invalid.
*/
public void setFileSelectionMode(int mode)
{
@@ -838,9 +1097,13 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the file selection mode, one of: {@link #FILES_ONLY},
+ * {@link #DIRECTORIES_ONLY} or {@link #FILES_AND_DIRECTORIES}. The
+ * default is {@link #FILES_ONLY}.
*
- * @return DOCUMENT ME!
+ * @return The file selection mode.
+ *
+ * @see #setFileSelectionMode(int)
*/
public int getFileSelectionMode()
{
@@ -848,9 +1111,14 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if file selection is enabled, and
+ * <code>false</code> otherwise. File selection is enabled when the
+ * file selection mode is {@link #FILES_ONLY} or
+ * {@link #FILES_AND_DIRECTORIES}.
*
- * @return DOCUMENT ME!
+ * @return <code>true</code> if file selection is enabled.
+ *
+ * @see #getFileSelectionMode()
*/
public boolean isFileSelectionEnabled()
{
@@ -859,9 +1127,14 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if directory selection is enabled, and
+ * <code>false</code> otherwise. Directory selection is enabled when the
+ * file selection mode is {@link #DIRECTORIES_ONLY} or
+ * {@link #FILES_AND_DIRECTORIES}.
*
- * @return DOCUMENT ME!
+ * @return <code>true</code> if file selection is enabled.
+ *
+ * @see #getFileSelectionMode()
*/
public boolean isDirectorySelectionEnabled()
{
@@ -870,9 +1143,12 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the flag that controls whether multiple selections are allowed in
+ * this filechooser and sends a {@link PropertyChangeEvent} (with the
+ * property name {@link #MULTI_SELECTION_ENABLED_CHANGED_PROPERTY}) to all
+ * registered listeners.
*
- * @param b DOCUMENT ME!
+ * @param b the new value of the flag.
*/
public void setMultiSelectionEnabled(boolean b)
{
@@ -885,9 +1161,12 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if multiple selections are allowed within this
+ * file chooser, and <code>false</code> otherwise.
*
- * @return DOCUMENT ME!
+ * @return A boolean.
+ *
+ * @see #setMultiSelectionEnabled(boolean)
*/
public boolean isMultiSelectionEnabled()
{
@@ -895,9 +1174,12 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if hidden files are to be hidden, and
+ * <code>false</code> otherwise.
*
- * @return DOCUMENT ME!
+ * @return A boolean.
+ *
+ * @see #setFileHidingEnabled(boolean)
*/
public boolean isFileHidingEnabled()
{
@@ -905,9 +1187,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the flag that controls whether or not hidden files are displayed,
+ * and sends a {@link PropertyChangeEvent} (with the property name
+ * {@link #FILE_HIDING_CHANGED_PROPERTY}) to all registered listeners.
*
- * @param b DOCUMENT ME!
+ * @param b the new value of the flag.
*/
public void setFileHidingEnabled(boolean b)
{
@@ -920,9 +1204,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the file filter and sends a {@link PropertyChangeEvent} (with the
+ * property name {@link #FILE_FILTER_CHANGED_PROPERTY}) to all registered
+ * listeners.
*
- * @param filter DOCUMENT ME!
+ * @param filter the filter.
*/
public void setFileFilter(FileFilter filter)
{
@@ -935,9 +1221,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the file filter.
*
- * @return DOCUMENT ME!
+ * @return The file filter.
+ *
+ * @see #setFileFilter(FileFilter)
*/
public FileFilter getFileFilter()
{
@@ -945,9 +1233,13 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets a custom {@link FileView} for the file chooser and sends a
+ * {@link PropertyChangeEvent} to all registered listeners. The property
+ * name is {@link #FILE_VIEW_CHANGED_PROPERTY}.
+ *
+ * @param fileView the file view (<code>null</code> permitted).
*
- * @param fileView DOCUMENT ME!
+ * @see #getFileView()
*/
public void setFileView(FileView fileView)
{
@@ -960,9 +1252,9 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the custom {@link FileView} for the file chooser.
*
- * @return DOCUMENT ME!
+ * @return The file view (possibly <code>null</code>).
*/
public FileView getFileView()
{
@@ -970,71 +1262,83 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the name of the file, generated by the current (or default)
+ * {@link FileView}.
*
- * @return DOCUMENT ME!
- */
- private FileView getInternalFileView()
- {
- if (fv == null)
- return getUI().getFileView(this);
- return fv;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return The file name.
*/
public String getName(File f)
{
- return getInternalFileView().getName(f);
+ String name = null;
+ if (fv != null)
+ name = fv.getName(f);
+ if (name == null)
+ name = getUI().getFileView(this).getName(f);
+ return name;
}
/**
- * DOCUMENT ME!
+ * Returns the description of the file, generated by the current (or default)
+ * {@link FileView}.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return The file description.
*/
public String getDescription(File f)
{
- return getInternalFileView().getDescription(f);
+ String result = null;
+ if (fv != null)
+ result = fv.getDescription(f);
+ if (result == null)
+ result = getUI().getFileView(this).getDescription(f);
+ return result;
}
/**
- * DOCUMENT ME!
+ * Returns the type description for the file, generated by the current (or
+ * default) {@link FileView}.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return The file type description.
*/
public String getTypeDescription(File f)
{
- return getInternalFileView().getTypeDescription(f);
+ String result = null;
+ if (fv != null)
+ result = getFileView().getTypeDescription(f);
+ if (result == null)
+ result = getUI().getFileView(this).getTypeDescription(f);
+ return result;
}
/**
- * DOCUMENT ME!
+ * Returns the icon provided by the current (or default) {@link FileView}.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return An icon representing the file.
*/
public Icon getIcon(File f)
{
- return getInternalFileView().getIcon(f);
+ Icon result = null;
+ if (fv != null)
+ result = fv.getIcon(f);
+ if (result == null)
+ result = getUI().getFileView(this).getIcon(f);
+ return result;
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if the file is traversable, and
+ * <code>false</code> otherwise.
*
- * @param f DOCUMENT ME!
+ * @param f the file or directory.
*
- * @return DOCUMENT ME!
+ * @return A boolean.
*/
public boolean isTraversable(File f)
{
@@ -1042,11 +1346,12 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if the file is accepted by the current
+ * file filter.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return A boolean.
*/
public boolean accept(File f)
{
@@ -1056,9 +1361,10 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sets the file system view for the file chooser and sends a
+ * {@link PropertyChangeEvent} to all registered listeners.
*
- * @param fsv DOCUMENT ME!
+ * @param fsv the file system view.
*/
public void setFileSystemView(FileSystemView fsv)
{
@@ -1071,9 +1377,11 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the file system view being used by this file chooser.
*
- * @return DOCUMENT ME!
+ * @return The file system view.
+ *
+ * @see #setFileSystemView(FileSystemView)
*/
public FileSystemView getFileSystemView()
{
@@ -1081,7 +1389,8 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Approves the selection. An {@link ActionEvent} is sent to all registered
+ * listeners.
*/
public void approveSelection()
{
@@ -1090,7 +1399,8 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Cancels the selection. An {@link ActionEvent} is sent to all registered
+ * listeners.
*/
public void cancelSelection()
{
@@ -1099,9 +1409,9 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Adds an {@link ActionListener} to the file chooser.
*
- * @param l DOCUMENT ME!
+ * @param l the listener.
*/
public void addActionListener(ActionListener l)
{
@@ -1109,9 +1419,9 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Removes an {@link ActionListener} from this file chooser.
*
- * @param l DOCUMENT ME!
+ * @param l the listener.
*/
public void removeActionListener(ActionListener l)
{
@@ -1126,9 +1436,9 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the action listeners registered with this file chooser.
*
- * @return DOCUMENT ME!
+ * @return An array of listeners.
*/
public ActionListener[] getActionListeners()
{
@@ -1136,9 +1446,9 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Sends an @link {ActionEvent} to all registered listeners.
*
- * @param command DOCUMENT ME!
+ * @param command the action command.
*/
protected void fireActionPerformed(String command)
{
@@ -1151,7 +1461,7 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Installs the UI delegate for the current look and feel.
*/
public void updateUI()
{
@@ -1160,9 +1470,9 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the UI delegate class identifier.
*
- * @return DOCUMENT ME!
+ * @return <code>FileChooserUI</code>.
*/
public String getUIClassID()
{
@@ -1170,9 +1480,9 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the UI delegate for the component.
*
- * @return DOCUMENT ME!
+ * @return The UI delegate.
*/
public FileChooserUI getUI()
{
@@ -1190,12 +1500,29 @@ public class JFileChooser extends JComponent implements Accessible
}
/**
- * DOCUMENT ME!
+ * Returns the accessible context.
*
- * @return DOCUMENT ME!
+ * @return The accessible context.
*/
public AccessibleContext getAccessibleContext()
{
- return null;
+ return new AccessibleJFileChooser();
+ }
+
+ /**
+ * Accessibility support for JFileChooser
+ */
+ protected class AccessibleJFileChooser
+ extends JComponent.AccessibleJComponent
+ {
+ protected AccessibleJFileChooser()
+ {
+ // Nothing to do here.
+ }
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.FILE_CHOOSER;
+ }
}
}
diff --git a/libjava/classpath/javax/swing/JFrame.java b/libjava/classpath/javax/swing/JFrame.java
index 7081f5980e4..8d4dcb53b3c 100644
--- a/libjava/classpath/javax/swing/JFrame.java
+++ b/libjava/classpath/javax/swing/JFrame.java
@@ -50,6 +50,7 @@ import java.awt.LayoutManager;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
+import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
/**
@@ -65,8 +66,31 @@ import javax.accessibility.AccessibleContext;
* @author Ronald Veldema (rveldema@cs.vu.nl)
*/
public class JFrame extends Frame
- implements WindowConstants, RootPaneContainer
+ implements WindowConstants, RootPaneContainer, Accessible
{
+ /**
+ * Provides accessibility support for <code>JFrame</code>s.
+ */
+ protected class AccessibleJFrame extends Frame.AccessibleAWTFrame
+ {
+ /**
+ * Creates a new instance of <code>AccessibleJFrame</code>.
+ */
+ public AccessibleJFrame()
+ {
+ super();
+ // Nothing to do here.
+ }
+ }
+
+ /**
+ * A flag for {@link #setDefaultCloseOperation(int)}, indicating that the
+ * application should be exited, when this <code>JFrame</code> is closed.
+ *
+ * @since 1.3
+ */
+ public static final int EXIT_ON_CLOSE = 3;
+
private static final long serialVersionUID = -3362141868504252139L;
private static boolean defaultLookAndFeelDecorated;
private int close_action = HIDE_ON_CLOSE;
@@ -78,13 +102,6 @@ public class JFrame extends Frame
*/
protected boolean rootPaneCheckingEnabled = false;
- /**
- * Tells us if we're in the initialization stage.
- * If so, adds go to top-level Container, otherwise they go
- * to the content pane for this container.
- */
- private boolean initStageDone = false;
-
public JFrame()
{
super("JFrame");
@@ -134,7 +151,7 @@ public class JFrame extends Frame
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
getRootPane(); // will do set/create
// We're now done the init stage.
- initStageDone = true;
+ setRootPaneCheckingEnabled(true);
}
public Dimension getPreferredSize()
@@ -156,13 +173,8 @@ public class JFrame extends Frame
{
// Check if we're in initialization stage. If so, call super.setLayout
// otherwise, valid calls go to the content pane.
- if (initStageDone)
- {
- if (isRootPaneCheckingEnabled())
- throw new Error("Cannot set layout. Use getContentPane().setLayout()"
- + " instead.");
- getContentPane().setLayout(manager);
- }
+ if (isRootPaneCheckingEnabled())
+ getContentPane().setLayout(manager);
else
super.setLayout(manager);
}
@@ -222,15 +234,10 @@ public class JFrame extends Frame
{
// If we're adding in the initialization stage use super.add.
// Otherwise pass the add onto the content pane.
- if (!initStageDone)
- super.addImpl(comp, constraints, index);
+ if (isRootPaneCheckingEnabled())
+ getContentPane().add(comp,constraints,index);
else
- {
- if (isRootPaneCheckingEnabled())
- throw new Error("rootPaneChecking is enabled - adding components "
- + "disallowed.");
- getContentPane().add(comp,constraints,index);
- }
+ super.addImpl(comp, constraints, index);
}
public void remove(Component comp)
@@ -275,6 +282,8 @@ public class JFrame extends Frame
public AccessibleContext getAccessibleContext()
{
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJFrame();
return accessibleContext;
}
diff --git a/libjava/classpath/javax/swing/JInternalFrame.java b/libjava/classpath/javax/swing/JInternalFrame.java
index b504aaaa5e3..479294b1377 100644
--- a/libjava/classpath/javax/swing/JInternalFrame.java
+++ b/libjava/classpath/javax/swing/JInternalFrame.java
@@ -437,13 +437,6 @@ public class JInternalFrame extends JComponent implements Accessible,
*/
protected boolean rootPaneCheckingEnabled = false;
- /**
- * Tells us if we're in the initialization stage.
- * If so, adds go to top-level Container, otherwise they go
- * to the content pane for this container.
- */
- private boolean initStageDone = false;
-
/** Whether the JInternalFrame is resizable. */
protected boolean resizable;
@@ -567,7 +560,7 @@ public class JInternalFrame extends JComponent implements Accessible,
storedBounds = new Rectangle();
setRootPane(createRootPane());
updateUI();
- initStageDone = true; // Done the init stage, now adds go to content pane.
+ setRootPaneCheckingEnabled(true); // Done the init stage, now adds go to content pane.
}
/**
@@ -587,15 +580,10 @@ public class JInternalFrame extends JComponent implements Accessible,
// If we're in the initialization stage use super.add. Here we add the
// rootPane as well as the title bar and other stuff.
// Otherwise pass the add onto the content pane.
- if (!initStageDone)
- super.addImpl(comp,constraints, index);
+ if (isRootPaneCheckingEnabled())
+ getContentPane().add(comp, constraints, index);
else
- {
- if (isRootPaneCheckingEnabled())
- throw new Error("Do not use add() on JInternalFrame directly. Use "
- + "getContentPane().add() instead");
- getContentPane().add(comp, constraints, index);
- }
+ super.addImpl(comp,constraints, index);
}
/**
@@ -1187,7 +1175,7 @@ public class JInternalFrame extends JComponent implements Accessible,
*/
protected String paramString()
{
- return "JInternalFrame";
+ return super.paramString();
}
/**
@@ -1227,8 +1215,7 @@ public class JInternalFrame extends JComponent implements Accessible,
public void reshape(int x, int y, int width, int height)
{
super.reshape(x, y, width, height);
- invalidate();
- doLayout();
+ revalidate();
}
/**
@@ -1489,13 +1476,8 @@ public class JInternalFrame extends JComponent implements Accessible,
{
// Check if we're in initialization stage. If so, call super.setLayout
// otherwise, valid calls go to the content pane.
- if (initStageDone)
- {
- if (isRootPaneCheckingEnabled())
- throw new Error("Cannot set layout. Use getContentPane().setLayout()"
- + " instead.");
- getContentPane().setLayout(manager);
- }
+ if (isRootPaneCheckingEnabled())
+ getContentPane().setLayout(manager);
else
super.setLayout(manager);
}
@@ -1678,7 +1660,12 @@ public class JInternalFrame extends JComponent implements Accessible,
*/
public void setUI(InternalFrameUI ui)
{
+ // We must temporarily go into init mode so that the UI can directly
+ // manipulate the JInternalFrame.
+ boolean old = isRootPaneCheckingEnabled();
+ setRootPaneCheckingEnabled(false);
super.setUI(ui);
+ setRootPaneCheckingEnabled(old);
}
/**
@@ -1704,7 +1691,13 @@ public class JInternalFrame extends JComponent implements Accessible,
*/
public void updateUI()
{
+ // We must go into the init stage when updating the UI, so the UI can
+ // set layout and components directly on the internal frame, not its
+ // content pane.
+ boolean old = isRootPaneCheckingEnabled();
+ setRootPaneCheckingEnabled(false);
setUI((InternalFrameUI) UIManager.getUI(this));
+ setRootPaneCheckingEnabled(old);
}
/**
diff --git a/libjava/classpath/javax/swing/JLabel.java b/libjava/classpath/javax/swing/JLabel.java
index 2e7ad98ddae..a9adc96b2f4 100644
--- a/libjava/classpath/javax/swing/JLabel.java
+++ b/libjava/classpath/javax/swing/JLabel.java
@@ -331,9 +331,6 @@ public class JLabel extends JComponent implements Accessible, SwingConstants
/** The gap between the icon and the text. */
private transient int iconTextGap = 4;
- /** The accessible context for this JLabel. */
- private AccessibleJLabel accessibleContext;
-
/**
* Creates a new vertically centered, horizontally on the leading edge
* JLabel object with text and no icon.
@@ -403,6 +400,7 @@ public class JLabel extends JComponent implements Accessible, SwingConstants
this.text = text;
this.icon = icon;
this.horizontalAlignment = horizontalAlignment;
+ setAlignmentX(0.0F);
updateUI();
}
@@ -477,12 +475,14 @@ public class JLabel extends JComponent implements Accessible, SwingConstants
{
if (text != newText)
{
- String oldText = text;
- text = newText;
- firePropertyChange("text", oldText, newText);
-
- if (text != null && text.length() <= displayedMnemonicIndex)
- setDisplayedMnemonicIndex(text.length() - 1);
+ String oldText = text;
+ text = newText;
+ firePropertyChange("text", oldText, newText);
+
+ if (text != null && text.length() <= displayedMnemonicIndex)
+ setDisplayedMnemonicIndex(text.length() - 1);
+ revalidate();
+ repaint();
}
}
diff --git a/libjava/classpath/javax/swing/JLayeredPane.java b/libjava/classpath/javax/swing/JLayeredPane.java
index 1ea39dc5007..346570d95b1 100644
--- a/libjava/classpath/javax/swing/JLayeredPane.java
+++ b/libjava/classpath/javax/swing/JLayeredPane.java
@@ -38,14 +38,20 @@ exception statement from your version. */
package javax.swing;
+import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
/**
* A container that adds depth to the usual <code>Container</code> semantics.
@@ -116,6 +122,30 @@ import javax.accessibility.Accessible;
*/
public class JLayeredPane extends JComponent implements Accessible
{
+
+ /**
+ * Provides accessibility support for <code>JLayeredPane</code>.
+ */
+ protected class AccessibleJLayeredPane extends AccessibleJComponent
+ {
+ /**
+ * Creates a new instance of <code>AccessibleJLayeredPane</code>.
+ */
+ public AccessibleJLayeredPane()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the accessble role of <code>JLayeredPane</code>,
+ * {@link AccessibleRole#LAYERED_PANE}.
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.LAYERED_PANE;
+ }
+ }
+
private static final long serialVersionUID = 5534920399324590459L;
public static final String LAYER_PROPERTY = "layeredContainerLayer";
@@ -131,13 +161,15 @@ public class JLayeredPane extends JComponent implements Accessible
TreeMap layers; // Layer Number (Integer) -> Layer Size (Integer)
Hashtable componentToLayer; // Component -> Layer Number (Integer)
+ private transient Rectangle rectCache;
+
public JLayeredPane()
{
layers = new TreeMap ();
componentToLayer = new Hashtable ();
+ setLayout(null);
}
-
/**
* Looks up the layer a child component is currently assigned to.
*
@@ -223,29 +255,37 @@ public class JLayeredPane extends JComponent implements Accessible
ret[1] = getComponents ().length;
Iterator i = layers.entrySet ().iterator ();
while (i.hasNext())
- {
+ {
Map.Entry pair = (Map.Entry) i.next();
Integer layerNum = (Integer) pair.getKey ();
Integer layerSz = (Integer) pair.getValue ();
- if (layerNum.intValue() == layer.intValue())
+ int layerInt = layerNum.intValue();
+ if (layerInt == layer.intValue())
{
ret[0] = ret[1] - layerSz.intValue ();
- return ret;
+ break;
+ }
+ // In the following case there exists no layer with the specified
+ // number, so we return an empty interval here with the index at which
+ // such a layer would be inserted
+ else if (layerInt > layer.intValue())
+ {
+ ret[1] = ret[0];
+ break;
}
else
{
ret[1] -= layerSz.intValue ();
}
- }
- // should have found the layer during iteration
- throw new IllegalArgumentException ();
+ }
+ return ret;
}
/**
* Increments the recorded size of a given layer.
*
* @param layer the layer number to increment.
- * @see #incrLayer()
+ * @see #incrLayer
*/
private void incrLayer(Integer layer)
{
@@ -259,7 +299,7 @@ public class JLayeredPane extends JComponent implements Accessible
* Decrements the recorded size of a given layer.
*
* @param layer the layer number to decrement.
- * @see #decrLayer()
+ * @see #incrLayer
*/
private void decrLayer(Integer layer)
{
@@ -546,26 +586,15 @@ public class JLayeredPane extends JComponent implements Accessible
*
* @param index the index of the child component to remove.
*/
- public void remove (int index)
+ public void remove(int index)
{
- Component c = getComponent (index);
- int layer = getLayer (c);
- decrLayer (new Integer(layer));
- componentToLayer.remove (c);
- super.remove (index);
+ Component c = getComponent(index);
+ int layer = getLayer(c);
+ decrLayer(new Integer(layer));
+ componentToLayer.remove(c);
+ super.remove(index);
+ // FIXME: Figure out if this call is correct.
revalidate();
- repaint();
- }
-
- /**
- * Removes a child from this container. The child is specified directly.
- * After removal, the child no longer occupies a layer.
- *
- * @param comp the child to remove.
- */
- public void remove (Component comp)
- {
- remove (getIndexOf (comp));
}
/**
@@ -613,7 +642,7 @@ public class JLayeredPane extends JComponent implements Accessible
* @param index an ignored parameter, for compatibility.
*/
protected void addImpl(Component comp, Object layerConstraint, int index)
- {
+ {
Integer layer;
if (layerConstraint != null && layerConstraint instanceof Integer)
layer = (Integer) layerConstraint;
@@ -627,10 +656,8 @@ public class JLayeredPane extends JComponent implements Accessible
componentToLayer.put (comp, layer);
incrLayer (layer);
- super.addImpl(comp, null, newIdx);
- revalidate();
- repaint();
- }
+ super.addImpl(comp, null, newIdx);
+ }
/**
* Sets the layer property for a JComponent.
@@ -642,4 +669,50 @@ public class JLayeredPane extends JComponent implements Accessible
{
getLayeredPaneAbove(component).setLayer(component, layer);
}
+
+ /**
+ * Returns the accessible context for this <code>JLayeredPane</code>.
+ *
+ * @return the accessible context for this <code>JLayeredPane</code>
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJLayeredPane();
+ return accessibleContext;
+ }
+
+ /**
+ * This method is overridden order to provide a reasonable painting
+ * mechanism for <code>JLayeredPane</code>. This is necessary since
+ * <code>JLayeredPane</code>'s do not have an own UI delegate.
+ *
+ * Basically this method clears the background for the
+ * <code>JLayeredPane</code> and then calls <code>super.paint(g)</code>.
+ *
+ * @param g the graphics context to use
+ */
+ public void paint(Graphics g)
+ {
+ if (isOpaque())
+ {
+ Color oldColor = g.getColor();
+ Rectangle clip = g.getClipBounds();
+ g.setColor(getBackground());
+ g.fillRect(clip.x, clip.y, clip.width, clip.height);
+ g.setColor(oldColor);
+ }
+ super.paint(g);
+ }
+
+ /**
+ * Overridden to return <code>false</code>, since <code>JLayeredPane</code>
+ * cannot guarantee that its children don't overlap.
+ *
+ * @return <code>false</code>
+ */
+ public boolean isOptimizedDrawingEnabled()
+ {
+ return false;
+ }
}
diff --git a/libjava/classpath/javax/swing/JList.java b/libjava/classpath/javax/swing/JList.java
index 92fe1ccfa67..4f5d3cc72c5 100644
--- a/libjava/classpath/javax/swing/JList.java
+++ b/libjava/classpath/javax/swing/JList.java
@@ -41,13 +41,25 @@ package javax.swing;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
+import java.awt.Cursor;
import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
import java.awt.Point;
import java.awt.Rectangle;
+import java.awt.event.FocusListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Locale;
import java.util.Vector;
import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleComponent;
import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleSelection;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
@@ -108,6 +120,736 @@ import javax.swing.text.Position;
public class JList extends JComponent implements Accessible, Scrollable
{
+
+ /**
+ * Provides accessibility support for <code>JList</code>.
+ */
+ protected class AccessibleJList extends AccessibleJComponent
+ implements AccessibleSelection, PropertyChangeListener,
+ ListSelectionListener, ListDataListener
+ {
+
+ /**
+ * Provides accessibility support for list elements in <code>JList</code>s.
+ */
+ protected class AccessibleJListChild extends AccessibleContext
+ implements Accessible, AccessibleComponent
+ {
+
+ /**
+ * The parent list.
+ */
+ JList parent;
+
+ /**
+ * The index in the list for that child.
+ */
+ int listIndex;
+
+ /**
+ * The cursor for this list child.
+ */
+ // TODO: Testcases show that this class somehow stores state about the
+ // cursor. I cannot make up though how that could affect
+ // the actual list.
+ Cursor cursor = Cursor.getDefaultCursor();
+
+ /**
+ * Creates a new instance of <code>AccessibleJListChild</code>.
+ *
+ * @param list the list of which this is an accessible child
+ * @param index the list index for this child
+ */
+ public AccessibleJListChild(JList list, int index)
+ {
+ parent = list;
+ listIndex = index;
+ }
+
+ /**
+ * Returns the accessible context of this object. Returns
+ * <code>this</code> since <code>AccessibleJListChild</code>s are their
+ * own accessible contexts.
+ *
+ * @return the accessible context of this object, <code>this</code>
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the background color for this list child. This returns the
+ * background of the <code>JList</code> itself since the background
+ * cannot be set on list children individually
+ *
+ * @return the background color for this list child
+ */
+ public Color getBackground()
+ {
+ return parent.getBackground();
+ }
+
+ /**
+ * Calling this method has no effect, since the background color cannot be
+ * set on list children individually.
+ *
+ * @param color not used here.
+ */
+ public void setBackground(Color color)
+ {
+ // Calling this method has no effect, since the background color cannot
+ // be set on list children individually.
+ }
+
+ /**
+ * Returns the foreground color for this list child. This returns the
+ * background of the <code>JList</code> itself since the foreground
+ * cannot be set on list children individually.
+ *
+ * @return the background color for this list child
+ */
+ public Color getForeground()
+ {
+ return parent.getForeground();
+ }
+
+ /**
+ * Calling this method has no effect, since the foreground color cannot be
+ * set on list children individually.
+ *
+ * @param color not used here.
+ */
+ public void setForeground(Color color)
+ {
+ // Calling this method has no effect, since the foreground color cannot
+ // be set on list children individually.
+ }
+
+ /**
+ * Returns the cursor for this list child.
+ *
+ * @return the cursor for this list child
+ */
+ public Cursor getCursor()
+ {
+ // TODO: Testcases show that this method returns the cursor that has
+ // been set by setCursor. I cannot make up though how that could affect
+ // the actual list.
+ return cursor;
+ }
+
+ /**
+ * Sets the cursor for this list child.
+ */
+ public void setCursor(Cursor cursor)
+ {
+ this.cursor = cursor;
+ // TODO: Testcases show that this method returns the cursor that has
+ // been set by setCursor. I cannot make up though how that could affect
+ // the actual list.
+ }
+
+ /**
+ * Returns the font of the <code>JList</code> since it is not possible to
+ * set fonts for list children individually.
+ *
+ * @return the font of the <code>JList</code>
+ */
+ public Font getFont()
+ {
+ return parent.getFont();
+ }
+
+ /**
+ * Does nothing since it is not possible to set the font on list children
+ * individually.
+ *
+ * @param font not used here
+ */
+ public void setFont(Font font)
+ {
+ // Does nothing since it is not possible to set the font on list
+ // children individually.
+ }
+
+ /**
+ * Returns the font metrics for the specified font. This method forwards
+ * to the parent <code>JList</code>.
+ *
+ * @param font the font for which the font metrics is queried
+ *
+ * @return the font metrics for the specified font
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ return parent.getFontMetrics(font);
+ }
+
+ /**
+ * Returns <code>true</code> if the parent <code>JList</code> is enabled,
+ * <code>false</code> otherwise. The list children cannot have an enabled
+ * flag set individually.
+ *
+ * @return <code>true</code> if the parent <code>JList</code> is enabled,
+ * <code>false</code> otherwise
+ */
+ public boolean isEnabled()
+ {
+ return parent.isEnabled();
+ }
+
+ /**
+ * Does nothing since the enabled flag cannot be set for list children
+ * individually.
+ *
+ * @param b not used here
+ */
+ public void setEnabled(boolean b)
+ {
+ // Does nothing since the enabled flag cannot be set for list children
+ // individually.
+ }
+
+ /**
+ * Returns <code>true</code> if this list child is visible,
+ * <code>false</code> otherwise. The value of this property depends
+ * on {@link JList#getFirstVisibleIndex()} and
+ * {@link JList#getLastVisibleIndex()}.
+ *
+ * @return <code>true</code> if this list child is visible,
+ * <code>false</code> otherwise
+ */
+ public boolean isVisible()
+ {
+ return listIndex >= parent.getFirstVisibleIndex()
+ && listIndex <= parent.getLastVisibleIndex();
+ }
+
+ /**
+ * The value of the visible property cannot be modified, so this method
+ * does nothing.
+ *
+ * @param b not used here
+ */
+ public void setVisible(boolean b)
+ {
+ // The value of the visible property cannot be modified, so this method
+ // does nothing.
+ }
+
+ /**
+ * Returns <code>true</code> if this list child is currently showing on
+ * screen and <code>false</code> otherwise. The list child is showing if
+ * it is visible and if it's parent JList is currently showing.
+ *
+ * @return <code>true</code> if this list child is currently showing on
+ * screen and <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ return isVisible() && parent.isShowing();
+ }
+
+ /**
+ * Returns <code>true</code> if this list child covers the screen location
+ * <code>point</code> (relative to the <code>JList</code> coordinate
+ * system, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if this list child covers the screen location
+ * <code>point</code> , <code>false</code> otherwise
+ */
+ public boolean contains(Point point)
+ {
+ return getBounds().contains(point);
+ }
+
+ /**
+ * Returns the absolute screen location of this list child.
+ *
+ * @return the absolute screen location of this list child
+ */
+ public Point getLocationOnScreen()
+ {
+ Point loc = getLocation();
+ SwingUtilities.convertPointToScreen(loc, parent);
+ return loc;
+ }
+
+ /**
+ * Returns the screen location of this list child relative to it's parent.
+ *
+ * @return the location of this list child relative to it's parent
+ *
+ * @see JList#indexToLocation(int)
+ */
+ public Point getLocation()
+ {
+ return parent.indexToLocation(listIndex);
+ }
+
+ /**
+ * Does nothing since the screen location cannot be set on list children
+ * explictitly.
+ *
+ * @param point not used here
+ */
+ public void setLocation(Point point)
+ {
+ // Does nothing since the screen location cannot be set on list children
+ // explictitly.
+ }
+
+ /**
+ * Returns the bounds of this list child.
+ *
+ * @return the bounds of this list child
+ *
+ * @see JList#getCellBounds(int, int)
+ */
+ public Rectangle getBounds()
+ {
+ return parent.getCellBounds(listIndex, listIndex);
+ }
+
+ /**
+ * Does nothing since the bounds cannot be set on list children
+ * individually.
+ *
+ * @param rectangle not used here
+ */
+ public void setBounds(Rectangle rectangle)
+ {
+ // Does nothing since the bounds cannot be set on list children
+ // individually.
+ }
+
+ /**
+ * Returns the size of this list child.
+ *
+ * @return the size of this list child
+ */
+ public Dimension getSize()
+ {
+ Rectangle b = getBounds();
+ return b.getSize();
+ }
+
+ /**
+ * Does nothing since the size cannot be set on list children
+ * individually.
+ *
+ * @param dimension not used here
+ */
+ public void setSize(Dimension dimension)
+ {
+ // Does nothing since the size cannot be set on list children
+ // individually.
+ }
+
+ /**
+ * Returns <code>null</code> because list children do not have children
+ * themselves
+ *
+ * @return <code>null</code>
+ */
+ public Accessible getAccessibleAt(Point point)
+ {
+ return null;
+ }
+
+ /**
+ * Returns <code>true</code> since list children are focus traversable.
+ *
+ * @return true
+ */
+ public boolean isFocusTraversable()
+ {
+ // TODO: Is this 100% ok?
+ return true;
+ }
+
+ /**
+ * Requests focus on the parent list. List children cannot request focus
+ * individually.
+ */
+ public void requestFocus()
+ {
+ // TODO: Is this 100% ok?
+ parent.requestFocus();
+ }
+
+ /**
+ * Adds a focus listener to the parent list. List children do not have
+ * their own focus management.
+ *
+ * @param listener the focus listener to add
+ */
+ public void addFocusListener(FocusListener listener)
+ {
+ // TODO: Is this 100% ok?
+ parent.addFocusListener(listener);
+ }
+
+ /**
+ * Removes a focus listener from the parent list. List children do not
+ * have their own focus management.
+ *
+ * @param listener the focus listener to remove
+ */
+ public void removeFocusListener(FocusListener listener)
+ {
+ // TODO: Is this 100%
+ parent.removeFocusListener(listener);
+ }
+
+ /**
+ * Returns the accessible role of this list item, which is
+ * {@link AccessibleRole#LABEL}.
+ *
+ * @return {@link AccessibleRole#LABEL}
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.LABEL;
+ }
+
+ /**
+ * Returns the accessible state set of this list item.
+ *
+ * @return the accessible state set of this list item
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet states = new AccessibleStateSet();
+ if (isVisible())
+ states.add(AccessibleState.VISIBLE);
+ if (isShowing())
+ states.add(AccessibleState.SHOWING);
+ if (isFocusTraversable())
+ states.add(AccessibleState.FOCUSABLE);
+ // TODO: How should the active state be handled? The API docs
+ // suggest that this state is set on the activated list child,
+ // that is the one that is drawn with a box. However, I don't know how
+ // to implement this.
+
+ // TODO: We set the selectable state here because list children are
+ // selectable. Is there a way to disable single children?
+ if (parent.isEnabled())
+ states.add(AccessibleState.SELECTABLE);
+
+ if (parent.isSelectedIndex(listIndex))
+ states.add(AccessibleState.SELECTED);
+
+ // TODO: Handle more states here?
+ return states;
+ }
+
+ /**
+ * Returns the index of this list child within it's parent list.
+ *
+ * @return the index of this list child within it's parent list
+ */
+ public int getAccessibleIndexInParent()
+ {
+ return listIndex;
+ }
+
+ /**
+ * Returns <code>0</code> since list children don't have children
+ * themselves.
+ *
+ * @return <code>0</code>
+ */
+ public int getAccessibleChildrenCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns <code>null</code> since list children don't have children
+ * themselves.
+ *
+ * @return <code>null</code>
+ */
+ public Accessible getAccessibleChild(int i)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the locale of this component. This call is forwarded to the
+ * parent list since list children don't have a separate locale setting.
+ *
+ * @return the locale of this component
+ */
+ public Locale getLocale()
+ {
+ return parent.getLocale();
+ }
+
+ /**
+ * This method does
+ * nothing, list children are transient accessible objects which means
+ * that they don't fire property change events.
+ *
+ * @param l not used here
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * This method does
+ * nothing, list children are transient accessible objects which means
+ * that they don't fire property change events.
+ *
+ * @param l not used here
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ // Do nothing here.
+ }
+
+ // TODO: Implement the remaining methods of this class.
+ }
+
+ /**
+ * Create a new AccessibleJList.
+ */
+ public AccessibleJList()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the number of selected accessible children.
+ *
+ * @return the number of selected accessible children
+ */
+ public int getAccessibleSelectionCount()
+ {
+ return getSelectedIndices().length;
+ }
+
+ /**
+ * Returns the n-th selected accessible child.
+ *
+ * @param n the index of the selected child to return
+ *
+ * @return the n-th selected accessible child
+ */
+ public Accessible getAccessibleSelection(int n)
+ {
+ return new AccessibleJListChild(JList.this, getSelectedIndices()[n]);
+ }
+
+ /**
+ * Returns <code>true</code> if the n-th child is selected,
+ * <code>false</code> otherwise.
+ *
+ * @param n the index of the child of which the selected state is queried
+ *
+ * @return <code>true</code> if the n-th child is selected,
+ * <code>false</code> otherwise
+ */
+ public boolean isAccessibleChildSelected(int n)
+ {
+ return isSelectedIndex(n);
+ }
+
+ /**
+ * Adds the accessible item with the specified index to the selected items.
+ * If multiple selections are supported, the item is added to the selection,
+ * otherwise the item replaces the current selection.
+ *
+ * @param i the index of the item to add to the selection
+ */
+ public void addAccessibleSelection(int i)
+ {
+ addSelectionInterval(i, i);
+ }
+
+ /**
+ * Removes the accessible item with the specified index to the selection.
+ *
+ * @param i the index of the item to be removed from the selection
+ */
+ public void removeAccessibleSelection(int i)
+ {
+ removeSelectionInterval(i, i);
+ }
+
+ /**
+ * Remove all selection items from the selection.
+ */
+ public void clearAccessibleSelection()
+ {
+ clearSelection();
+ }
+
+ /**
+ * Selects all items if multiple selections are supported.
+ * Otherwise do nothing.
+ */
+ public void selectAllAccessibleSelection()
+ {
+ addSelectionInterval(0, getModel().getSize());
+ }
+
+ /**
+ * Receices notification when the list selection is changed. This method
+ * fires two property change events, the first with
+ * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY} and the second
+ * with {@link AccessibleContext#ACCESSIBLE_SELECTION_PROPERTY}.
+ *
+ * @param event the list selection event
+ */
+ public void valueChanged(ListSelectionEvent event)
+ {
+ firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
+ Boolean.TRUE);
+ firePropertyChange(ACCESSIBLE_SELECTION_PROPERTY, Boolean.FALSE,
+ Boolean.TRUE);
+ }
+
+ /**
+ * Receives notification when items have changed in the
+ * <code>JList</code>. This method fires a property change event with
+ * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY}.
+ *
+ * @param event the list data event
+ */
+ public void contentsChanged(ListDataEvent event)
+ {
+ firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
+ Boolean.TRUE);
+ }
+
+ /**
+ * Receives notification when items are inserted into the
+ * <code>JList</code>. This method fires a property change event with
+ * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY}.
+ *
+ * @param event the list data event
+ */
+ public void intervalAdded(ListDataEvent event)
+ {
+ firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
+ Boolean.TRUE);
+ }
+
+ /**
+ * Receives notification when items are removed from the
+ * <code>JList</code>. This method fires a property change event with
+ * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY}.
+ *
+ * @param event the list data event
+ */
+ public void intervalRemoved(ListDataEvent event)
+ {
+ firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
+ Boolean.TRUE);
+ }
+
+
+ /**
+ * Receives notification about changes of the <code>JList</code>'s
+ * properties. This is used to re-register this object as listener to
+ * the data model and selection model when the data model or selection model
+ * changes.
+ *
+ * @param e the property change event
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ String propertyName = e.getPropertyName();
+ if (propertyName.equals("model"))
+ {
+ ListModel oldModel = (ListModel) e.getOldValue();
+ oldModel.removeListDataListener(this);
+ ListModel newModel = (ListModel) e.getNewValue();
+ newModel.addListDataListener(this);
+ }
+ else if (propertyName.equals("selectionModel"))
+ {
+ ListSelectionModel oldModel = (ListSelectionModel) e.getOldValue();
+ oldModel.removeListSelectionListener(this);
+ ListSelectionModel newModel = (ListSelectionModel) e.getNewValue();
+ oldModel.addListSelectionListener(this);
+ }
+ }
+
+ /**
+ * Return the state set of the <code>JList</code>.
+ *
+ * @return the state set of the <code>JList</code>
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ // TODO: Figure out if there is possibly more state that must be
+ // handled here.
+ AccessibleStateSet s = super.getAccessibleStateSet();
+ if (getSelectionMode() != ListSelectionModel.SINGLE_SELECTION)
+ s.add(AccessibleState.MULTISELECTABLE);
+ return s;
+ }
+
+ /**
+ * Returns the accessible role for <code>JList</code>,
+ * {@link AccessibleRole#LIST}.
+ *
+ * @return the accessible role for <code>JList</code>
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.LIST;
+ }
+
+ /**
+ * Returns the accessible child at the visual location <code>p</code>
+ * (relative to the upper left corner of the <code>JList</code>). If there
+ * is no child at that location, this returns <code>null</code>.
+ *
+ * @param p the screen location for which to return the accessible child
+ *
+ * @return the accessible child at the specified location, or
+ * <code>null</code> if there is no child at that location
+ */
+ public Accessible getAccessibleAt(Point p)
+ {
+ int childIndex = locationToIndex(p);
+ return getAccessibleChild(childIndex);
+ }
+
+ /**
+ * Returns the number of accessible children in the <code>JList</code>.
+ *
+ * @return the number of accessible children in the <code>JList</code>
+ */
+ public int getAccessibleChildrenCount()
+ {
+ return getModel().getSize();
+ }
+
+ /**
+ * Returns the n-th accessible child of this <code>JList</code>. This will
+ * be an instance of {@link AccessibleJListChild}. If there is no child
+ * at that index, <code>null</code> is returned.
+ *
+ * @param n the index of the child to return
+ *
+ * @return the n-th accessible child of this <code>JList</code>
+ */
+ public Accessible getAccessibleChild(int n)
+ {
+ if (getModel().getSize() <= n)
+ return null;
+ return new AccessibleJListChild(JList.this, n);
+ }
+ }
+
private static final long serialVersionUID = 4406629526391098046L;
/**
@@ -181,7 +923,7 @@ public class JList extends JComponent implements Accessible, Scrollable
/**
* This property specifies a foreground color for the selected cells in
- * the list. When {@link ListCellRenderer.getListCellRendererComponent}
+ * the list. When {@link ListCellRenderer#getListCellRendererComponent}
* is called with a selected cell object, the component returned will
* have its "foreground" set to this color.
*/
@@ -189,7 +931,7 @@ public class JList extends JComponent implements Accessible, Scrollable
/**
* This property specifies a background color for the selected cells in
- * the list. When {@link ListCellRenderer.getListCellRendererComponent}
+ * the list. When {@link ListCellRenderer#getListCellRendererComponent}
* is called with a selected cell object, the component returned will
* have its "background" property set to this color.
*/
@@ -216,9 +958,9 @@ public class JList extends JComponent implements Accessible, Scrollable
/**
* This property indicates a <em>preference</em> for the number of rows
* displayed in the list, and will scale the
- * {@link #preferredScrollableViewportSize} property accordingly. The actual
+ * {@link #getPreferredScrollableViewportSize} property accordingly. The actual
* number of displayed rows, when the list is placed in a real {@link
- * Viewport} or other component, may be greater or less than this number.
+ * JViewport} or other component, may be greater or less than this number.
*/
int visibleRowCount;
@@ -270,7 +1012,7 @@ public class JList extends JComponent implements Accessible, Scrollable
event.getValueIsAdjusting());
JList.this.repaint();
}
- };
+ }
/**
* Shared ListListener instance, subscribed to both the current {@link
@@ -437,7 +1179,7 @@ public class JList extends JComponent implements Accessible, Scrollable
/**
* Sets the value of the {@link #visibleRowCount} property.
*
- * @param visibleRowCount The new property value
+ * @param vc The new property value
*/
public void setVisibleRowCount(int vc)
{
@@ -563,8 +1305,8 @@ public class JList extends JComponent implements Accessible, Scrollable
/**
* Returns the list index of the upper left or upper right corner of the
- * {@link #visibleRect} property, depending on the {@link
- * #componentOrientation} property.
+ * visible rectangle of this list, depending on the {@link
+ * Component#getComponentOrientation} property.
*
* @return The index of the first visible list cell, or <code>-1</code>
* if none is visible.
@@ -585,7 +1327,8 @@ public class JList extends JComponent implements Accessible, Scrollable
*
* @return index of the cell to which specified location is closest to.
*/
- public int locationToIndex(Point location) {
+ public int locationToIndex(Point location)
+ {
return getUI().locationToIndex(this, location);
}
@@ -595,14 +1338,15 @@ public class JList extends JComponent implements Accessible, Scrollable
*
* @return location of the cell located at the specified index in the list.
*/
- public Point indexToLocation(int index){
- return getCellBounds(index, index).getLocation();
+ public Point indexToLocation(int index)
+ {
+ return getUI().indexToLocation(this, index);
}
/**
* Returns the list index of the lower right or lower left corner of the
- * {@link #visibleRect} property, depending on the {@link
- * #componentOrientation} property.
+ * visible rectangle of this list, depending on the {@link
+ * Component#getComponentOrientation} property.
*
* @return The index of the last visible list cell, or <code>-1</code>
* if none is visible.
@@ -625,7 +1369,7 @@ public class JList extends JComponent implements Accessible, Scrollable
* selected.
*
* @return An array of model indices, each of which is selected according
- * to the {@link #selection} property
+ * to the {@link #getSelectedValues} property
*/
public int[] getSelectedIndices()
{
@@ -640,7 +1384,7 @@ public class JList extends JComponent implements Accessible, Scrollable
n++;
int [] v = new int[n];
j = 0;
- for (i = lo; i < hi; ++i)
+ for (i = lo; i <= hi; ++i)
if (selectionModel.isSelectedIndex(i))
v[j++] = i;
return v;
@@ -670,7 +1414,7 @@ public class JList extends JComponent implements Accessible, Scrollable
* @return The first selected element, or <code>null</code> if no element
* is selected.
*
- * @see getSelectedValues
+ * @see #getSelectedValues
*/
public Object getSelectedValue()
{
@@ -686,7 +1430,7 @@ public class JList extends JComponent implements Accessible, Scrollable
*
* @return An array containing all the selected values
*
- * @see getSelectedValue
+ * @see #setSelectedValue
*/
public Object[] getSelectedValues()
{
@@ -845,7 +1589,7 @@ public class JList extends JComponent implements Accessible, Scrollable
}
/**
- * Sets the value of the {@link #celLRenderer} property.
+ * Sets the value of the {@link #getCellRenderer} property.
*
* @param renderer The new property value
*/
@@ -876,10 +1620,15 @@ public class JList extends JComponent implements Accessible, Scrollable
* #listListener} is unsubscribed from the existing model, if it exists,
* and re-subscribed to the new model.
*
- * @param model The new property value
+ * @param model the new model (<code>null</code> not permitted).
+ *
+ * @throws IllegalArgumentException if <code>model</code> is
+ * <code>null</code>.
*/
public void setModel(ListModel model)
{
+ if (model == null)
+ throw new IllegalArgumentException("Null 'model' argument.");
if (this.model == model)
return;
@@ -1019,14 +1768,14 @@ public class JList extends JComponent implements Accessible, Scrollable
public AccessibleContext getAccessibleContext()
{
- return null;
+ return new AccessibleJList();
}
/**
* Returns a size indicating how much space this list would like to
* consume, when contained in a scrollable viewport. This is part of the
* {@link Scrollable} interface, which interacts with {@link
- * ScrollPaneLayout} and {@link Viewport} to define scrollable objects.
+ * ScrollPaneLayout} and {@link JViewport} to define scrollable objects.
*
* @return The preferred size
*/
@@ -1036,36 +1785,43 @@ public class JList extends JComponent implements Accessible, Scrollable
//return the value from getPreferredSize. The current ListUI is
//expected to override getPreferredSize to return an appropriate value.
if (getLayoutOrientation() != VERTICAL)
- return getPreferredSize();
+ return getPreferredSize();
+
+ int size = getModel().getSize();
+ // Trivial case: if fixedCellWidth and fixedCellHeight were set
+ // just use them
if (fixedCellHeight != -1 && fixedCellWidth != -1)
- return new Dimension(fixedCellWidth, getModel().getSize() *
- fixedCellHeight);
+ return new Dimension(fixedCellWidth, size * fixedCellHeight);
+
+ // If the model is empty we use 16 * the number of visible rows
+ // for the height and either fixedCellWidth (if set) or 256
+ // for the width
+ if (size == 0)
+ {
+ if (fixedCellWidth == -1)
+ return new Dimension(256, 16 * getVisibleRowCount());
+ else
+ return new Dimension(fixedCellWidth, 16 * getVisibleRowCount());
+ }
- int prefWidth, prefHeight;
+ // Calculate the width: if fixedCellWidth was set use that, otherwise
+ // use the preferredWidth
+ int prefWidth;
if (fixedCellWidth != -1)
prefWidth = fixedCellWidth;
else
- {
- prefWidth = 0;
- int size = getModel().getSize();
- for (int i = 0; i < size; i++)
- if (getCellBounds(i, i).width > prefWidth)
- prefWidth = getCellBounds(i, i).width;
- }
-
- if (getModel().getSize() == 0 && fixedCellWidth == -1)
- return new Dimension(256, 16 * getVisibleRowCount());
- else if (getModel().getSize() == 0)
- return new Dimension (fixedCellWidth, 16 * getVisibleRowCount());
-
+ prefWidth = getPreferredSize().width;
+
+ // Calculate the height: if fixedCellHeight was set use that, otherwise
+ // use the height of the first row multiplied by the number of visible
+ // rows
+ int prefHeight;
if (fixedCellHeight != -1)
prefHeight = fixedCellHeight;
else
- {
- prefHeight = getVisibleRowCount() * getCellBounds
- (getFirstVisibleIndex(), getFirstVisibleIndex()).height;
- }
+ prefHeight = getVisibleRowCount() * getCellBounds(0, 0).height;
+
return new Dimension (prefWidth, prefHeight);
}
@@ -1196,7 +1952,7 @@ public class JList extends JComponent implements Accessible, Scrollable
}
/**
- * Gets the value of the {@link #scrollableTracksViewportWidth} property.
+ * Gets the value of the <code>scrollableTracksViewportWidth</code> property.
*
* @return <code>true</code> if the viewport is larger (horizontally)
* than the list and the list should be expanded to fit the viewport;
@@ -1221,7 +1977,7 @@ public class JList extends JComponent implements Accessible, Scrollable
}
/**
- * Gets the value of the {@link #scrollableTracksViewportWidth} property.
+ * Gets the value of the </code>scrollableTracksViewportWidth</code> property.
*
* @return <code>true</code> if the viewport is larger (vertically)
* than the list and the list should be expanded to fit the viewport;
@@ -1373,7 +2129,7 @@ public class JList extends JComponent implements Accessible, Scrollable
*/
public Rectangle getCellBounds(int index0, int index1)
{
- return ((ListUI) ui).getCellBounds(this, index0, index1);
+ return getUI().getCellBounds(this, index0, index1);
}
/**
@@ -1383,8 +2139,8 @@ public class JList extends JComponent implements Accessible, Scrollable
*
* @param prefix the prefix to search for in the cell values
* @param startIndex the index where to start searching from
- * @param bias the search direction, either {@link Position.Bias.Forward}
- * or {@link Position.Bias.Backward}
+ * @param bias the search direction, either {@link Position.Bias#Forward}
+ * or {@link Position.Bias#Backward}
*
* @return the index of the found element or -1 if no such element has
* been found
diff --git a/libjava/classpath/javax/swing/JMenu.java b/libjava/classpath/javax/swing/JMenu.java
index 8dcad8b77cd..9734eb8732f 100644
--- a/libjava/classpath/javax/swing/JMenu.java
+++ b/libjava/classpath/javax/swing/JMenu.java
@@ -45,8 +45,6 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.EventListener;
@@ -137,10 +135,6 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
this(text);
}
- private void writeObject(ObjectOutputStream stream) throws IOException
- {
- }
-
/**
* Adds specified menu item to this menu
*
@@ -768,6 +762,7 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
*/
protected void processKeyEvent(KeyEvent event)
{
+ // TODO: Implement this properly.
}
/**
@@ -812,6 +807,7 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
return accessibleContext;
}
+ // FIXME: This inner class is a complete stub and needs to be implemented.
protected class AccessibleJMenu extends AccessibleJMenuItem
implements AccessibleSelection
{
@@ -819,6 +815,7 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
protected AccessibleJMenu()
{
+ // Nothing to do here.
}
public int getAccessibleChildrenCount()
@@ -858,32 +855,48 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
public void addAccessibleSelection(int value0)
{
+ // TODO: Implement this properly.
}
public void removeAccessibleSelection(int value0)
{
+ // TODO: Implement this properly.
}
public void clearAccessibleSelection()
{
+ // TODO: Implement this properly.
}
public void selectAllAccessibleSelection()
{
+ // TODO: Implement this properly.
}
}
protected class WinListener extends WindowAdapter implements Serializable
{
- JPopupMenu popupMenu;
private static final long serialVersionUID = -6415815570638474823L;
+ /**
+ * Creates a new <code>WinListener</code>.
+ *
+ * @param popup the popup menu which is observed
+ */
public WinListener(JPopupMenu popup)
{
+ // TODO: What should we do with the popup argument?
}
+ /**
+ * Receives notification when the popup menu is closing and deselects
+ * the menu.
+ *
+ * @param event the window event
+ */
public void windowClosing(WindowEvent event)
{
+ setSelected(false);
}
}
diff --git a/libjava/classpath/javax/swing/JMenuBar.java b/libjava/classpath/javax/swing/JMenuBar.java
index eebb1a050be..f018daabf80 100644
--- a/libjava/classpath/javax/swing/JMenuBar.java
+++ b/libjava/classpath/javax/swing/JMenuBar.java
@@ -46,6 +46,9 @@ 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.swing.plaf.MenuBarUI;
/**
@@ -59,6 +62,137 @@ import javax.swing.plaf.MenuBarUI;
*/
public class JMenuBar extends JComponent implements Accessible, MenuElement
{
+ /**
+ * Provides accessibility support for <code>JMenuBar</code>.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ protected class AccessibleJMenuBar extends AccessibleJComponent
+ implements AccessibleSelection
+ {
+
+ /**
+ * Returns the number of selected items in the menu bar. Possible values
+ * are <code>0</code> if nothing is selected, or <code>1</code> if one
+ * item is selected.
+ *
+ * @return the number of selected items in the menu bar
+ */
+ public int getAccessibleSelectionCount()
+ {
+ int count = 0;
+ if (getSelectionModel().getSelectedIndex() != -1)
+ count = 1;
+ return count;
+ }
+
+ /**
+ * Returns the selected with index <code>i</code> menu, or
+ * <code>null</code> if the specified menu is not selected.
+ *
+ * @param i the index of the menu to return
+ *
+ * @return the selected with index <code>i</code> menu, or
+ * <code>null</code> if the specified menu is not selected
+ */
+ public Accessible getAccessibleSelection(int i)
+ {
+ if (getSelectionModel().getSelectedIndex() != i)
+ return null;
+ return getMenu(i);
+ }
+
+ /**
+ * Returns <code>true</code> if the specified menu is selected,
+ * <code>false</code> otherwise.
+ *
+ * @param i the index of the menu to check
+ *
+ *@return <code>true</code> if the specified menu is selected,
+ * <code>false</code> otherwise
+ */
+ public boolean isAccessibleChildSelected(int i)
+ {
+ return getSelectionModel().getSelectedIndex() == i;
+ }
+
+ /**
+ * Selects the menu with index <code>i</code>. If another menu is already
+ * selected, this will be deselected.
+ *
+ * @param i the menu to be selected
+ */
+ public void addAccessibleSelection(int i)
+ {
+ getSelectionModel().setSelectedIndex(i);
+ }
+
+ /**
+ * Deselects the menu with index <code>i</code>.
+ *
+ * @param i the menu index to be deselected
+ */
+ public void removeAccessibleSelection(int i)
+ {
+ if (getSelectionModel().getSelectedIndex() == i)
+ getSelectionModel().clearSelection();
+ }
+
+ /**
+ * Deselects all possibly selected menus.
+ */
+ public void clearAccessibleSelection()
+ {
+ getSelectionModel().clearSelection();
+ }
+
+ /**
+ * In menu bars it is not possible to select all items, so this method
+ * does nothing.
+ */
+ public void selectAllAccessibleSelection()
+ {
+ // In menu bars it is not possible to select all items, so this method
+ // does nothing.
+ }
+
+ /**
+ * Returns the accessible role of <code>JMenuBar</code>, which is
+ * {@link AccessibleRole#MENU_BAR}.
+ *
+ * @return the accessible role of <code>JMenuBar</code>, which is
+ * {@link AccessibleRole#MENU_BAR}
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.MENU_BAR;
+ }
+
+ /**
+ * Returns the <code>AccessibleSelection</code> for this object. This
+ * method returns <code>this</code>, since the
+ * <code>AccessibleJMenuBar</code> manages its selection itself.
+ *
+ * @return the <code>AccessibleSelection</code> for this object
+ */
+ public AccessibleSelection getAccessibleSelection()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the state of this <code>AccessibleJMenuBar</code>.
+ *
+ * @return the state of this <code>AccessibleJMenuBar</code>.
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet stateSet = super.getAccessibleStateSet();
+ // TODO: Figure out what state must be added to the super state set.
+ return stateSet;
+ }
+ }
+
private static final long serialVersionUID = -8191026883931977036L;
/** JMenuBar's model. It keeps track of selected menu's index */
@@ -100,13 +234,15 @@ public class JMenuBar extends JComponent implements Accessible, MenuElement
*/
public void addNotify()
{
- // FIXME: Should register this menu bar with the keyboard manager
super.addNotify();
+ KeyboardManager.getManager().registerJMenuBar(this);
}
public AccessibleContext getAccessibleContext()
{
- return null;
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJMenuBar();
+ return accessibleContext;
}
/**
@@ -253,7 +389,7 @@ public class JMenuBar extends JComponent implements Accessible, MenuElement
* This method returns a name to identify which look and feel class will be
* the UI delegate for the menu bar.
*
- * @return The Look and Feel classID. "MenuItemUI"
+ * @return The Look and Feel classID. "MenuBarUI"
*/
public String getUIClassID()
{
@@ -338,6 +474,63 @@ public class JMenuBar extends JComponent implements Accessible, MenuElement
}
/**
+ * This method overrides JComponent.processKeyBinding to allow the
+ * JMenuBar to check all the child components (recursiveley) to see
+ * if they'll consume the event.
+ *
+ * @param ks the KeyStroke for the event
+ * @param e the KeyEvent for the event
+ * @param condition the focus condition for the binding
+ * @param pressed true if the key is pressed
+ */
+ protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition,
+ boolean pressed)
+ {
+ // See if the regular JComponent behavior consumes the event
+ if (super.processKeyBinding(ks, e, condition, pressed))
+ return true;
+
+ // If not, have to recursively check all the child menu elements to see
+ // if they want it
+ MenuElement[] children = getSubElements();
+ for (int i = 0; i < children.length; i++)
+ if (processKeyBindingHelper(children[i], ks, e, condition, pressed))
+ return true;
+ return false;
+ }
+
+ /**
+ * This is a helper method to recursively check the children of this
+ * JMenuBar to see if they will consume a key event via key bindings.
+ * This is used for menu accelerators.
+ * @param menuElement the menuElement to check (and check all its children)
+ * @param ks the KeyStroke for the event
+ * @param e the KeyEvent that may be consumed
+ * @param condition the focus condition for the binding
+ * @param pressed true if the key was pressed
+ * @return true <code>menuElement</code> or one of its children consume
+ * the event (processKeyBinding returns true for menuElement or one of
+ * its children).
+ */
+ static boolean processKeyBindingHelper(MenuElement menuElement, KeyStroke ks,
+ KeyEvent e, int condition,
+ boolean pressed)
+ {
+ // First check the menuElement itself, if it's a JComponent
+ if (menuElement instanceof JComponent
+ && ((JComponent) menuElement).processKeyBinding(ks, e, condition,
+ pressed))
+ return true;
+
+ // If that didn't consume it, check all the children recursively
+ MenuElement[] children = menuElement.getSubElements();
+ for (int i = 0; i < children.length; i++)
+ if (processKeyBindingHelper(children[i], ks, e, condition, pressed))
+ return true;
+ return false;
+ }
+
+ /**
* Process mouse events forwarded from MenuSelectionManager. This method
* doesn't do anything. It is here to conform to the MenuElement interface.
*
@@ -358,7 +551,7 @@ public class JMenuBar extends JComponent implements Accessible, MenuElement
*/
public void removeNotify()
{
- // Must unregister this menu bar with the current keyboard manager.
+ KeyboardManager.getManager().unregisterJMenuBar(this);
super.removeNotify();
}
@@ -384,9 +577,14 @@ public class JMenuBar extends JComponent implements Accessible, MenuElement
* Sets help menu for this menu bar
*
* @param menu help menu
+ *
+ * @specnote The specification states that this method is not yet implemented
+ * and should throw an exception.
*/
public void setHelpMenu(JMenu menu)
{
+ // We throw an Error here, just as Sun's JDK does.
+ throw new Error("setHelpMenu() not yet implemented.");
}
/**
diff --git a/libjava/classpath/javax/swing/JMenuItem.java b/libjava/classpath/javax/swing/JMenuItem.java
index 069b7bc86f8..c87a4dc2b20 100644
--- a/libjava/classpath/javax/swing/JMenuItem.java
+++ b/libjava/classpath/javax/swing/JMenuItem.java
@@ -44,9 +44,6 @@ 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;
@@ -84,6 +81,7 @@ public class JMenuItem extends AbstractButton implements Accessible,
public JMenuItem()
{
super();
+ init(null, null);
}
/**
@@ -118,6 +116,7 @@ public class JMenuItem extends AbstractButton implements Accessible,
{
super();
super.setAction(action);
+ init(null, null);
}
/**
@@ -147,15 +146,6 @@ public class JMenuItem extends AbstractButton implements Accessible,
setMnemonic(mnemonic);
}
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException
- {
- }
-
- private void writeObject(ObjectOutputStream stream) throws IOException
- {
- }
-
/**
* Initializes this menu item
*
@@ -176,7 +166,7 @@ public class JMenuItem extends AbstractButton implements Accessible,
//borderPainted = false;
focusPainted = false;
horizontalAlignment = JButton.LEFT;
- horizontalTextPosition = JButton.LEFT;
+ horizontalTextPosition = JButton.TRAILING;
}
/**
@@ -189,7 +179,7 @@ public class JMenuItem extends AbstractButton implements Accessible,
{
super.setUI(ui);
}
-
+
/**
* This method sets this menuItem's UI to the UIManager's default for the
* current look and feel.
@@ -255,13 +245,18 @@ public class JMenuItem extends AbstractButton implements Accessible,
}
/**
- * Sets accelerator for this menu item.
- *
+ * Sets the key combination which invokes the menu item's action
+ * listeners without navigating the menu hierarchy. Note that when the
+ * keyboard accelerator is typed, it will work whether or not the
+ * menu is currently displayed.
+ *
* @param keystroke accelerator for this menu item.
*/
public void setAccelerator(KeyStroke keystroke)
{
+ KeyStroke old = this.accelerator;
this.accelerator = keystroke;
+ firePropertyChange ("accelerator", old, keystroke);
}
/**
@@ -276,7 +271,11 @@ public class JMenuItem extends AbstractButton implements Accessible,
super.configurePropertiesFromAction(action);
if (! (this instanceof JMenu) && action != null)
- setAccelerator((KeyStroke) (action.getValue(Action.ACCELERATOR_KEY)));
+ {
+ setAccelerator((KeyStroke) (action.getValue(Action.ACCELERATOR_KEY)));
+ super.registerKeyboardAction(action, accelerator,
+ JComponent.WHEN_IN_FOCUSED_WINDOW);
+ }
}
/**
@@ -667,6 +666,7 @@ public class JMenuItem extends AbstractButton implements Accessible,
public void stateChanged(ChangeEvent event)
{
+ // TODO: What should be done here, if anything?
}
public AccessibleRole getAccessibleRole()
diff --git a/libjava/classpath/javax/swing/JOptionPane.java b/libjava/classpath/javax/swing/JOptionPane.java
index ad0772ab8d3..057326cd209 100644
--- a/libjava/classpath/javax/swing/JOptionPane.java
+++ b/libjava/classpath/javax/swing/JOptionPane.java
@@ -1,5 +1,5 @@
/* JOptionPane.java
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,7 +39,6 @@ exception statement from your version. */
package javax.swing;
import java.awt.Component;
-import java.awt.Dimension;
import java.awt.Frame;
import javax.accessibility.Accessible;
@@ -60,16 +59,19 @@ public class JOptionPane extends JComponent implements Accessible
/**
* DOCUMENT ME!
*/
+ // FIXME: This inner class is a complete stub and needs to be implemented
+ // properly.
protected class AccessibleJOptionPane extends JComponent.AccessibleJComponent
{
/** DOCUMENT ME! */
private static final long serialVersionUID = 686071432213084821L;
-
+
/**
* Creates a new AccessibleJOptionPane object.
*/
protected AccessibleJOptionPane()
{
+ // Nothing to do here.
}
/**
@@ -343,8 +345,6 @@ public class JOptionPane extends JComponent implements Accessible
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
updateUI();
- invalidate();
- repaint();
}
/**
@@ -369,17 +369,12 @@ public class JOptionPane extends JComponent implements Accessible
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);
- dialog.invalidate();
- dialog.repaint();
-
+ dialog.pack();
+ dialog.setLocationRelativeTo(parentComponent);
+
return dialog;
}
@@ -513,6 +508,8 @@ public class JOptionPane extends JComponent implements Accessible
*/
public Object getInputValue()
{
+ if (getValue().equals(new Integer(CANCEL_OPTION)))
+ setInputValue(null);
return inputValue;
}
@@ -858,13 +855,13 @@ public class JOptionPane extends JComponent implements Accessible
*/
public static int showConfirmDialog(Component parentComponent, Object message)
{
- JOptionPane pane = new JOptionPane(message);
+ JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE);
JDialog dialog = pane.createDialog(parentComponent, "Select an Option");
-
- dialog.pack();
dialog.show();
-
- return ((Integer) pane.getValue()).intValue();
+
+ if (pane.getValue() instanceof Integer)
+ return ((Integer) pane.getValue()).intValue();
+ return -1;
}
/**
@@ -886,10 +883,11 @@ public class JOptionPane extends JComponent implements Accessible
{
JOptionPane pane = new JOptionPane(message, PLAIN_MESSAGE, optionType);
JDialog dialog = pane.createDialog(parentComponent, title);
- dialog.pack();
dialog.show();
- return ((Integer) pane.getValue()).intValue();
+ if (pane.getValue() instanceof Integer)
+ return ((Integer) pane.getValue()).intValue();
+ return -1;
}
/**
@@ -912,10 +910,11 @@ public class JOptionPane extends JComponent implements Accessible
{
JOptionPane pane = new JOptionPane(message, messageType, optionType);
JDialog dialog = pane.createDialog(parentComponent, title);
- dialog.pack();
dialog.show();
- return ((Integer) pane.getValue()).intValue();
+ if (pane.getValue() instanceof Integer)
+ return ((Integer) pane.getValue()).intValue();
+ return -1;
}
/**
@@ -940,10 +939,11 @@ public class JOptionPane extends JComponent implements Accessible
{
JOptionPane pane = new JOptionPane(message, messageType, optionType, icon);
JDialog dialog = pane.createDialog(parentComponent, title);
- dialog.pack();
dialog.show();
- return ((Integer) pane.getValue()).intValue();
+ if (pane.getValue() instanceof Integer)
+ return ((Integer) pane.getValue()).intValue();
+ return -1;
}
/**
@@ -964,9 +964,8 @@ public class JOptionPane extends JComponent implements Accessible
JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE);
pane.setWantsInput(true);
JDialog dialog = pane.createDialog(parentComponent, null);
- dialog.pack();
dialog.show();
-
+
return (String) pane.getInputValue();
}
@@ -991,9 +990,8 @@ public class JOptionPane extends JComponent implements Accessible
pane.setInitialSelectionValue(initialSelectionValue);
pane.setWantsInput(true);
JDialog dialog = pane.createDialog(parentComponent, null);
- dialog.pack();
dialog.show();
-
+
return (String) pane.getInputValue();
}
@@ -1017,9 +1015,8 @@ public class JOptionPane extends JComponent implements Accessible
JOptionPane pane = new JOptionPane(message, messageType);
pane.setWantsInput(true);
JDialog dialog = pane.createDialog(parentComponent, title);
- dialog.pack();
dialog.show();
-
+
return (String) pane.getInputValue();
}
@@ -1050,10 +1047,9 @@ public class JOptionPane extends JComponent implements Accessible
pane.setSelectionValues(selectionValues);
pane.setInitialSelectionValue(initialSelectionValue);
JDialog dialog = pane.createDialog(parentComponent, title);
- dialog.pack();
dialog.show();
-
- return (String) pane.getInputValue();
+
+ return pane.getInputValue();
}
/**
@@ -1071,9 +1067,8 @@ public class JOptionPane extends JComponent implements Accessible
JOptionPane pane = new JOptionPane(message, QUESTION_MESSAGE);
pane.setWantsInput(true);
JDialog dialog = pane.createDialog(null, null);
- dialog.pack();
dialog.show();
-
+
return (String) pane.getInputValue();
}
@@ -1096,9 +1091,8 @@ public class JOptionPane extends JComponent implements Accessible
pane.setWantsInput(true);
pane.setInitialSelectionValue(initialSelectionValue);
JDialog dialog = pane.createDialog(null, null);
- dialog.pack();
dialog.show();
-
+
return (String) pane.getInputValue();
}
@@ -1120,8 +1114,10 @@ public class JOptionPane extends JComponent implements Accessible
JInternalFrame frame = pane.createInternalFrame(parentComponent, null);
startModal(frame);
-
- return ((Integer) pane.getValue()).intValue();
+
+ if (pane.getValue() instanceof Integer)
+ return ((Integer) pane.getValue()).intValue();
+ return -1;
}
/**
@@ -1146,7 +1142,9 @@ public class JOptionPane extends JComponent implements Accessible
startModal(frame);
- return ((Integer) pane.getValue()).intValue();
+ if (pane.getValue() instanceof Integer)
+ return ((Integer) pane.getValue()).intValue();
+ return -1;
}
/**
@@ -1172,7 +1170,9 @@ public class JOptionPane extends JComponent implements Accessible
startModal(frame);
- return ((Integer) pane.getValue()).intValue();
+ if (pane.getValue() instanceof Integer)
+ return ((Integer) pane.getValue()).intValue();
+ return -1;
}
/**
@@ -1200,7 +1200,9 @@ public class JOptionPane extends JComponent implements Accessible
startModal(frame);
- return ((Integer) pane.getValue()).intValue();
+ if (pane.getValue() instanceof Integer)
+ return ((Integer) pane.getValue()).intValue();
+ return -1;
}
/**
@@ -1222,7 +1224,7 @@ public class JOptionPane extends JComponent implements Accessible
JInternalFrame frame = pane.createInternalFrame(parentComponent, null);
startModal(frame);
-
+
return (String) pane.getInputValue();
}
@@ -1248,7 +1250,7 @@ public class JOptionPane extends JComponent implements Accessible
JInternalFrame frame = pane.createInternalFrame(parentComponent, title);
startModal(frame);
-
+
return (String) pane.getInputValue();
}
@@ -1283,8 +1285,8 @@ public class JOptionPane extends JComponent implements Accessible
JInternalFrame frame = pane.createInternalFrame(parentComponent, title);
startModal(frame);
-
- return (String) pane.getInputValue();
+
+ return pane.getInputValue();
}
/**
@@ -1376,8 +1378,10 @@ public class JOptionPane extends JComponent implements Accessible
JInternalFrame frame = pane.createInternalFrame(parentComponent, title);
startModal(frame);
-
- return ((Integer) pane.getValue()).intValue();
+
+ if (pane.getValue() instanceof Integer)
+ return ((Integer) pane.getValue()).intValue();
+ return -1;
}
/**
@@ -1391,8 +1395,7 @@ public class JOptionPane extends JComponent implements Accessible
{
JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE);
JDialog dialog = pane.createDialog(parentComponent, null);
- dialog.pack();
- dialog.show();
+ dialog.show();
}
/**
@@ -1410,7 +1413,6 @@ public class JOptionPane extends JComponent implements Accessible
{
JOptionPane pane = new JOptionPane(message, messageType);
JDialog dialog = pane.createDialog(parentComponent, title);
- dialog.pack();
dialog.show();
}
@@ -1431,7 +1433,6 @@ public class JOptionPane extends JComponent implements Accessible
JOptionPane pane = new JOptionPane(message, messageType);
pane.setIcon(icon);
JDialog dialog = pane.createDialog(parentComponent, title);
- dialog.pack();
dialog.show();
}
@@ -1461,10 +1462,11 @@ public class JOptionPane extends JComponent implements Accessible
options, initialValue);
JDialog dialog = pane.createDialog(parentComponent, title);
- dialog.pack();
dialog.show();
- return ((Integer) pane.getValue()).intValue();
+ if (pane.getValue() instanceof Integer)
+ return ((Integer) pane.getValue()).intValue();
+ return -1;
}
/**
@@ -1524,34 +1526,34 @@ public class JOptionPane extends JComponent implements Accessible
* JInternalFrame's preferred size.
*
* @param f The JInternalFrame to make modal.
- * @param pane The JOptionPane to add to the JInternalFrame.
*/
private static void startModal(JInternalFrame f)
{
synchronized (f)
- {
- final JInternalFrame tmp = f;
- tmp.toFront();
-
- f.addInternalFrameListener(new InternalFrameAdapter()
- {
- public void internalFrameClosed(InternalFrameEvent e)
- {
- synchronized (tmp)
- {
- tmp.removeInternalFrameListener(this);
- tmp.notifyAll();
- }
- }
- });
- try
- {
- while (! f.isClosed())
- f.wait();
- }
- catch (InterruptedException ignored)
- {
- }
- }
+ {
+ final JInternalFrame tmp = f;
+ tmp.toFront();
+
+ f.addInternalFrameListener(new InternalFrameAdapter()
+ {
+ public void internalFrameClosed(InternalFrameEvent e)
+ {
+ synchronized (tmp)
+ {
+ tmp.removeInternalFrameListener(this);
+ tmp.notifyAll();
+ }
+ }
+ });
+ try
+ {
+ while (! f.isClosed())
+ f.wait();
+ }
+ catch (InterruptedException ignored)
+ {
+ // Ignore this Exception.
+ }
+ }
}
}
diff --git a/libjava/classpath/javax/swing/JPanel.java b/libjava/classpath/javax/swing/JPanel.java
index c7f7c448331..7805e92b6e9 100644
--- a/libjava/classpath/javax/swing/JPanel.java
+++ b/libjava/classpath/javax/swing/JPanel.java
@@ -43,6 +43,7 @@ import java.awt.LayoutManager;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
import javax.swing.plaf.PanelUI;
/**
@@ -52,63 +53,90 @@ import javax.swing.plaf.PanelUI;
*/
public class JPanel extends JComponent implements Accessible
{
- public JPanel()
+ /**
+ * Provides accessibility support for <code>JPanel</code>.
+ *
+ * @author Roman Kennke (roman@kennke.org)
+ */
+ protected class AccessibleJPanel extends AccessibleJComponent
+ {
+ /**
+ * Creates a new instance of <code>AccessibleJPanel</code>.
+ */
+ public AccessibleJPanel()
{
- this(new FlowLayout(),
- true);
+ // Nothing to do here.
}
-
- public JPanel(boolean double_buffered)
- {
- this(new FlowLayout(),
- double_buffered);
- }
-
- public JPanel(LayoutManager layout)
- {
- this(layout,
- true);
- }
-
-
- public JPanel(LayoutManager layout,
- boolean isDoubleBuffered)
- {
- if (layout == null)
- {
- System.err.println("NO LAYOUT SET !!!");
- layout = new FlowLayout();
- }
- setLayout(layout);
- setOpaque(true);
-
- updateUI();
- }
-
- public String getUIClassID()
- { return "PanelUI"; }
-
- public void setUI(PanelUI ui) {
- super.setUI(ui);
- }
-
- public PanelUI getUI() {
- return (PanelUI)ui;
- }
-
- public void updateUI() {
- setUI((PanelUI)UIManager.getUI(this));
- }
-
-
- public AccessibleContext getAccessibleContext()
+ /**
+ * Returns the accessible role for <code>JPanel</code>, which is
+ * {@link AccessibleRole#PANEL}.
+ *
+ * @return the accessible role for <code>JPanel</code>
+ */
+ public AccessibleRole getAccessibleRole()
{
- return null;
+ return AccessibleRole.PANEL;
}
+ }
+
+ public JPanel()
+ {
+ this(new FlowLayout(), true);
+ }
+
+ public JPanel(boolean double_buffered)
+ {
+ this(new FlowLayout(), double_buffered);
+ }
+
+ public JPanel(LayoutManager layout)
+ {
+ this(layout, true);
+ }
+
+ public JPanel(LayoutManager layout, boolean isDoubleBuffered)
+ {
+ if (layout == null)
+ {
+ // TODO: Is this correct? Or should we throw a NPE?
+ layout = new FlowLayout();
+ }
+ setLayout(layout);
+ setOpaque(true);
+
+ updateUI();
+ }
+
+ public String getUIClassID()
+ {
+ return "PanelUI";
+ }
+
+ public void setUI(PanelUI ui)
+ {
+ super.setUI(ui);
+ }
+
+ public PanelUI getUI()
+ {
+ return (PanelUI) ui;
+ }
+
+ public void updateUI()
+ {
+ setUI((PanelUI) UIManager.getUI(this));
+ }
+
+ public AccessibleContext getAccessibleContext()
+ {
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJPanel();
+ return accessibleContext;
+ }
- protected String paramString()
- {
+ protected String paramString()
+ {
return "JPanel";
- }
+ }
}
diff --git a/libjava/classpath/javax/swing/JPasswordField.java b/libjava/classpath/javax/swing/JPasswordField.java
index 151d2484a82..11e45e8a58a 100644
--- a/libjava/classpath/javax/swing/JPasswordField.java
+++ b/libjava/classpath/javax/swing/JPasswordField.java
@@ -67,6 +67,7 @@ public class JPasswordField extends JTextField
*/
protected AccessibleJPasswordField()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/JPopupMenu.java b/libjava/classpath/javax/swing/JPopupMenu.java
index c4ee5fe7346..1f2282e2326 100644
--- a/libjava/classpath/javax/swing/JPopupMenu.java
+++ b/libjava/classpath/javax/swing/JPopupMenu.java
@@ -39,19 +39,13 @@ exception statement from your version. */
package javax.swing;
import java.awt.Component;
-import java.awt.Container;
import java.awt.Dimension;
-import java.awt.GridBagConstraints;
import java.awt.Insets;
-import java.awt.Panel;
import java.awt.Point;
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.ArrayList;
import java.util.EventListener;
@@ -102,11 +96,11 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
1. if DefaultLightWeightPopupEnabled true
(i) use lightweight container if popup feets inside top-level window
- (ii) only use heavyweight container (JWindow) if popup doesn't fit.
+ (ii) only use heavyweight container (JDialog) if popup doesn't fit.
2. if DefaultLightWeightPopupEnabled false
(i) if popup fits, use awt.Panel (mediumWeight)
- (ii) if popup doesn't fit, use JWindow (heavyWeight)
+ (ii) if popup doesn't fit, use JDialog (heavyWeight)
*/
private static boolean DefaultLightWeightPopupEnabled = true;
@@ -130,8 +124,15 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
/* Popup that is used to display JPopupMenu */
private transient Popup popup;
- /* Location of the popup */
- private Point popupLocation;
+ /**
+ * Location of the popup, X coordinate.
+ */
+ private int popupLocationX;
+
+ /**
+ * Location of the popup, Y coordinate.
+ */
+ private int popupLocationY;
/* Field indicating if popup menu is visible or not */
private boolean visible = false;
@@ -158,15 +159,6 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
updateUI();
}
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException
- {
- }
-
- private void writeObject(ObjectOutputStream stream) throws IOException
- {
- }
-
/**
* Adds given menu item to the popup menu
*
@@ -220,19 +212,7 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
public void remove(int index)
{
super.remove(index);
-
- GridBagConstraints constraints = new GridBagConstraints();
- constraints.fill = GridBagConstraints.BOTH;
- 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);
- }
- this.setSize(this.getPreferredSize());
+ revalidate();
}
/**
@@ -257,27 +237,7 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
*/
public void insert(Component component, int index)
{
- GridBagConstraints constraints = new GridBagConstraints();
- constraints.fill = GridBagConstraints.BOTH;
- constraints.weightx = 100.0;
- constraints.weighty = 100.0;
-
- 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);
- }
- }
- this.setSize(this.getPreferredSize());
+ super.add(component, index);
}
/**
@@ -527,7 +487,20 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
*/
public void pack()
{
- super.setSize(null);
+ // Hook up this call so that it gets executed on the event thread in order
+ // to avoid synchronization problems when calling the layout manager.
+ if (! SwingUtilities.isEventDispatchThread())
+ {
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ show();
+ }
+ });
+ }
+
+ setSize(getPreferredSize());
}
/**
@@ -547,8 +520,21 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
*
* @param visible true if popup menu will become visible and false otherwise.
*/
- public void setVisible(boolean visible)
+ public void setVisible(final boolean visible)
{
+ // Hook up this call so that it gets executed on the event thread in order
+ // to avoid synchronization problems when calling the layout manager.
+ if (! SwingUtilities.isEventDispatchThread())
+ {
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ setVisible(visible);
+ }
+ });
+ }
+
if (visible == isVisible())
return;
@@ -556,58 +542,21 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
this.visible = visible;
if (old != isVisible())
{
- firePropertyChange("visible", old, isVisible());
- if (visible)
- {
- firePopupMenuWillBecomeVisible();
- 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() - popupLocation.x))
- || (size.height > (rootContainer.getHeight() - popupLocation.y)))
- 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 p = new Point(popupLocation.x, popupLocation.y);
- SwingUtilities.convertPointFromScreen(p, layeredPane);
- popup.show(p.x, p.y, size.width, size.height);
- }
- else
- {
- // Subtract insets of the top-level container if popup menu's
- // top-left corner is inside it.
- Insets insets = rootContainer.getInsets();
- popup.show(popupLocation.x - insets.left,
- popupLocation.y - insets.top, size.width,
- size.height);
- }
- }
- else
- {
- firePopupMenuWillBecomeInvisible();
- popup.hide();
- }
+ firePropertyChange("visible", old, isVisible());
+ if (visible)
+ {
+ firePopupMenuWillBecomeVisible();
+
+ PopupFactory pf = PopupFactory.getSharedInstance();
+ pack();
+ popup = pf.getPopup(invoker, this, popupLocationX, popupLocationY);
+ popup.show();
+ }
+ else
+ {
+ firePopupMenuWillBecomeInvisible();
+ popup.hide();
+ }
}
}
@@ -619,11 +568,11 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
*/
public void setLocation(int x, int y)
{
- if (popupLocation == null)
- popupLocation = new Point();
-
- popupLocation.x = x;
- popupLocation.y = y;
+ popupLocationX = x;
+ popupLocationY = y;
+ // Handle the case when the popup is already showing. In this case we need
+ // to fetch a new popup from PopupFactory and use this. See the general
+ // contract of the PopupFactory.
}
/**
@@ -657,11 +606,14 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
*/
public void show(Component component, int x, int y)
{
- setInvoker(component);
- Point p = new Point(x, y);
- SwingUtilities.convertPointToScreen(p, component);
- setLocation(p.x, p.y);
- setVisible(true);
+ if (component.isShowing())
+ {
+ setInvoker(component);
+ Point p = new Point(x, y);
+ SwingUtilities.convertPointToScreen(p, component);
+ setLocation(p.x, p.y);
+ setVisible(true);
+ }
}
/**
@@ -882,162 +834,13 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
}
/**
- * This interface is used to display menu items of the JPopupMenu
- */
- private interface Popup
- {
- /**
- * Displays container on the screen
- *
- * @param x x-coordinate of popup menu's location on the screen
- * @param y y-coordinate of popup menu's location on the screen
- * @param width width of the container that is used to display menu
- * item's for popup menu
- * @param height height of the container that is used to display menu
- * item's for popup menu
- */
- void show(int x, int y, int width, int height);
-
- /**
- * Hides container used to display popup menu item's from the screen
- */
- void hide();
- }
-
- /**
- * This class represents Popup menu that uses light weight container
- * to display its contents.
- */
- private class LightWeightPopup extends Container implements Popup
- {
- private Component c;
-
- /**
- * Creates a new LightWeightPopup menu
- *
- * @param c Container containing menu items
- */
- public LightWeightPopup(Container c)
- {
- this.c = c;
- }
-
- /**
- * Displayes lightweight container with menu items to the screen
- *
- * @param x x-coordinate of lightweight container on the screen
- * @param y y-coordinate of lightweight container on the screen
- * @param width width of the lightweight container
- * @param height height of the lightweight container
- */
- public void show(int x, int y, int width, int height)
- {
- JLayeredPane layeredPane;
- layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane();
- c.setBounds(x, y, width, height);
- layeredPane.add(c, JLayeredPane.POPUP_LAYER, 0);
- }
-
- /**
- * Hides lightweight container from the screen
- */
- public void hide()
- {
- // FIXME: Right now the lightweight container is removed from JLayered
- // pane. It is probably would be better in order to improve performance
- // to make the container invisible instead of removing it everytime.
- JLayeredPane layeredPane;
- layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane();
- int index = layeredPane.getIndexOf(c);
- layeredPane.remove(index);
- }
- }
-
- /**
- * MediumWeightPopup is an AWT Panel with JPopupMenu's menu items.
- * It is used to display JPopupMenu's menu items on the screen
- */
- private class MediumWeightPopup extends Panel implements Popup
- {
- /**
- * Creates a new MediumWeightPopup object.
- *
- * @param c Container with JPopupMenu's menu items
- */
- public MediumWeightPopup(Container c)
- {
- this.add(c);
- }
-
- /**
- * Displays AWT Panel with its components on the screen
- *
- * @param x x-coordinate of the upper-left corner of the panel's
- * @param y y-coordinate of the upper-left corner of the panel's
- * @param width width of the panel
- * @param height height of the panel
- */
- public void show(int x, int y, int width, int height)
- {
- JLayeredPane layeredPane;
- layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane();
- layeredPane.add(this, JLayeredPane.POPUP_LAYER, 0);
- this.setBounds(x, y, width, height);
- }
-
- /**
- * Hides This panel from the screen
- */
- public void hide()
- {
- // FIXME: Right now the lightweight container is removed from JLayered
- // pane. It is probably would be better in order to improve performance
- // to make the container invisible instead of removing it everytime.
- JLayeredPane layeredPane;
- layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane();
- int index = layeredPane.getIndexOf(this);
- layeredPane.remove(index);
- }
- }
-
- /**
- * HeavyWeightPopup is JWindow that is used to display JPopupMenu menu item's
- * on the screen
- */
- private class HeavyWeightPopup extends JWindow implements Popup
- {
- /**
- * Creates a new HeavyWeightPopup object.
- *
- * @param c Container containing menu items
- */
- public HeavyWeightPopup(Container c)
- {
- this.setContentPane(c);
- }
-
- /**
- * Displays JWindow container JPopupMenu's menu items to the screen
- *
- * @param x x-coordinate of JWindow containing menu items
- * @param y y-coordinate of JWindow containing menu items
- * @param width width of the JWindow
- * @param height height of the JWindow
- */
- public void show(int x, int y, int width, int height)
- {
- this.setBounds(x, y, width, height);
- this.show();
- }
- }
-
- /**
* This is the separator that can be used in popup menu.
*/
public static class Separator extends JSeparator
{
public Separator()
{
+ super();
}
public String getUIClassID()
@@ -1052,6 +855,7 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
protected AccessibleJPopupMenu()
{
+ // Nothing to do here.
}
public AccessibleRole getAccessibleRole()
@@ -1066,8 +870,9 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
{
public void propertyChange(PropertyChangeEvent evt)
{
- JPopupMenu.this.revalidate();
- JPopupMenu.this.repaint();
+ // We used to have a revalidate() and repaint() call here. However I think
+ // this is not needed. Instead, a new Popup has to be fetched from the
+ // PopupFactory and used here.
}
}
}
diff --git a/libjava/classpath/javax/swing/JProgressBar.java b/libjava/classpath/javax/swing/JProgressBar.java
index 1b8fcea4672..0de9115dc7d 100644
--- a/libjava/classpath/javax/swing/JProgressBar.java
+++ b/libjava/classpath/javax/swing/JProgressBar.java
@@ -81,6 +81,8 @@ public class JProgressBar extends JComponent implements SwingConstants,
/**
* AccessibleJProgressBar
*/
+ // FIXME: This inner class is a complete stub and needs to be implemented
+ // properly.
protected class AccessibleJProgressBar extends AccessibleJComponent
implements AccessibleValue
{
@@ -91,6 +93,7 @@ public class JProgressBar extends JComponent implements SwingConstants,
*/
protected AccessibleJProgressBar()
{
+ // Nothing to do here.
}
/**
@@ -243,7 +246,7 @@ public class JProgressBar extends JComponent implements SwingConstants,
model = new DefaultBoundedRangeModel(minimum, 0, minimum, maximum);
if (orientation != HORIZONTAL && orientation != VERTICAL)
throw new IllegalArgumentException(orientation + " is not a legal orientation");
- this.orientation = orientation;
+ setOrientation(orientation);
changeListener = createChangeListener();
model.addChangeListener(changeListener);
updateUI();
diff --git a/libjava/classpath/javax/swing/JRadioButton.java b/libjava/classpath/javax/swing/JRadioButton.java
index 66f5902e899..e0593f3a501 100644
--- a/libjava/classpath/javax/swing/JRadioButton.java
+++ b/libjava/classpath/javax/swing/JRadioButton.java
@@ -192,8 +192,8 @@ public class JRadioButton extends JToggleButton
public JRadioButton(String text, Icon icon, boolean selected)
{
super(text, icon, selected);
- borderPainted = false;
- contentAreaFilled = false;
+ setBorderPainted(false);
+ setHorizontalAlignment(LEADING);
}
/**
diff --git a/libjava/classpath/javax/swing/JRadioButtonMenuItem.java b/libjava/classpath/javax/swing/JRadioButtonMenuItem.java
index 76a8fef640a..61a8dbab300 100644
--- a/libjava/classpath/javax/swing/JRadioButtonMenuItem.java
+++ b/libjava/classpath/javax/swing/JRadioButtonMenuItem.java
@@ -38,9 +38,6 @@ exception statement from your version. */
package javax.swing;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
@@ -149,10 +146,6 @@ public class JRadioButtonMenuItem extends JMenuItem implements Accessible
model.setSelected(selected);
}
- private void writeObject(ObjectOutputStream stream) throws IOException
- {
- }
-
/**
* This method returns a name to identify which look and feel class will be
* the UI delegate for the menuItem.
@@ -202,6 +195,7 @@ public class JRadioButtonMenuItem extends JMenuItem implements Accessible
*/
protected AccessibleJRadioButtonMenuItem()
{
+ // Nothing to do here.
}
public AccessibleRole getAccessibleRole()
diff --git a/libjava/classpath/javax/swing/JRootPane.java b/libjava/classpath/javax/swing/JRootPane.java
index cb0bafd84e0..dea4ee4b195 100644
--- a/libjava/classpath/javax/swing/JRootPane.java
+++ b/libjava/classpath/javax/swing/JRootPane.java
@@ -42,10 +42,14 @@ import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
+import java.awt.IllegalComponentStateException;
+import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.LayoutManager2;
+import java.awt.Rectangle;
import java.io.Serializable;
+import javax.accessibility.Accessible;
import javax.accessibility.AccessibleRole;
import javax.swing.plaf.RootPaneUI;
@@ -59,10 +63,10 @@ import javax.swing.plaf.RootPaneUI;
*
* @author Ronald Veldema (rveldema@cs.vu.nl)
*/
-public class JRootPane extends JComponent
+public class JRootPane extends JComponent implements Accessible
{
// The class used to obtain the accessible role for this object.
- protected static class AccessibleJRootPane
+ protected class AccessibleJRootPane extends AccessibleJComponent
{
/**
* For compatability with Sun's JDK
@@ -74,6 +78,7 @@ public class JRootPane extends JComponent
*/
protected AccessibleJRootPane()
{
+ // Nothing to do here.
}
/**
@@ -95,10 +100,36 @@ public class JRootPane extends JComponent
private static final long serialVersionUID = -4100116998559815027L;
/**
+ * The cached layout info for the glass pane.
+ */
+ private Rectangle glassPaneBounds;
+
+ /**
+ * The cached layout info for the layered pane.
+ */
+ private Rectangle layeredPaneBounds;
+
+ /**
+ * The cached layout info for the content pane.
+ */
+ private Rectangle contentPaneBounds;
+
+ /**
+ * The cached layout info for the menu bar.
+ */
+ private Rectangle menuBarBounds;
+
+ /**
+ * The cached preferred size.
+ */
+ private Dimension prefSize;
+
+ /**
* Creates a new <code>RootLayout</code> object.
*/
protected RootLayout()
{
+ // Nothing to do here.
}
/**
@@ -109,6 +140,7 @@ public class JRootPane extends JComponent
*/
public void addLayoutComponent(Component comp, Object constraints)
{
+ // Nothing to do here.
}
/**
@@ -119,6 +151,7 @@ public class JRootPane extends JComponent
*/
public void addLayoutComponent(String name, Component comp)
{
+ // Nothing to do here.
}
/**
@@ -130,7 +163,7 @@ public class JRootPane extends JComponent
*/
public float getLayoutAlignmentX(Container target)
{
- return target.getAlignmentX();
+ return 0.0F;
}
/**
@@ -142,7 +175,7 @@ public class JRootPane extends JComponent
*/
public float getLayoutAlignmentY(Container target)
{
- return target.getAlignmentY();
+ return 0.0F;
}
/**
@@ -152,6 +185,14 @@ public class JRootPane extends JComponent
*/
public void invalidateLayout(Container target)
{
+ synchronized (this)
+ {
+ glassPaneBounds = null;
+ layeredPaneBounds = null;
+ contentPaneBounds = null;
+ menuBarBounds = null;
+ prefSize = null;
+ }
}
/**
@@ -161,81 +202,56 @@ public class JRootPane extends JComponent
*/
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 (glassPaneBounds == null || layeredPaneBounds == null
+ || contentPaneBounds == null || menuBarBounds == null)
{
+ Insets i = getInsets();
+ int containerWidth = c.getBounds().width - i.left - i.right;
+ int containerHeight = c.getBounds().height - i.top - i.bottom;
+
+ // 1. the glassPane fills entire viewable region (bounds - insets).
+ // 2. the layeredPane filles entire viewable region.
+ // 3. the menuBar is positioned at the upper edge of layeredPane.
+ // 4. the contentPane fills viewable region minus menuBar, if present.
+
+
+ // +-------------------------------+
+ // | JLayeredPane |
+ // | +--------------------------+ |
+ // | | menuBar | |
+ // | +--------------------------+ |
+ // | +--------------------------+ |
+ // | |contentPane | |
+ // | | | |
+ // | | | |
+ // | | | |
+ // | +--------------------------+ |
+ // +-------------------------------+
+
if (menuBar != null)
{
- int maxWidth;
- menuBarSize = menuBar.getPreferredSize();
- maxWidth = Math.max(menuBarSize.width, contentPaneSize.width);
- menuBar.setBounds(0, 0, maxWidth, menuBarSize.height);
- glassPane.setBounds(0, menuBarSize.height, maxWidth,
- contentPaneSize.height);
- contentPane.setBounds(0, menuBarSize.height, maxWidth,
- contentPaneSize.height);
- layeredPane.setSize(maxWidth,
- menuBarSize.height + contentPaneSize.height);
+ Dimension menuBarSize = menuBar.getPreferredSize();
+ if (menuBarSize.height > containerHeight)
+ menuBarSize.height = containerHeight;
+ menuBarBounds = new Rectangle(0, 0, containerWidth,
+ menuBarSize.height);
+ contentPaneBounds = new Rectangle(0, menuBarSize.height,
+ containerWidth,
+ containerHeight - menuBarSize.height);
}
else
- {
- glassPane.setBounds(0, 0, contentPaneSize.width,
- contentPaneSize.height);
- contentPane.setBounds(0, 0, contentPaneSize.width,
- contentPaneSize.height);
- layeredPane.setSize(contentPaneSize.width, contentPaneSize.height);
- }
+ contentPaneBounds = new Rectangle(0, 0, containerWidth,
+ containerHeight);
+
+ glassPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight);
+ layeredPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight);
}
- 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;
- glassPane.setBounds(0, menuBarSize.height, containerSize.width,
- containerSize.height - menuBarSize.height);
- contentPane.setBounds(0, menuBarSize.height,
- containerSize.width,
- (containerSize.height - menuBarSize.height));
- }
- else
- {
- glassPane.setBounds(0, 0, containerSize.width,
- containerSize.height);
- contentPane.setBounds(0, 0, containerSize.width,
- containerSize.height);
- }
- layeredPane.setSize(containerSize.width, containerSize.height);
- }
+ glassPane.setBounds(glassPaneBounds);
+ layeredPane.setBounds(layeredPaneBounds);
+ if (menuBar != null)
+ menuBar.setBounds(menuBarBounds);
+ contentPane.setBounds(contentPaneBounds);
}
/**
@@ -271,30 +287,29 @@ public class JRootPane extends JComponent
*/
public Dimension preferredLayoutSize(Container c)
{
- Dimension menuBarSize;
- Dimension prefSize;
-
- Dimension containerSize = c.getSize();
- Dimension contentPaneSize = contentPane.getPreferredSize();
-
- if (containerSize.width == 0 && containerSize.height == 0)
+ // We must synchronize here, otherwise we cannot guarantee that the
+ // prefSize is still non-null when returning.
+ synchronized (this)
{
- if (menuBar != null)
+ if (prefSize == null)
{
- int maxWidth;
- menuBarSize = menuBar.getPreferredSize();
- maxWidth = Math.max(menuBarSize.width, contentPaneSize.width);
- prefSize = new Dimension(maxWidth,
- contentPaneSize.height
- + menuBarSize.height);
+ Insets i = getInsets();
+ prefSize = new Dimension(i.left + i.right, i.top + i.bottom);
+ Dimension contentPrefSize = contentPane.getPreferredSize();
+ prefSize.width += contentPrefSize.width;
+ prefSize.height += contentPrefSize.height;
+ if (menuBar != null)
+ {
+ Dimension menuBarSize = menuBar.getPreferredSize();
+ if (menuBarSize.width > contentPrefSize.width)
+ prefSize.width += menuBarSize.width - contentPrefSize.width;
+ prefSize.height += menuBarSize.height;
+ }
}
- else
- prefSize = contentPaneSize;
- }
- else
- prefSize = c.getSize();
-
- return prefSize;
+ // Return a copy here so the cached value won't get trashed by some
+ // other component.
+ return new Dimension(prefSize);
+ }
}
/**
@@ -304,6 +319,7 @@ public class JRootPane extends JComponent
*/
public void removeLayoutComponent(Component comp)
{
+ // Nothing to do here.
}
}
@@ -335,6 +351,32 @@ public class JRootPane extends JComponent
protected JButton defaultButton;
/**
+ * This field is unused since JDK1.3. To override the default action you
+ * should modify the JRootPane's ActionMap.
+ *
+ * @deprecated since JDK1.3
+ *
+ * @specnote the specs indicate that the type of this field is
+ * a package private inner class
+ * javax.swing.JRootPane.DefaultAction. I assume that the closest
+ * public superclass is javax.swing.Action.
+ */
+ protected Action defaultPressAction;
+
+ /**
+ * This field is unused since JDK1.3. To override the default action you
+ * should modify the JRootPane's ActionMap.
+ *
+ * @deprecated since JDK1.3
+ *
+ * @specnote the specs indicate that the type of this field is
+ * a package private inner class
+ * javax.swing.JRootPane.DefaultAction. I assume that the closest
+ * public superclass is javax.swing.Action.
+ */
+ protected Action defaultReleaseAction;
+
+ /**
* @since 1.4
*/
private int windowDecorationStyle = NONE;
@@ -403,14 +445,25 @@ public class JRootPane extends JComponent
}
/**
- * DOCUMENT ME!
+ * Sets the JRootPane's content pane. The content pane should typically be
+ * opaque for painting to work properly. This method also
+ * removes the old content pane from the layered pane.
*
- * @param p DOCUMENT ME!
+ * @param p the Container that will be the content pane
+ * @throws IllegalComponentStateException if p is null
*/
public void setContentPane(Container p)
{
- contentPane = p;
- getLayeredPane().add(contentPane, JLayeredPane.FRAME_CONTENT_LAYER);
+ if (p == null)
+ throw new IllegalComponentStateException ("cannot " +
+ "have a null content pane");
+ else
+ {
+ if (contentPane != null && contentPane.getParent() == layeredPane)
+ layeredPane.remove(contentPane);
+ contentPane = p;
+ getLayeredPane().add(contentPane, JLayeredPane.FRAME_CONTENT_LAYER);
+ }
}
/**
@@ -488,7 +541,6 @@ public class JRootPane extends JComponent
getGlassPane();
getLayeredPane();
getContentPane();
- setDoubleBuffered(true);
updateUI();
}
@@ -524,7 +576,6 @@ public class JRootPane extends JComponent
{
JPanel p = new JPanel();
p.setName(this.getName() + ".glassPane");
- p.setLayout(new BorderLayout());
p.setVisible(false);
p.setOpaque(false);
return p;
@@ -615,7 +666,8 @@ public class JRootPane extends JComponent
&& style != COLOR_CHOOSER_DIALOG
&& style != FILE_CHOOSER_DIALOG
&& style != QUESTION_DIALOG
- && style != WARNING_DIALOG)
+ && style != WARNING_DIALOG
+ && style != PLAIN_DIALOG)
throw new IllegalArgumentException("invalid style");
int oldStyle = windowDecorationStyle;
diff --git a/libjava/classpath/javax/swing/JScrollPane.java b/libjava/classpath/javax/swing/JScrollPane.java
index e83513f07de..45dfbf50619 100644
--- a/libjava/classpath/javax/swing/JScrollPane.java
+++ b/libjava/classpath/javax/swing/JScrollPane.java
@@ -40,13 +40,14 @@ package javax.swing;
import java.awt.Component;
import java.awt.ComponentOrientation;
-import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
-import java.awt.Point;
import java.awt.Rectangle;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@@ -77,10 +78,73 @@ import javax.swing.plaf.UIResource;
* <tr><td>wheelScrollingEnabled </td><td>scrollPane </td><td>yes </td></tr>
* </table>
*/
-public class JScrollPane
- extends JComponent
+public class JScrollPane extends JComponent
implements Accessible, ScrollPaneConstants
{
+ /**
+ * Provides accessibility support for the <code>JScrollPane</code>.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ protected class AccessibleJScrollPane extends AccessibleJComponent
+ implements ChangeListener, PropertyChangeListener
+ {
+
+ /**
+ * The viewport of the underlying scrollpane.
+ */
+ protected JViewport viewPort;
+
+ /**
+ * Creates a new <code>AccessibleJScrollPane</code> object. This
+ * initializes the <code>viewport</code> field with the current viewport
+ * from the scrollpane associated with this
+ * <code>AccessibleJScrollPane</code>.
+ */
+ public AccessibleJScrollPane()
+ {
+ viewPort = getViewport();
+ viewPort.addChangeListener(this);
+ viewPort.addPropertyChangeListener(this);
+ }
+
+ /**
+ * Receives notification when the state of the viewport changes.
+ *
+ * @param event the change event
+ */
+ public void stateChanged(ChangeEvent event)
+ {
+ // TODO: Figure out what should be done here, if anything.
+ }
+
+ /**
+ * Receives notification if any of the viewport's bound properties changes.
+ *
+ * @param e the propery change event
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ // TODO: Figure out what should be done here, if anything.
+ }
+
+ /**
+ * Resets the <code>viewPort</code> field when the scrollpane's viewport
+ * changes. This method is called by
+ * {@link JScrollPane#setViewport(JViewport)} in order to update the
+ * <code>viewPort</code> field and set up the listeners on this viewport
+ * correctly.
+ */
+ public void resetViewPort()
+ {
+ viewPort.removeChangeListener(this);
+ viewPort.removePropertyChangeListener(this);
+ viewPort = getViewport();
+ viewPort.addChangeListener(this);
+ viewPort.addPropertyChangeListener(this);
+ }
+ }
+
private static final long serialVersionUID = 5203525440012340014L;
protected JViewport columnHeader;
@@ -100,7 +164,6 @@ public class JScrollPane
Border viewportBorder;
boolean wheelScrollingEnabled;
- ChangeListener scrollListener;
public JViewport getColumnHeader()
{
@@ -228,10 +291,10 @@ public class JScrollPane
remove(c);
}
- private void addNonNull(Component c)
+ private void addNonNull(Component c, Object constraints)
{
if (c != null)
- add(c);
+ add(c, constraints);
}
public void setComponentOrientation(ComponentOrientation co)
@@ -250,7 +313,7 @@ public class JScrollPane
JViewport old = columnHeader;
removeNonNull(old);
columnHeader = h;
- addNonNull(h);
+ addNonNull(h, JScrollPane.COLUMN_HEADER);
firePropertyChange("columnHeader", old, h);
sync();
}
@@ -294,25 +357,25 @@ public class JScrollPane
{
removeNonNull(lowerRight);
lowerRight = c;
- addNonNull(c);
+ addNonNull(c, JScrollPane.LOWER_RIGHT_CORNER);
}
else if (key == UPPER_RIGHT_CORNER)
{
removeNonNull(upperRight);
upperRight = c;
- addNonNull(c);
+ addNonNull(c, JScrollPane.UPPER_RIGHT_CORNER);
}
else if (key == LOWER_LEFT_CORNER)
{
removeNonNull(lowerLeft);
lowerLeft = c;
- addNonNull(c);
+ addNonNull(c, JScrollPane.LOWER_LEFT_CORNER);
}
else if (key == UPPER_LEFT_CORNER)
{
removeNonNull(upperLeft);
upperLeft = c;
- addNonNull(c);
+ addNonNull(c, JScrollPane.UPPER_LEFT_CORNER);
}
else
throw new IllegalArgumentException("unknown corner " + key);
@@ -327,22 +390,10 @@ public class JScrollPane
JScrollBar old = horizontalScrollBar;
removeNonNull(old);
horizontalScrollBar = h;
- addNonNull(h);
+ addNonNull(h, JScrollPane.HORIZONTAL_SCROLLBAR);
firePropertyChange("horizontalScrollBar", old, h);
sync();
- if (old != null)
- {
- BoundedRangeModel model = old.getModel();
- if (model != null)
- model.removeChangeListener(scrollListener);
- }
- if (h != null)
- {
- BoundedRangeModel model = h.getModel();
- if (model != null)
- model.addChangeListener(scrollListener);
- }
}
public void setHorizontalScrollBarPolicy(int h)
@@ -359,6 +410,7 @@ public class JScrollPane
horizontalScrollBarPolicy = h;
firePropertyChange("horizontalScrollBarPolicy", old, h);
sync();
+ revalidate();
}
public void setLayout(LayoutManager l)
@@ -379,7 +431,7 @@ public class JScrollPane
JViewport old = rowHeader;
removeNonNull(old);
rowHeader = v;
- addNonNull(v);
+ addNonNull(v, JScrollPane.ROW_HEADER);
firePropertyChange("rowHeader", old, v);
sync();
}
@@ -400,22 +452,9 @@ public class JScrollPane
JScrollBar old = verticalScrollBar;
removeNonNull(old);
verticalScrollBar = v;
- addNonNull(v);
+ addNonNull(v, JScrollPane.VERTICAL_SCROLLBAR);
firePropertyChange("verticalScrollBar", old, v);
sync();
-
- if (old != null)
- {
- BoundedRangeModel model = old.getModel();
- if (model != null)
- model.removeChangeListener(scrollListener);
- }
- if (v != null)
- {
- BoundedRangeModel model = v.getModel();
- if (model != null)
- model.addChangeListener(scrollListener);
- }
}
public void setVerticalScrollBarPolicy(int v)
@@ -432,6 +471,7 @@ public class JScrollPane
verticalScrollBarPolicy = v;
firePropertyChange("verticalScrollBarPolicy", old, v);
sync();
+ revalidate();
}
public void setWheelScrollingEnabled(boolean b)
@@ -452,16 +492,17 @@ public class JScrollPane
JViewport old = viewport;
removeNonNull(old);
- if (old != null)
- old.removeChangeListener(scrollListener);
viewport = v;
- if (v != null)
- v.addChangeListener(scrollListener);
- addNonNull(v);
+ addNonNull(v, JScrollPane.VIEWPORT);
revalidate();
repaint();
firePropertyChange("viewport", old, v);
sync();
+ if (accessibleContext != null)
+ {
+ AccessibleJScrollPane asp = (AccessibleJScrollPane) accessibleContext;
+ asp.resetViewPort();
+ }
}
public void setViewportBorder(Border b)
@@ -494,79 +535,6 @@ public class JScrollPane
return true;
}
- ChangeListener createScrollListener()
- {
- return new ChangeListener()
- {
-
- public void stateChanged(ChangeEvent event)
- {
- JScrollBar vsb = JScrollPane.this.getVerticalScrollBar();
- JScrollBar hsb = JScrollPane.this.getHorizontalScrollBar();
- JViewport vp = JScrollPane.this.getViewport();
-
- if (vp != null && event.getSource() == vp)
- {
- // 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();
- if (vsb != null
- && (vsb.getMinimum() != 0
- || vsb.getMaximum() != vs.height
- || vsb.getValue() != vr.y
- || vsb.getVisibleAmount() != vr.height))
- vsb.setValues(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.setValues(vr.x, vr.width, 0, vs.width);
- }
- else
- {
- // otherwise we got a change update from either the VSB or
- // HSB model, and we need to update the viewport positions of
- // both the main viewport and any row or column headers 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);
-
- pt.x = 0;
-
- if (rowHeader != null
- && rowHeader.getViewPosition() != pt)
- rowHeader.setViewPosition(pt);
-
- pt.x = xpos;
- pt.y = 0;
-
- if (columnHeader != null
- && columnHeader.getViewPosition() != pt)
- columnHeader.setViewPosition(pt);
-
- }
- }
- };
- }
-
-
/**
* Creates a new <code>JScrollPane</code> without a view. The scrollbar
* policy is set to {@link #VERTICAL_SCROLLBAR_AS_NEEDED} and
@@ -627,7 +595,6 @@ public class JScrollPane
*/
public JScrollPane(Component view, int vsbPolicy, int hsbPolicy)
{
- scrollListener = createScrollListener();
setVerticalScrollBarPolicy(vsbPolicy);
setVerticalScrollBar(createVerticalScrollBar());
setHorizontalScrollBarPolicy(hsbPolicy);
@@ -635,7 +602,6 @@ public class JScrollPane
viewport = createViewport();
if (view != null)
getViewport().setView(view);
- viewport.addChangeListener(scrollListener);
add(viewport,0);
setLayout(new ScrollPaneLayout());
setOpaque(false);
@@ -728,4 +694,18 @@ public class JScrollPane
}
}
}
+
+ /**
+ * Returns the accessible context associated with this
+ * <code>JScrollPane</code>.
+ *
+ * @return the accessible context associated with this
+ * <code>JScrollPane</code>
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJScrollPane();
+ return accessibleContext;
+ }
}
diff --git a/libjava/classpath/javax/swing/JSeparator.java b/libjava/classpath/javax/swing/JSeparator.java
index 6a3b97d35c6..602af6a380c 100644
--- a/libjava/classpath/javax/swing/JSeparator.java
+++ b/libjava/classpath/javax/swing/JSeparator.java
@@ -62,6 +62,7 @@ public class JSeparator extends JComponent implements SwingConstants,
*/
protected AccessibleJSeparator()
{
+ // Nothing to do here.
}
/**
@@ -131,7 +132,6 @@ public class JSeparator extends JComponent implements SwingConstants,
public void updateUI()
{
setUI((SeparatorUI) UIManager.getUI(this));
- invalidate();
}
/**
diff --git a/libjava/classpath/javax/swing/JSlider.java b/libjava/classpath/javax/swing/JSlider.java
index 2caf509a1bb..b28b06abad7 100644
--- a/libjava/classpath/javax/swing/JSlider.java
+++ b/libjava/classpath/javax/swing/JSlider.java
@@ -118,6 +118,8 @@ public class JSlider extends JComponent implements SwingConstants, Accessible,
/**
* DOCUMENT ME!
*/
+ // FIXME: This inner class is a complete stub and needs to be implemented
+ // properly.
protected class AccessibleJSlider extends JComponent.AccessibleJComponent
implements AccessibleValue
{
@@ -128,6 +130,7 @@ public class JSlider extends JComponent implements SwingConstants, Accessible,
*/
protected AccessibleJSlider()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/JSpinner.java b/libjava/classpath/javax/swing/JSpinner.java
index fc2b13e81a9..af34d9cf67d 100644
--- a/libjava/classpath/javax/swing/JSpinner.java
+++ b/libjava/classpath/javax/swing/JSpinner.java
@@ -108,10 +108,10 @@ public class JSpinner extends JComponent
/**
* DOCUMENT ME!
*/
- public void commitEdit()
- throws ParseException
+ public void commitEdit() throws ParseException
{
- } /* TODO */
+ // TODO: Implement this properly.
+ }
/**
* DOCUMENT ME!
@@ -184,7 +184,8 @@ public class JSpinner extends JComponent
*/
public void propertyChange(PropertyChangeEvent event)
{
- } /* TODO */
+ // TODO: Implement this properly.
+ }
/**
* DOCUMENT ME!
@@ -193,11 +194,12 @@ public class JSpinner extends JComponent
*/
public void stateChanged(ChangeEvent event)
{
- } /* TODO */
+ // TODO: Implement this properly.
+ }
- /* no-ops */
public void removeLayoutComponent(Component child)
{
+ // Nothing to do here.
}
/**
@@ -208,6 +210,7 @@ public class JSpinner extends JComponent
*/
public void addLayoutComponent(String name, Component child)
{
+ // Nothing to do here.
}
}
@@ -258,6 +261,31 @@ public class JSpinner extends JComponent
}
/**
+ * A <code>JSpinner</code> editor used for the {@link SpinnerListModel}.
+ * This editor uses a <code>JFormattedTextField</code> to edit the values
+ * of the spinner.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ public static class ListEditor extends DefaultEditor
+ {
+ /**
+ * Creates a new instance of <code>ListEditor</code>.
+ *
+ * @param spinner the spinner for which this editor is used
+ */
+ public ListEditor(JSpinner spinner)
+ {
+ super(spinner);
+ }
+
+ public SpinnerListModel getModel()
+ {
+ return (SpinnerListModel) getSpinner().getModel();
+ }
+ }
+
+ /**
* An editor class for a <code>JSpinner</code> that is used
* for displaying and editing dates (e.g. that uses
* <code>SpinnerDateModel</code> as model).
@@ -307,7 +335,7 @@ public class JSpinner extends JComponent
/**
* Initializes the JFormattedTextField for this editor.
*
- * @param the date format to use in the formatted text field
+ * @param format the date format to use in the formatted text field
*/
private void init(SimpleDateFormat format)
{
diff --git a/libjava/classpath/javax/swing/JSplitPane.java b/libjava/classpath/javax/swing/JSplitPane.java
index cea5afef20a..cdab7bb6c4e 100644
--- a/libjava/classpath/javax/swing/JSplitPane.java
+++ b/libjava/classpath/javax/swing/JSplitPane.java
@@ -59,6 +59,8 @@ public class JSplitPane extends JComponent implements Accessible
/**
* DOCUMENT ME!
*/
+ // FIXME: This inner class is a complete stub and must be implemented
+ // properly.
protected class AccessibleJSplitPane extends JComponent.AccessibleJComponent
implements AccessibleValue
{
@@ -69,6 +71,7 @@ public class JSplitPane extends JComponent implements Accessible
*/
protected AccessibleJSplitPane()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/JTabbedPane.java b/libjava/classpath/javax/swing/JTabbedPane.java
index 828a69a24dc..27ba7bb82fc 100644
--- a/libjava/classpath/javax/swing/JTabbedPane.java
+++ b/libjava/classpath/javax/swing/JTabbedPane.java
@@ -56,8 +56,9 @@ import javax.swing.plaf.TabbedPaneUI;
import javax.swing.plaf.UIResource;
/**
- * This is a container for components. One component is displayed at a time.
- * Users can switch between components by clicking on tabs.
+ * This is a container for components where only one component is displayed at
+ * a given time and the displayed component can be switched by clicking on
+ * tabs.
*
* <p>
* Tabs can be oriented in several ways. They can be above, below, left and
@@ -72,12 +73,16 @@ public class JTabbedPane extends JComponent implements Serializable,
SwingConstants
{
/**
- * DOCUMENT ME!
+ * Accessibility support for <code>JTabbedPane</code>.
*/
+ // FIXME: This inner class is a complete stub and must be implemented
+ // properly.
protected class AccessibleJTabbedPane extends JComponent.AccessibleJComponent
implements AccessibleSelection, ChangeListener
{
- /** DOCUMENT ME! */
+ /**
+ * The serialization UID.
+ */
private static final long serialVersionUID = 7610530885966830483L;
/**
@@ -89,18 +94,21 @@ public class JTabbedPane extends JComponent implements Serializable,
}
/**
- * DOCUMENT ME!
+ * Receives notification when the selection state of the
+ * <code>JTabbedPane</code> changes.
*
- * @param e DOCUMENT ME!
+ * @param e the change event describing the change
*/
public void stateChanged(ChangeEvent e)
{
+ // Implement this properly.
}
/**
- * DOCUMENT ME!
+ * Returns the accessible role of the <code>JTabbedPane</code>, which is
+ * {@link AccessibleRole#PAGE_TAB_LIST}.
*
- * @return DOCUMENT ME!
+ * @return the accessible role of the <code>JTabbedPane</code>
*/
public AccessibleRole getAccessibleRole()
{
@@ -108,9 +116,11 @@ public class JTabbedPane extends JComponent implements Serializable,
}
/**
- * DOCUMENT ME!
+ * Returns the number of accessible child components of the
+ * <code>JTabbedPane</code>.
*
- * @return DOCUMENT ME!
+ * @return the number of accessible child components of the
+ * <code>JTabbedPane</code>
*/
public int getAccessibleChildrenCount()
{
@@ -118,11 +128,11 @@ public class JTabbedPane extends JComponent implements Serializable,
}
/**
- * DOCUMENT ME!
+ * Returns the accessible child component at the specified index.
*
- * @param i DOCUMENT ME!
+ * @param i the index of the child component to fetch
*
- * @return DOCUMENT ME!
+ * @return the accessible child component at the specified index
*/
public Accessible getAccessibleChild(int i)
{
@@ -130,9 +140,10 @@ public class JTabbedPane extends JComponent implements Serializable,
}
/**
- * DOCUMENT ME!
+ * Returns the current selection state of the <code>JTabbedPane</code>
+ * as AccessibleSelection object.
*
- * @return DOCUMENT ME!
+ * @return the current selection state of the <code>JTabbedPane</code>
*/
public AccessibleSelection getAccessibleSelection()
{
@@ -140,11 +151,15 @@ public class JTabbedPane extends JComponent implements Serializable,
}
/**
- * DOCUMENT ME!
+ * Returns the accessible child component at the specified coordinates.
+ * If there is no child component at this location, then return the
+ * currently selected tab.
*
- * @param p DOCUMENT ME!
+ * @param p the coordinates at which to look up the child component
*
- * @return DOCUMENT ME!
+ * @return the accessible child component at the specified coordinates or
+ * the currently selected tab if there is no child component at
+ * this location
*/
public Accessible getAccessibleAt(Point p)
{
@@ -152,9 +167,13 @@ public class JTabbedPane extends JComponent implements Serializable,
}
/**
- * DOCUMENT ME!
+ * The number of selected child components of the
+ * <code>JTabbedPane</code>. This will be <code>0</code> if the
+ * <code>JTabbedPane</code> has no children, or <code>1</code> otherwise,
+ * since there is always exactly one tab selected.
*
- * @return DOCUMENT ME!
+ * @return number of selected child components of the
+ * <code>JTabbedPane</code>
*/
public int getAccessibleSelectionCount()
{
@@ -192,6 +211,7 @@ public class JTabbedPane extends JComponent implements Serializable,
*/
public void addAccessibleSelection(int i)
{
+ // TODO: Implement this properly.
}
/**
@@ -201,6 +221,7 @@ public class JTabbedPane extends JComponent implements Serializable,
*/
public void removeAccessibleSelection(int i)
{
+ // TODO: Implement this properly.
}
/**
@@ -208,6 +229,7 @@ public class JTabbedPane extends JComponent implements Serializable,
*/
public void clearAccessibleSelection()
{
+ // TODO: Implement this properly.
}
/**
@@ -215,6 +237,7 @@ public class JTabbedPane extends JComponent implements Serializable,
*/
public void selectAllAccessibleSelection()
{
+ // TODO: Implement this properly.
}
}
@@ -231,6 +254,7 @@ public class JTabbedPane extends JComponent implements Serializable,
*/
protected ModelListener()
{
+ // Nothing to do here.
}
/**
@@ -313,9 +337,10 @@ public class JTabbedPane extends JComponent implements Serializable,
*/
public void setComponent(Component c)
{
- remove(component);
- this.component = c;
- add(c);
+ int i = indexOfComponent(component);
+ insertTab(title, icon, c, tip, i);
+ component = c;
+ removeTabAt(i);
}
/**
@@ -596,7 +621,7 @@ public class JTabbedPane extends JComponent implements Serializable,
throw new IllegalArgumentException("tabLayoutPolicy is not valid.");
this.tabPlacement = tabPlacement;
layoutPolicy = tabLayoutPolicy;
-
+
changeEvent = new ChangeEvent(this);
changeListener = createChangeListener();
@@ -863,15 +888,17 @@ public class JTabbedPane extends JComponent implements Serializable,
* This method inserts tabs into JTabbedPane. This includes adding the
* component to the JTabbedPane and hiding it.
*
- * @param title The title of the tab.
- * @param icon The tab's icon.
- * @param component The component associated with the tab.
- * @param tip The tooltip for the tab.
- * @param index The index to insert the tab at.
+ * @param title the title of the tab; may be <code>null</code>
+ * @param icon the tab's icon; may be <code>null</code>
+ * @param component the component associated with the tab
+ * @param tip the tooltip for the tab
+ * @param index the index to insert the tab at
*/
public void insertTab(String title, Icon icon, Component component,
String tip, int index)
{
+ if (title == null)
+ title = "";
Page p = new Page(title, icon, component, tip);
tabs.insertElementAt(p, index);
@@ -893,10 +920,10 @@ public class JTabbedPane extends JComponent implements Serializable,
/**
* This method adds a tab to the JTabbedPane.
*
- * @param title The title of the tab.
- * @param icon The icon for the tab.
- * @param component The associated component.
- * @param tip The associated tooltip.
+ * @param title the title of the tab; may be <code>null</code>
+ * @param icon the icon for the tab; may be <code>null</code>
+ * @param component the associated component
+ * @param tip the associated tooltip
*/
public void addTab(String title, Icon icon, Component component, String tip)
{
@@ -906,9 +933,9 @@ public class JTabbedPane extends JComponent implements Serializable,
/**
* This method adds a tab to the JTabbedPane.
*
- * @param title The title of the tab.
- * @param icon The icon for the tab.
- * @param component The associated component.
+ * @param title the title of the tab; may be <code>null</code>
+ * @param icon the icon for the tab; may be <code>null</code>
+ * @param component the associated component
*/
public void addTab(String title, Icon icon, Component component)
{
@@ -918,8 +945,8 @@ public class JTabbedPane extends JComponent implements Serializable,
/**
* This method adds a tab to the JTabbedPane.
*
- * @param title The title of the tab.
- * @param component The associated component.
+ * @param title the title of the tab; may be <code>null</code>
+ * @param component the associated component
*/
public void addTab(String title, Component component)
{
@@ -942,6 +969,7 @@ public class JTabbedPane extends JComponent implements Serializable,
super.add(component);
else
insertTab(component.getName(), null, component, null, tabs.size());
+
return component;
}
@@ -950,8 +978,8 @@ public class JTabbedPane extends JComponent implements Serializable,
* instance of UIResource, it doesn't add the tab and instead add the
* component directly to the JTabbedPane.
*
- * @param title The title of the tab.
- * @param component The associated component.
+ * @param title the title of the tab; may be <code>null</code>
+ * @param component the associated component
*
* @return The Component that was added.
*/
@@ -1025,45 +1053,37 @@ public class JTabbedPane extends JComponent implements Serializable,
}
/**
- * The tab and it's associated component are removed. After the component
- * has been removed from the JTabbedPane, it's set visible to ensure that
- * it can be seen.
+ * Removes the tab at index. After the component associated with
+ * index is removed, its visibility is reset to true to ensure it
+ * will be visible if added to other containers.
*
* @param index The index of the tab to remove.
*/
public void removeTabAt(int index)
{
checkIndex(index, 0, tabs.size());
- Component c = getComponentAt(index);
- super.remove(index);
- c.show();
tabs.remove(index);
+ getComponentAt(index).show();
}
/**
- * This method removes the component from the JTabbedPane. After the
- * component has been removed from the JTabbedPane, it's set visible to
- * ensure that it can be seen.
+ * Removes the specified Component from the JTabbedPane.
*
* @param component The Component to remove.
*/
public void remove(Component component)
{
- // This simply removes the component.
- int index = indexOfComponent(component);
super.remove(component);
- component.show();
- setComponentAt(index, null);
}
/**
- * This method removes the tab and component from the JTabbedPane. It simply
- * calls removeTabAt(int index).
+ * Removes the tab and component which corresponds to the specified index.
*
* @param index The index of the tab to remove.
*/
public void remove(int index)
{
+ remove(getComponentAt(index));
removeTabAt(index);
}
diff --git a/libjava/classpath/javax/swing/JTable.java b/libjava/classpath/javax/swing/JTable.java
index 21680d567e2..69a865df9c0 100644
--- a/libjava/classpath/javax/swing/JTable.java
+++ b/libjava/classpath/javax/swing/JTable.java
@@ -40,22 +40,34 @@ package javax.swing;
import java.awt.Color;
import java.awt.Component;
+import java.awt.Cursor;
import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
+import java.awt.event.FocusListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.EventObject;
import java.util.Hashtable;
+import java.util.Locale;
import java.util.Vector;
import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleComponent;
import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleExtendedTable;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleSelection;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleTable;
+import javax.accessibility.AccessibleTableModelChange;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
@@ -76,10 +88,874 @@ import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import javax.swing.text.Caret;
-public class JTable extends JComponent
+public class JTable
+ extends JComponent
implements TableModelListener, Scrollable, TableColumnModelListener,
ListSelectionListener, CellEditorListener, Accessible
{
+ /**
+ * Provides accessibility support for <code>JTable</code>.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ protected class AccessibleJTable
+ extends AccessibleJComponent
+ implements AccessibleSelection, ListSelectionListener, TableModelListener,
+ TableColumnModelListener, CellEditorListener, PropertyChangeListener,
+ AccessibleExtendedTable
+ {
+
+ /**
+ * Provides accessibility support for table cells.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ protected class AccessibleJTableCell
+ extends AccessibleContext
+ implements Accessible, AccessibleComponent
+ {
+
+ /**
+ * The table of this cell.
+ */
+ private JTable table;
+
+ /**
+ * The row index of this cell.
+ */
+ private int row;
+
+ /**
+ * The column index of this cell.
+ */
+ private int column;
+
+ /**
+ * The index of this cell inside the AccessibleJTable parent.
+ */
+ private int index;
+
+ /**
+ * Creates a new <code>AccessibleJTableCell</code>.
+ *
+ * @param t the table
+ * @param r the row
+ * @param c the column
+ * @param i the index of this cell inside the accessible table parent
+ */
+ public AccessibleJTableCell(JTable t, int r, int c, int i)
+ {
+ table = t;
+ row = r;
+ column = c;
+ index = i;
+ }
+
+ /**
+ * Returns the accessible row for the table cell.
+ *
+ * @return the accessible row for the table cell
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ // TODO: What is the role of the table cell?
+ return AccessibleRole.UNKNOWN;
+ }
+
+ /**
+ * Returns the accessible state set of this accessible table cell.
+ *
+ * @return the accessible state set of this accessible table cell
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ // TODO: What state shoiuld be returned here?
+ return new AccessibleStateSet();
+ }
+
+ /**
+ * Returns the index of this cell in the parent object.
+ *
+ * @return the index of this cell in the parent object
+ */
+ public int getAccessibleIndexInParent()
+ {
+ return index;
+ }
+
+ /**
+ * Returns the number of children of this object. Table cells cannot have
+ * children, so we return <code>0</code> here.
+ *
+ * @return <code>0</code>
+ */
+ public int getAccessibleChildrenCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the accessible child at index <code>i</code>. Table cells
+ * don't have children, so we return <code>null</code> here.
+ *
+ * @return <code>null</code>
+ */
+ public Accessible getAccessibleChild(int i)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the locale setting for this accessible table cell.
+ *
+ * @return the locale setting for this accessible table cell
+ */
+ public Locale getLocale()
+ {
+ // TODO: For now, we return english here. This must be fixed as soon
+ // as we have a localized Swing.
+ return Locale.ENGLISH;
+ }
+
+ /**
+ * Returns the accessible context of this table cell. Since accessible
+ * table cells are their own accessible context, we return
+ * <code>this</code>.
+ *
+ * @return the accessible context of this table cell
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the background color of this cell.
+ *
+ * @return the background color of this cell
+ */
+ public Color getBackground()
+ {
+ return table.getBackground();
+ }
+
+ /**
+ * Sets the background of the cell. Since table cells cannot have
+ * individual background colors, this method does nothing. Set the
+ * background directly on the table instead.
+ *
+ * @param color not used
+ */
+ public void setBackground(Color color)
+ {
+ // This method does nothing. See API comments.
+ }
+
+ /**
+ * Returns the foreground color of the table cell.
+ *
+ * @return the foreground color of the table cell
+ */
+ public Color getForeground()
+ {
+ return table.getForeground();
+ }
+
+ /**
+ * Sets the foreground of the cell. Since table cells cannot have
+ * individual foreground colors, this method does nothing. Set the
+ * foreground directly on the table instead.
+ *
+ * @param color not used
+ */
+ public void setForeground(Color color)
+ {
+ // This method does nothing. See API comments.
+ }
+
+ /**
+ * Returns the cursor for this table cell.
+ *
+ * @return the cursor for this table cell
+ */
+ public Cursor getCursor()
+ {
+ return table.getCursor();
+ }
+
+ /**
+ * Sets the cursor of the cell. Since table cells cannot have
+ * individual cursors, this method does nothing. Set the
+ * cursor directly on the table instead.
+ *
+ * @param cursor not used
+ */
+ public void setCursor(Cursor cursor)
+ {
+ // This method does nothing. See API comments.
+ }
+
+ /**
+ * Returns the font of the table cell.
+ *
+ * @return the font of the table cell
+ */
+ public Font getFont()
+ {
+ return table.getFont();
+ }
+
+ /**
+ * Sets the font of the cell. Since table cells cannot have
+ * individual fonts, this method does nothing. Set the
+ * font directly on the table instead.
+ *
+ * @param font not used
+ */
+ public void setFont(Font font)
+ {
+ // This method does nothing. See API comments.
+ }
+
+ /**
+ * Returns the font metrics for a specified font.
+ *
+ * @param font the font for which we return the metrics
+ *
+ * @return the font metrics for a specified font
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ return table.getFontMetrics(font);
+ }
+
+ /**
+ * Returns <code>true</code> if this table cell is enabled,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if this table cell is enabled,
+ * <code>false</code> otherwise
+ */
+ public boolean isEnabled()
+ {
+ return table.isEnabled();
+ }
+
+ /**
+ * Table cells cannot be disabled or enabled individually, so this method
+ * does nothing. Set the enabled flag on the table itself.
+ *
+ * @param b not used here
+ */
+ public void setEnabled(boolean b)
+ {
+ // This method does nothing. See API comments.
+ }
+
+ /**
+ * Returns <code>true</code> if this cell is visible, <code>false</code>
+ * otherwise.
+ *
+ * @return <code>true</code> if this cell is visible, <code>false</code>
+ * otherwise
+ */
+ public boolean isVisible()
+ {
+ return table.isVisible();
+ }
+
+ /**
+ * The visibility cannot be set on individual table cells, so this method
+ * does nothing. Set the visibility on the table itself.
+ *
+ * @param b not used
+ */
+ public void setVisible(boolean b)
+ {
+ // This method does nothing. See API comments.
+ }
+
+ /**
+ * Returns <code>true</code> if this table cell is currently showing on
+ * screen.
+ *
+ * @return <code>true</code> if this table cell is currently showing on
+ * screen
+ */
+ public boolean isShowing()
+ {
+ return table.isShowing();
+ }
+
+ /**
+ * Returns <code>true</code> if this table cell contains the location
+ * at <code>point</code>, <code>false</code> otherwise.
+ * <code>point</code> is interpreted as relative to the coordinate system
+ * of the table cell.
+ *
+ * @return <code>true</code> if this table cell contains the location
+ * at <code>point</code>, <code>false</code> otherwise
+ */
+ public boolean contains(Point point)
+ {
+ Rectangle cellRect = table.getCellRect(row, column, true);
+ cellRect.x = 0;
+ cellRect.y = 0;
+ return cellRect.contains(point);
+ }
+
+ /**
+ * Returns the screen location of the table cell.
+ *
+ * @return the screen location of the table cell
+ */
+ public Point getLocationOnScreen()
+ {
+ Point tableLoc = table.getLocationOnScreen();
+ Rectangle cellRect = table.getCellRect(row, column, true);
+ tableLoc.x += cellRect.x;
+ tableLoc.y += cellRect.y;
+ return tableLoc;
+ }
+
+ /**
+ * Returns the location of this cell relative to the table's bounds.
+ *
+ * @return the location of this cell relative to the table's bounds
+ */
+ public Point getLocation()
+ {
+ Rectangle cellRect = table.getCellRect(row, column, true);
+ return new Point(cellRect.x, cellRect.y);
+ }
+
+ /**
+ * The location of the table cells cannot be manipulated directly, so
+ * this method does nothing.
+ *
+ * @param point not used
+ */
+ public void setLocation(Point point)
+ {
+ // This method does nothing. See API comments.
+ }
+
+ /**
+ * Returns the bounds of the cell relative to its table.
+ *
+ * @return the bounds of the cell relative to its table
+ */
+ public Rectangle getBounds()
+ {
+ return table.getCellRect(row, column, true);
+ }
+
+ /**
+ * The bounds of the table cells cannot be manipulated directly, so
+ * this method does nothing.
+ *
+ * @param rectangle not used
+ */
+ public void setBounds(Rectangle rectangle)
+ {
+ // This method does nothing. See API comments.
+ }
+
+ /**
+ * Returns the size of the table cell.
+ *
+ * @return the size of the table cell
+ */
+ public Dimension getSize()
+ {
+ Rectangle cellRect = table.getCellRect(row, column, true);
+ return new Dimension(cellRect.width, cellRect.height);
+ }
+
+ /**
+ * The size cannot be set on table cells directly, so this method does
+ * nothing.
+ *
+ * @param dimension not used
+ */
+ public void setSize(Dimension dimension)
+ {
+ // This method does nothing. See API comments.
+ }
+
+ /**
+ * Table cells have no children, so we return <code>null</code> here.
+ *
+ * @return <code>null</code>
+ */
+ public Accessible getAccessibleAt(Point point)
+ {
+ return null;
+ }
+
+ /**
+ * Returns <code>true</code> if this table cell is focus traversable,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if this table cell is focus traversable,
+ * <code>false</code> otherwise
+ */
+ public boolean isFocusTraversable()
+ {
+ return table.isFocusable();
+ }
+
+ /**
+ * Requests that this table cell gets the keyboard focus.
+ */
+ public void requestFocus()
+ {
+ // We first set the selection models' lead selection to this cell.
+ table.getColumnModel().getSelectionModel()
+ .setLeadSelectionIndex(column);
+ table.getSelectionModel().setLeadSelectionIndex(row);
+ // Now we request that the table receives focus.
+ table.requestFocus();
+ }
+
+ /**
+ * Adds a focus listener to this cell. The focus listener is really
+ * added to the table, so there is no way to find out when an individual
+ * cell changes the focus.
+ *
+ * @param listener the focus listener to add
+ */
+ public void addFocusListener(FocusListener listener)
+ {
+ table.addFocusListener(listener);
+ }
+
+ /**
+ * Removes a focus listener from the cell. The focus listener is really
+ * removed from the table.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeFocusListener(FocusListener listener)
+ {
+ table.removeFocusListener(listener);
+ }
+
+ }
+
+ protected class AccessibleJTableModelChange
+ implements AccessibleTableModelChange
+ {
+ protected int type;
+ protected int firstRow;
+ protected int lastRow;
+ protected int firstColumn;
+ protected int lastColumn;
+
+ protected AccessibleJTableModelChange(int type, int firstRow,
+ int lastRow, int firstColumn,
+ int lastColumn)
+ {
+ this.type = type;
+ this.firstRow = firstRow;
+ this.lastRow = lastRow;
+ this.firstColumn = firstColumn;
+ this.lastColumn = lastColumn;
+ }
+
+ public int getType()
+ {
+ return type;
+ }
+
+ public int getFirstRow()
+ {
+ return firstRow;
+ }
+
+ public int getLastRow()
+ {
+ return lastRow;
+ }
+
+ public int getFirstColumn()
+ {
+ return firstColumn;
+ }
+
+ public int getLastColumn()
+ {
+ return lastColumn;
+ }
+ }
+
+ /**
+ * Creates a new <code>AccessibleJTable</code>.
+ *
+ * @since JDK1.5
+ */
+ protected AccessibleJTable()
+ {
+ getModel().addTableModelListener(this);
+ getSelectionModel().addListSelectionListener(this);
+ getColumnModel().addColumnModelListener(this);
+ getCellEditor().addCellEditorListener(this);
+ }
+
+ /**
+ * Returns the number of selected items in this table.
+ */
+ public int getAccessibleSelectionCount()
+ {
+ return getSelectedColumnCount();
+ }
+
+ public Accessible getAccessibleSelection(int i)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean isAccessibleChildSelected(int i)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void addAccessibleSelection(int i)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void removeAccessibleSelection(int i)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void clearAccessibleSelection()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void selectAllAccessibleSelection()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void valueChanged(ListSelectionEvent event)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * Receives notification when the table model changes. Depending on the
+ * type of change, this method calls {@link #tableRowsInserted} or
+ * {@link #tableRowsDeleted}.
+ *
+ * @param event the table model event
+ */
+ public void tableChanged(TableModelEvent event)
+ {
+ switch (event.getType())
+ {
+ case TableModelEvent.INSERT:
+ tableRowsInserted(event);
+ break;
+ case TableModelEvent.DELETE:
+ tableRowsDeleted(event);
+ break;
+ }
+ }
+
+ /**
+ * Receives notification when one or more rows have been inserted into the
+ * table.
+ *
+ * @param event the table model event
+ */
+ public void tableRowsInserted(TableModelEvent event)
+ {
+ // TODO: What to do here, if anything? This might be a hook method for
+ // subclasses...
+ }
+
+ /**
+ * Receives notification when one or more rows have been deleted from the
+ * table.
+ *
+ * @param event the table model event
+ */
+ public void tableRowsDeleted(TableModelEvent event)
+ {
+ // TODO: What to do here, if anything? This might be a hook method for
+ // subclasses...
+ }
+
+ public void columnAdded(TableColumnModelEvent event)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void columnMarginChanged(ChangeEvent event)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void columnMoved(TableColumnModelEvent event)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void columnRemoved(TableColumnModelEvent event)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void columnSelectionChanged(ListSelectionEvent event)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void editingCanceled(ChangeEvent event)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void editingStopped(ChangeEvent event)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * Receives notification when any of the JTable's properties changes. This
+ * is used to replace the listeners on the table's model, selection model,
+ * column model and cell editor.
+ *
+ * @param e the property change event
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ String propName = e.getPropertyName();
+ if (propName.equals("tableModel"))
+ {
+ TableModel oldModel = (TableModel) e.getOldValue();
+ oldModel.removeTableModelListener(this);
+ TableModel newModel = (TableModel) e.getNewValue();
+ newModel.addTableModelListener(this);
+ }
+ else if (propName.equals("columnModel"))
+ {
+ TableColumnModel oldModel = (TableColumnModel) e.getOldValue();
+ oldModel.removeColumnModelListener(this);
+ TableColumnModel newModel = (TableColumnModel) e.getNewValue();
+ newModel.addColumnModelListener(this);
+ }
+ else if (propName.equals("selectionModel"))
+ {
+ ListSelectionModel oldModel = (ListSelectionModel) e.getOldValue();
+ oldModel.removeListSelectionListener(this);
+ ListSelectionModel newModel = (ListSelectionModel) e.getNewValue();
+ newModel.addListSelectionListener(this);
+ }
+ else if (propName.equals("cellEditor"))
+ {
+ CellEditor oldEd = (CellEditor) e.getOldValue();
+ oldEd.removeCellEditorListener(this);
+ CellEditor newEd = (CellEditor) e.getNewValue();
+ newEd.addCellEditorListener(this);
+ }
+ }
+
+ public int getAccessibleRow(int index)
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getAccessibleColumn(int index)
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getAccessibleIndex(int r, int c)
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public Accessible getAccessibleCaption()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setAccessibleCaption(Accessible caption)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public Accessible getAccessibleSummary()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setAccessibleSummary(Accessible summary)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public int getAccessibleRowCount()
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getAccessibleColumnCount()
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public Accessible getAccessibleAt(int r, int c)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int getAccessibleRowExtentAt(int r, int c)
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getAccessibleColumnExtentAt(int r, int c)
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public AccessibleTable getAccessibleRowHeader()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setAccessibleRowHeader(AccessibleTable header)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public AccessibleTable getAccessibleColumnHeader()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setAccessibleColumnHeader(AccessibleTable header)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public Accessible getAccessibleRowDescription(int r)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setAccessibleRowDescription(int r, Accessible description)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public Accessible getAccessibleColumnDescription(int c)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setAccessibleColumnDescription(int c, Accessible description)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean isAccessibleSelected(int r, int c)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isAccessibleRowSelected(int r)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isAccessibleColumnSelected(int c)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public int[] getSelectedAccessibleRows()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int[] getSelectedAccessibleColumns()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ }
+ /**
+ * Handles property changes from the <code>TableColumn</code>s of this
+ * <code>JTable</code>.
+ *
+ * More specifically, this triggers a {@link #revalidate()} call if the
+ * preferredWidth of one of the observed columns changes.
+ */
+ class TableColumnPropertyChangeHandler implements PropertyChangeListener
+ {
+ /**
+ * Receives notification that a property of the observed TableColumns
+ * has changed.
+ *
+ * @param ev the property change event
+ */
+ public void propertyChange(PropertyChangeEvent ev)
+ {
+ if (ev.getPropertyName().equals("preferredWidth"))
+ {
+ JTableHeader header = getTableHeader();
+ TableColumn col = (TableColumn) ev.getSource();
+ header.setResizingColumn(col);
+ doLayout();
+ header.setResizingColumn(null);
+ }
+ }
+ }
/**
* A cell renderer for boolean values.
@@ -364,7 +1240,7 @@ public class JTable extends JComponent
* property when the {@link #dataModel} property is changed.
*
* @see #setModel(TableModel)
- * @see #createColumnsFromModel()
+ * @see #createDefaultColumnsFromModel()
* @see #setColumnModel(TableColumnModel)
* @see #setAutoCreateColumnsFromModel(boolean)
* @see #getAutoCreateColumnsFromModel()
@@ -480,11 +1356,6 @@ public class JTable extends JComponent
protected ListSelectionModel selectionModel;
/**
- * The accessibleContext property.
- */
- protected AccessibleContext accessibleContext;
-
- /**
* The current cell editor.
*/
protected TableCellEditor cellEditor;
@@ -492,7 +1363,7 @@ public class JTable extends JComponent
/**
* Whether or not drag-and-drop is enabled on this table.
*
- * @see #setDragEnabled()
+ * @see #setDragEnabled(boolean)
* @see #getDragEnabled()
*/
private boolean dragEnabled;
@@ -584,6 +1455,12 @@ public class JTable extends JComponent
Object oldCellValue;
/**
+ * The property handler for this table's columns.
+ */
+ TableColumnPropertyChangeHandler tableColumnPropertyChangeHandler =
+ new TableColumnPropertyChangeHandler();
+
+ /**
* Creates a new <code>JTable</code> instance.
*/
public JTable ()
@@ -643,15 +1520,28 @@ public class JTable extends JComponent
*/
public JTable (TableModel dm, TableColumnModel cm, ListSelectionModel sm)
{
- setModel(dm == null ? createDefaultDataModel() : dm);
+ boolean autoCreate = false;
+ if (cm != null)
+ setColumnModel(cm);
+ else
+ {
+ setColumnModel(createDefaultColumnModel());
+ autoCreate = true;
+ }
setSelectionModel(sm == null ? createDefaultSelectionModel() : sm);
-
- this.columnModel = cm;
+ setModel(dm == null ? createDefaultDataModel() : dm);
+ setAutoCreateColumnsFromModel(autoCreate);
initializeLocalVars();
- // The next two lines are for compliance with the JDK which starts
- // the JLists associated with a JTable with both lead selection
- // indices at 0, rather than -1 as in regular JLists
+ // The following four lines properly set the lead selection indices.
+ // After this, the UI will handle the lead selection indices.
+ // FIXME: this should probably not be necessary, if the UI is installed
+ // before the TableModel is set then the UI will handle things on its
+ // own, but certain variables need to be set before the UI can be installed
+ // so we must get the correct order for all the method calls in this
+ // constructor.
+ selectionModel.setAnchorSelectionIndex(0);
selectionModel.setLeadSelectionIndex(0);
+ columnModel.getSelectionModel().setAnchorSelectionIndex(0);
columnModel.getSelectionModel().setLeadSelectionIndex(0);
updateUI();
}
@@ -659,12 +1549,8 @@ public class JTable extends JComponent
protected void initializeLocalVars()
{
setTableHeader(createDefaultTableHeader());
- this.autoCreateColumnsFromModel = false;
- if (columnModel == null)
- {
- this.autoCreateColumnsFromModel = true;
- createColumnsFromModel();
- }
+ if (autoCreateColumnsFromModel)
+ createDefaultColumnsFromModel();
this.columnModel.addColumnModelListener(this);
this.defaultRenderersByColumnClass = new Hashtable();
@@ -754,6 +1640,7 @@ public class JTable extends JComponent
}
columnModel.addColumn(column);
+ column.addPropertyChangeListener(tableColumnPropertyChangeHandler);
}
protected void createDefaultEditors()
@@ -799,20 +1686,6 @@ public class JTable extends JComponent
return new JTableHeader(columnModel);
}
- private void createColumnsFromModel()
- {
- if (dataModel == null)
- return;
-
- TableColumnModel cm = createDefaultColumnModel();
-
- for (int i = 0; i < dataModel.getColumnCount(); ++i)
- {
- cm.addColumn(new TableColumn(i));
- }
- this.setColumnModel(cm);
- }
-
// listener support
public void columnAdded (TableColumnModelEvent event)
@@ -890,8 +1763,19 @@ public class JTable extends JComponent
if ((event.getFirstRow() ==TableModelEvent.HEADER_ROW)
&& autoCreateColumnsFromModel)
- createColumnsFromModel();
+ createDefaultColumnsFromModel();
+ // If the structure changes, we need to revalidate, since that might
+ // affect the size parameters of the JTable. Otherwise we only need
+ // to perform a repaint to update the view.
+ if (event.getType() == TableModelEvent.INSERT)
+ revalidate();
+ else if (event.getType() == TableModelEvent.DELETE)
+ {
+ if (dataModel.getRowCount() == 0)
+ clearSelection();
+ revalidate();
+ }
repaint();
}
@@ -944,8 +1828,7 @@ public class JTable extends JComponent
{
int y0 = getLocation().y;
int nrows = getRowCount();
- Dimension gap = getIntercellSpacing();
- int height = getRowHeight() + (gap == null ? 0 : gap.height);
+ int height = getRowHeight();
int y = point.y;
for (int i = 0; i < nrows; ++i)
@@ -990,10 +1873,7 @@ public class JTable extends JComponent
int y = (height + y_gap) * row;
for (int i = 0; i < column; ++i)
- {
- x += columnModel.getColumn(i).getWidth();
- x += x_gap;
- }
+ x += columnModel.getColumn(i).getWidth();
if (includeSpacing)
return new Rectangle(x, y, width, height);
@@ -1015,7 +1895,7 @@ public class JTable extends JComponent
* @return The current value of the selectedRow property
*/
public int getSelectedRow ()
- {
+ {
return selectionModel.getMinSelectionIndex();
}
@@ -1069,13 +1949,14 @@ public class JTable extends JComponent
// scroll direction.
if (orientation == SwingConstants.VERTICAL)
- return rowHeight;
+ return direction * rowHeight;
else
{
int sum = 0;
for (int i = 0; i < getColumnCount(); ++i)
sum += columnModel.getColumn(0).getWidth();
- return getColumnCount() == 0 ? 10 : sum / getColumnCount();
+ int inc = getColumnCount() == 0 ? 10 : sum / getColumnCount();
+ return direction * inc;
}
}
@@ -1656,24 +2537,29 @@ public class JTable extends JComponent
// Don't do anything if setting the current model again.
if (dataModel == m)
return;
-
+
+ TableModel oldModel = dataModel;
+
// Remove table as TableModelListener from old model.
if (dataModel != null)
dataModel.removeTableModelListener(this);
if (m != null)
{
- // Set property.
+ // Set property.
dataModel = m;
- // Add table as TableModelListener to new model.
- dataModel.addTableModelListener(this);
+ // Add table as TableModelListener to new model.
+ dataModel.addTableModelListener(this);
- // Automatically create columns.
- if (autoCreateColumnsFromModel)
- createColumnsFromModel();
+ // Automatically create columns.
+ if (autoCreateColumnsFromModel)
+ createDefaultColumnsFromModel();
}
-
+
+ // This property is bound, so we fire a property change event.
+ firePropertyChange("model", oldModel, dataModel);
+
// Repaint table.
revalidate();
repaint();
@@ -1959,7 +2845,8 @@ public class JTable extends JComponent
int average = spill / cols.length;
for (int i = 0; i < cols.length; i++)
{
- cols[i].setWidth(cols[i].getWidth() + average);
+ if (cols[i] != null)
+ cols[i].setWidth(cols[i].getWidth() + average);
}
}
@@ -2023,6 +2910,8 @@ public class JTable extends JComponent
case AUTO_RESIZE_OFF:
default:
+ int prefWidth = resizingColumn.getPreferredWidth();
+ resizingColumn.setWidth(prefWidth);
}
}
else
@@ -2258,6 +3147,8 @@ public class JTable extends JComponent
*/
public void createDefaultColumnsFromModel()
{
+ assert columnModel != null : "The columnModel must not be null.";
+
// remove existing columns
int columnIndex = columnModel.getColumnCount() - 1;
while (columnIndex >= 0)
@@ -2272,7 +3163,9 @@ public class JTable extends JComponent
{
TableColumn column = new TableColumn(c);
column.setIdentifier(dataModel.getColumnName(c));
+ column.setHeaderValue(dataModel.getColumnName(c));
columnModel.addColumn(column);
+ column.addPropertyChangeListener(tableColumnPropertyChangeHandler);
}
}
@@ -2372,4 +3265,13 @@ public class JTable extends JComponent
return editor.getTableCellEditorComponent
(this, getValueAt(row, column), isCellSelected(row, column), row, column);
}
+
+ /**
+ * This revalidates the <code>JTable</code> and queues a repaint.
+ */
+ protected void resizeAndRepaint()
+ {
+ revalidate();
+ repaint();
+ }
}
diff --git a/libjava/classpath/javax/swing/JTextArea.java b/libjava/classpath/javax/swing/JTextArea.java
index 53591ffcc3a..2fa185b6207 100644
--- a/libjava/classpath/javax/swing/JTextArea.java
+++ b/libjava/classpath/javax/swing/JTextArea.java
@@ -42,6 +42,8 @@ import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Rectangle;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleStateSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
@@ -92,6 +94,35 @@ import javax.swing.text.View;
public class JTextArea extends JTextComponent
{
/**
+ * Provides accessibility support for <code>JTextArea</code>.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ protected class AccessibleJTextArea extends AccessibleJTextComponent
+ {
+
+ /**
+ * Creates a new <code>AccessibleJTextArea</code> object.
+ */
+ protected AccessibleJTextArea()
+ {
+ super();
+ }
+
+ /**
+ * Returns the accessible state of this <code>AccessibleJTextArea</code>.
+ *
+ * @return the accessible state of this <code>AccessibleJTextArea</code>
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet state = super.getAccessibleStateSet();
+ // TODO: Figure out what state must be added here to the super's state.
+ return state;
+ }
+ }
+
+ /**
* Compatible with Sun's JDK
*/
private static final long serialVersionUID = -6141680179310439825L;
@@ -208,6 +239,8 @@ public class JTextArea extends JTextComponent
/* This shouldn't happen in theory -- but, if it does... */
throw new RuntimeException("Unexpected exception occurred.", exception);
}
+ if (toAppend != null && toAppend.length() > 0)
+ revalidate();
}
/**
@@ -312,8 +345,12 @@ public class JTextArea extends JTextComponent
{
if (columns < 0)
throw new IllegalArgumentException();
-
- this.columns = columns;
+
+ if (columns != this.columns)
+ {
+ this.columns = columns;
+ revalidate();
+ }
}
/**
@@ -337,8 +374,12 @@ public class JTextArea extends JTextComponent
{
if (rows < 0)
throw new IllegalArgumentException();
-
- this.rows = rows;
+
+ if (rows != this.rows)
+ {
+ this.rows = rows;
+ revalidate();
+ }
}
/**
@@ -547,4 +588,16 @@ public class JTextArea extends JTextComponent
return new Dimension(Math.max(reqWidth, neededWidth),
Math.max(reqHeight, neededHeight));
}
+
+ /**
+ * Returns the accessible context associated with the <code>JTextArea</code>.
+ *
+ * @return the accessible context associated with the <code>JTextArea</code>
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJTextArea();
+ return accessibleContext;
+ }
}
diff --git a/libjava/classpath/javax/swing/JTextField.java b/libjava/classpath/javax/swing/JTextField.java
index 5ae9c9f1a82..8dc2f256914 100644
--- a/libjava/classpath/javax/swing/JTextField.java
+++ b/libjava/classpath/javax/swing/JTextField.java
@@ -46,9 +46,8 @@ import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
+import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleStateSet;
-import javax.swing.text.AttributeSet;
-import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.PlainDocument;
@@ -69,15 +68,19 @@ public class JTextField extends JTextComponent
*/
protected AccessibleJTextField()
{
+ super();
}
/**
- * getAccessibleStateSet
- * @return AccessibleStateSet
+ * Returns the accessible state of this <code>AccessibleJTextField</code>.
+ *
+ * @return the accessible state of this <code>AccessibleJTextField</code>
*/
public AccessibleStateSet getAccessibleStateSet()
{
- return null;
+ AccessibleStateSet state = super.getAccessibleStateSet();
+ // TODO: Figure out what state must be added here to the super's state.
+ return state;
}
}
@@ -92,17 +95,17 @@ public class JTextField extends JTextComponent
public static final String notifyAction = "notify-field-accept";
static
- {
- actions = new Action[1];
- actions[0] = new TextAction(notifyAction)
+ {
+ actions = new Action[1];
+ actions[0] = new TextAction(notifyAction)
{
- public void actionPerformed(ActionEvent event)
- {
- JTextField textField = (JTextField) event.getSource();
- textField.fireActionPerformed();
- }
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextField textField = (JTextField) event.getSource();
+ textField.fireActionPerformed();
+ }
};
- }
+ }
private int columns;
private int align;
@@ -117,6 +120,11 @@ public class JTextField extends JTextComponent
private PropertyChangeListener actionPropertyChangeListener;
/**
+ * The horizontal visibility of the textfield.
+ */
+ private BoundedRangeModel horizontalVisibility;
+
+ /**
* Creates a new instance of <code>JTextField</code>.
*/
public JTextField()
@@ -172,9 +180,9 @@ public class JTextField extends JTextComponent
{
if (columns < 0)
throw new IllegalArgumentException();
-
+
this.columns = columns;
-
+
setDocument(doc == null ? createDefaultModel() : doc);
if (text != null)
@@ -182,6 +190,9 @@ public class JTextField extends JTextComponent
// default value for alignment
align = LEADING;
+
+ // Initialize the horizontal visibility model.
+ horizontalVisibility = new DefaultBoundedRangeModel();
}
/**
@@ -192,15 +203,9 @@ public class JTextField extends JTextComponent
*/
protected Document createDefaultModel()
{
- // subclassed to swallow newlines
- return new PlainDocument() {
- public void insertString(int offset, String str, AttributeSet a)
- throws BadLocationException
- {
- if (str != null && str.indexOf('\n') == -1)
- super.insertString(offset, str, a);
- }
- };
+ PlainDocument doc = new PlainDocument();
+ doc.putProperty("filterNewlines", Boolean.TRUE);
+ return doc;
}
/**
@@ -268,6 +273,11 @@ public class JTextField extends JTextComponent
return columns;
}
+ /**
+ * Sets the number of columns and then invalidates the layout.
+ * @param columns the number of columns
+ * @throws IllegalArgumentException if columns < 0
+ */
public void setColumns(int columns)
{
if (columns < 0)
@@ -275,16 +285,31 @@ public class JTextField extends JTextComponent
this.columns = columns;
invalidate();
+ //FIXME: do we need this repaint call?
repaint();
}
+ /**
+ * Returns the horizontal alignment, which is one of: JTextField.LEFT,
+ * JTextField.CENTER, JTextField.RIGHT, JTextField.LEADING,
+ * JTextField.TRAILING.
+ * @return the horizontal alignment
+ */
public int getHorizontalAlignment()
{
return align;
}
+ /**
+ * Sets the horizontal alignment of the text. Calls invalidate and repaint
+ * and fires a property change event.
+ * @param newAlign must be one of: JTextField.LEFT, JTextField.CENTER,
+ * JTextField.RIGHT, JTextField.LEADING, JTextField.TRAILING.
+ * @throws IllegalArgumentException if newAlign is not one of the above.
+ */
public void setHorizontalAlignment(int newAlign)
{
+ //FIXME: should throw an IllegalArgumentException if newAlign is invalid
if (align == newAlign)
return;
@@ -295,12 +320,20 @@ public class JTextField extends JTextComponent
repaint();
}
+ /**
+ * Sets the current font and revalidates so the font will take effect.
+ */
public void setFont(Font newFont)
{
super.setFont(newFont);
revalidate();
}
+ /**
+ * Returns the preferred size. If there is a non-zero number of columns,
+ * this is the number of columns multiplied by the column width, otherwise
+ * it returns super.getPreferredSize().
+ */
public Dimension getPreferredSize()
{
Dimension size = super.getPreferredSize();
@@ -318,6 +351,7 @@ public class JTextField extends JTextComponent
*/
public int getScrollOffset()
{
+ //FIXME: this should return horizontalVisibility's value
return scrollOffset;
}
@@ -328,9 +362,15 @@ public class JTextField extends JTextComponent
*/
public void setScrollOffset(int offset)
{
+ //FIXME: this should actualy scroll the field if needed
scrollOffset = offset;
}
+ /**
+ * Returns the set of Actions that are commands for the editor.
+ * This is the actions supported by this editor plus the actions
+ * of the UI (returned by JTextComponent.getActions()).
+ */
public Action[] getActions()
{
return TextAction.augmentList(super.getActions(), actions);
@@ -364,26 +404,27 @@ public class JTextField extends JTextComponent
if (action != null)
{
- removeActionListener(action);
- action.removePropertyChangeListener(actionPropertyChangeListener);
- actionPropertyChangeListener = null;
+ removeActionListener(action);
+ action.removePropertyChangeListener(actionPropertyChangeListener);
+ actionPropertyChangeListener = null;
}
-
+
Action oldAction = action;
action = newAction;
if (action != null)
{
- addActionListener(action);
- actionPropertyChangeListener =
- createActionPropertyChangeListener(action);
- action.addPropertyChangeListener(actionPropertyChangeListener);
+ addActionListener(action);
+ actionPropertyChangeListener = createActionPropertyChangeListener(action);
+ action.addPropertyChangeListener(actionPropertyChangeListener);
}
-
+
+ //FIXME: is this a hack? The horizontal alignment hasn't changed
firePropertyChange("horizontalAlignment", oldAction, newAction);
}
/**
+ * Sets the command string used in action events.
* @since 1.3
*/
public void setActionCommand(String command)
@@ -397,45 +438,79 @@ public class JTextField extends JTextComponent
protected PropertyChangeListener createActionPropertyChangeListener(Action action)
{
return new PropertyChangeListener()
+ {
+ public void propertyChange(PropertyChangeEvent event)
{
- public void propertyChange(PropertyChangeEvent event)
- {
- // Update properties "action" and "horizontalAlignment".
- String name = event.getPropertyName();
-
- if (name.equals("enabled"))
- {
- boolean enabled = ((Boolean) event.getNewValue()).booleanValue();
- JTextField.this.setEnabled(enabled);
- }
- else if (name.equals(Action.SHORT_DESCRIPTION))
- {
- JTextField.this.setToolTipText((String) event.getNewValue());
- }
- }
- };
+ // Update properties "action" and "horizontalAlignment".
+ String name = event.getPropertyName();
+
+ if (name.equals("enabled"))
+ {
+ boolean enabled = ((Boolean) event.getNewValue()).booleanValue();
+ JTextField.this.setEnabled(enabled);
+ }
+ else if (name.equals(Action.SHORT_DESCRIPTION))
+ {
+ JTextField.this.setToolTipText((String) event.getNewValue());
+ }
+ }
+ };
}
/**
+ *
* @since 1.3
*/
protected void configurePropertiesFromAction(Action action)
{
if (action != null)
{
- setEnabled(action.isEnabled());
- setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION));
+ setEnabled(action.isEnabled());
+ setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION));
}
else
{
- setEnabled(true);
- setToolTipText(null);
+ setEnabled(true);
+ setToolTipText(null);
}
}
+ /**
+ * Returns the column width, which is the width of the character m
+ * for the font in use.
+ * @return the width of the character m for the font in use.
+ */
protected int getColumnWidth()
{
FontMetrics metrics = getToolkit().getFontMetrics(getFont());
return metrics.charWidth('m');
}
+
+ /**
+ * Returns the accessible context associated with the <code>JTextField</code>.
+ *
+ * @return the accessible context associated with the <code>JTextField</code>
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJTextField();
+ return accessibleContext;
+ }
+
+ /**
+ * Returns the bounded range model that describes the horizontal visibility
+ * of the text field in the case when the text does not fit into the
+ * available space. The actual values of this model are managed by the look
+ * and feel implementation.
+ *
+ * @return the bounded range model that describes the horizontal visibility
+ */
+ public BoundedRangeModel getHorizontalVisibility()
+ {
+ // TODO: The real implementation of this property is still missing.
+ // However, this is not done in JTextField but must instead be handled in
+ // javax.swing.text.FieldView.
+ return horizontalVisibility;
+ }
}
diff --git a/libjava/classpath/javax/swing/JTextPane.java b/libjava/classpath/javax/swing/JTextPane.java
index 80632fff38e..1f5b99e43c5 100644
--- a/libjava/classpath/javax/swing/JTextPane.java
+++ b/libjava/classpath/javax/swing/JTextPane.java
@@ -39,8 +39,6 @@ exception statement from your version. */
package javax.swing;
import java.awt.Component;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
@@ -49,7 +47,6 @@ import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import javax.swing.text.Element;
import javax.swing.text.MutableAttributeSet;
-import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyledDocument;
import javax.swing.text.StyledEditorKit;
@@ -106,7 +103,7 @@ public class JTextPane
* @throws IllegalArgumentException if <code>document</code> is not an
* instance of <code>StyledDocument</code>
*
- * @see {@link #setStyledDocument}
+ * @see #setStyledDocument
*/
public void setDocument(Document document)
{
@@ -120,7 +117,7 @@ public class JTextPane
/**
* Returns the {@link StyledDocument} that is the content model for
* this <code>JTextPane</code>. This is a typed wrapper for
- * {@link #getDocument}.
+ * {@link #getDocument()}.
*
* @return the content model of this <code>JTextPane</code>
*/
@@ -179,8 +176,6 @@ public class JTextPane
doc.setCharacterAttributes(start, contentLength, getInputAttributes(),
true);
- // Set dot to new position.
- setCaretPosition(start + contentLength);
}
catch (BadLocationException e)
{
@@ -300,7 +295,7 @@ public class JTextPane
* @param replace if <code>true</code>, the attributes of the current
* selection are overridden, otherwise they are merged
*
- * @see {@link #getInputAttributes}
+ * @see #getInputAttributes
*/
public void setCharacterAttributes(AttributeSet attribute,
boolean replace)
diff --git a/libjava/classpath/javax/swing/JToggleButton.java b/libjava/classpath/javax/swing/JToggleButton.java
index 25d67f59e4f..077e5adb887 100644
--- a/libjava/classpath/javax/swing/JToggleButton.java
+++ b/libjava/classpath/javax/swing/JToggleButton.java
@@ -129,7 +129,7 @@ public class JToggleButton extends AbstractButton implements Accessible
* Compatible with Sun's JDK.
*/
private static final long serialVersionUID = -1589950750899943974L;
-
+
/**
* Sets the pressed state of the button. The selected state
* of the button also changes follwing the button being pressed.
@@ -174,8 +174,27 @@ public class JToggleButton extends AbstractButton implements Accessible
ActionEvent.ACTION_PERFORMED,
actionCommand));
}
-
}
+
+ /**
+ * Checks if the button is selected.
+ *
+ * @returns true if the button is selected
+ */
+ public boolean isSelected()
+ {
+ return super.isSelected();
+ }
+
+ /**
+ * Sets the selected state of the button.
+ *
+ * @param b true if button is selected
+ */
+ public void setSelected(boolean b)
+ {
+ super.setSelected(b);
+ }
}
/**
@@ -276,6 +295,7 @@ public class JToggleButton extends AbstractButton implements Accessible
setModel(new ToggleButtonModel());
model.setSelected(selected);
+ setAlignmentX(LEFT_ALIGNMENT);
}
/**
diff --git a/libjava/classpath/javax/swing/JToolBar.java b/libjava/classpath/javax/swing/JToolBar.java
index 649919e0618..a508ee6d8e7 100644
--- a/libjava/classpath/javax/swing/JToolBar.java
+++ b/libjava/classpath/javax/swing/JToolBar.java
@@ -68,6 +68,8 @@ public class JToolBar extends JComponent implements SwingConstants, Accessible
/**
* AccessibleJToolBar
*/
+ // FIXME: This inner class is a complete stub and must be implemented
+ // properly.
protected class AccessibleJToolBar extends AccessibleJComponent
{
/** DOCUMENT ME! */
@@ -78,6 +80,7 @@ public class JToolBar extends JComponent implements SwingConstants, Accessible
*/
protected AccessibleJToolBar()
{
+ // Nothing to do here.
}
/**
@@ -749,7 +752,6 @@ public class JToolBar extends JComponent implements SwingConstants, Accessible
{
AbstractButton b = (AbstractButton) component;
b.setRolloverEnabled(rollover);
- b.updateUI();
}
} // addImpl()
diff --git a/libjava/classpath/javax/swing/JToolTip.java b/libjava/classpath/javax/swing/JToolTip.java
index 8d774782780..6bc3e3fa287 100644
--- a/libjava/classpath/javax/swing/JToolTip.java
+++ b/libjava/classpath/javax/swing/JToolTip.java
@@ -58,6 +58,8 @@ public class JToolTip extends JComponent implements Accessible
/**
* DOCUMENT ME!
*/
+ // FIXME: This inner class is a complete stub and must be implemented
+ // properly.
protected class AccessibleJToolTip extends AccessibleJComponent
{
private static final long serialVersionUID = -6222548177795408476L;
@@ -67,6 +69,7 @@ public class JToolTip extends JComponent implements Accessible
*/
protected AccessibleJToolTip()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/JTree.java b/libjava/classpath/javax/swing/JTree.java
index bb24c7a459d..4422a193396 100644
--- a/libjava/classpath/javax/swing/JTree.java
+++ b/libjava/classpath/javax/swing/JTree.java
@@ -37,16 +37,32 @@ exception statement from your version. */
package javax.swing;
+import java.awt.Color;
+import java.awt.Cursor;
import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Point;
import java.awt.Rectangle;
+import java.awt.event.FocusListener;
+import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
+import java.util.Locale;
import java.util.Vector;
import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleComponent;
import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleSelection;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleText;
+import javax.accessibility.AccessibleValue;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeModelEvent;
@@ -57,7 +73,6 @@ import javax.swing.event.TreeWillExpandListener;
import javax.swing.plaf.TreeUI;
import javax.swing.text.Position;
import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.ExpandVetoException;
@@ -68,1754 +83,2830 @@ import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
-public class JTree
- extends JComponent
- implements Scrollable, Accessible
+public class JTree extends JComponent implements Scrollable, Accessible
{
- /**
- * Listens to the model of the JTree and updates the property
- * <code>expandedState</code> if nodes are removed or changed.
- */
- protected class TreeModelHandler
- implements
- TreeModelListener
- {
-
- /**
- * Creates a new instance of TreeModelHandler.
- */
- protected TreeModelHandler()
- {
- }
-
- /**
- * Notifies when a node has changed in some ways. This does not include
- * that a node has changed its location or changed it's children. It
- * only means that some attributes of the node have changed that might
- * affect its presentation.
- *
- * This method is called after the actual change occured.
- *
- * @param ev the TreeModelEvent describing the change
- */
- public void treeNodesChanged(TreeModelEvent ev)
- {
- // nothing to do here
- }
-
- /**
- * Notifies when a node is inserted into the tree.
- *
- * This method is called after the actual change occured.
- *
- * @param ev the TreeModelEvent describing the change
- */
- public void treeNodesInserted(TreeModelEvent ev)
- {
- // nothing to do here
- }
-
- /**
- * Notifies when a node is removed from the tree.
- *
- * This method is called after the actual change occured.
- *
- * @param ev the TreeModelEvent describing the change
- */
- public void treeNodesRemoved(TreeModelEvent ev)
- {
- // TODO: The API docs suggest that this method should do something
- // but I cannot really see what has to be done here ...
- }
-
- /**
- * Notifies when the structure of the tree is changed.
- *
- * This method is called after the actual change occured.
- *
- * @param ev the TreeModelEvent describing the change
- */
- public void treeStructureChanged(TreeModelEvent ev)
- {
- // set state of new path
- TreePath path = ev.getTreePath();
- setExpandedState(path, isExpanded(path));
- }
- } // TreeModelHandler
-
- /**
- * This redirects TreeSelectionEvents and rewrites the source of it to be
- * this JTree. This is typically done when the tree model generates an
- * event, but the JTree object associated with that model should be listed
- * as the actual source of the event.
- */
- protected class TreeSelectionRedirector
- implements
- TreeSelectionListener,
- Serializable
- {
- /** The serial version UID. */
- private static final long serialVersionUID = -3505069663646241664L;
-
- /**
- * Creates a new instance of TreeSelectionRedirector
- */
- protected TreeSelectionRedirector()
- {
- }
-
- /**
- * Notifies when the tree selection changes.
- *
- * @param ev the TreeSelectionEvent that describes the change
- */
- public void valueChanged(TreeSelectionEvent ev)
- {
- TreeSelectionEvent rewritten = (TreeSelectionEvent) ev
- .cloneWithSource(JTree.this);
- fireValueChanged(rewritten);
- JTree.this.repaint();
- }
- } // TreeSelectionRedirector
-
- /**
- * A TreeModel that does not allow anything to be selected.
+
+ /**
+ * This class implements accessibility support for the JTree class. It
+ * provides an implementation of the Java Accessibility API appropriate
+ * to tree user-interface elements.
+ */
+ protected class AccessibleJTree extends JComponent.AccessibleJComponent
+ implements AccessibleSelection, TreeSelectionListener, TreeModelListener,
+ TreeExpansionListener
+ {
+
+ /**
+ * This class implements accessibility support for the JTree child. It provides
+ * an implementation of the Java Accessibility API appropriate to tree nodes.
+ */
+ protected class AccessibleJTreeNode extends AccessibleContext
+ implements Accessible, AccessibleComponent, AccessibleSelection,
+ AccessibleAction
+ {
+
+ private JTree tree;
+ private TreePath tp;
+ private Accessible acc;
+ private AccessibleStateSet states;
+ private Vector selectionList;
+ private Vector actionList;
+ private TreeModel mod;
+ private Cursor cursor;
+
+ /**
+ * Constructs an AccessibleJTreeNode
+ *
+ * @param t - the current tree
+ * @param p - the current path to be dealt with
+ * @param ap - the accessible object to use
+ */
+ public AccessibleJTreeNode(JTree t, TreePath p, Accessible ap)
+ {
+ states = new AccessibleStateSet();
+ selectionList = new Vector();
+ actionList = new Vector();
+ mod = tree.getModel();
+ cursor = JTree.this.getCursor();
+
+ tree = t;
+ tp = p;
+ acc = ap;
+
+ // Add all the children of this path that may already be
+ // selected to the selection list.
+ TreePath[] selected = tree.getSelectionPaths();
+ for (int i = 0; i < selected.length; i++)
+ {
+ TreePath sel = selected[i];
+ if ((sel.getParentPath()).equals(tp))
+ selectionList.add(sel);
+ }
+
+ // Add all the actions available for a node to
+ // the action list.
+ actionList.add("EXPAND");
+ actionList.add("COLLAPSE");
+ actionList.add("EDIT");
+ actionList.add("SELECT");
+ actionList.add("DESELECT");
+ }
+
+ /**
+ * Adds the specified selected item in the object to the object's
+ * selection.
+ *
+ * @param i - the i-th child of this node.
+ */
+ public void addAccessibleSelection(int i)
+ {
+ if (mod != null)
+ {
+ Object child = mod.getChild(tp.getLastPathComponent(), i);
+ if (child != null)
+ {
+ if (!states.contains(AccessibleState.MULTISELECTABLE))
+ clearAccessibleSelection();
+ selectionList.add(child);
+ tree.addSelectionPath(tp.pathByAddingChild(child));
+ }
+ }
+ }
+
+ /**
+ * Adds the specified focus listener to receive focus events
+ * from this component.
+ *
+ * @param l - the new focus listener
+ */
+ public void addFocusListener(FocusListener l)
+ {
+ tree.addFocusListener(l);
+ }
+
+ /**
+ * Add a PropertyChangeListener to the listener list.
+ *
+ * @param l - the new property change listener
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Clears the selection in the object, so that nothing in the
+ * object is selected.
+ */
+ public void clearAccessibleSelection()
+ {
+ selectionList.clear();
+ }
+
+ /**
+ * Checks whether the specified point is within this object's
+ * bounds, where the point's x and y coordinates are defined to be
+ * relative to the coordinate system of the object.
+ *
+ * @param p - the point to check
+ * @return true if p is in the bounds
+ */
+ public boolean contains(Point p)
+ {
+ return getBounds().contains(p);
+ }
+
+ /**
+ * Perform the specified Action on the tree node.
+ *
+ * @param i - the i-th action to perform
+ * @return true if the the action was performed; else false.
+ */
+ public boolean doAccessibleAction(int i)
+ {
+ if (i >= actionList.size() || i < 0)
+ return false;
+
+ if (actionList.get(i).equals("EXPAND"))
+ tree.expandPath(tp);
+ else if (actionList.get(i).equals("COLLAPSE"))
+ tree.collapsePath(tp);
+ else if (actionList.get(i).equals("SELECT"))
+ tree.addSelectionPath(tp);
+ else if (actionList.get(i).equals("DESELECT"))
+ tree.removeSelectionPath(tp);
+ else if (actionList.get(i).equals("EDIT"))
+ tree.startEditingAtPath(tp);
+ else
+ return false;
+ return true;
+ }
+
+ /**
+ * Get the AccessibleAction associated with this object.
+ *
+ * @return the action
+ */
+ public AccessibleAction getAccessibleAction()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the number of accessible actions available in this tree node.
+ *
+ * @return the number of actions
+ */
+ public int getAccessibleActionCount()
+ {
+ return actionList.size();
+ }
+
+ /**
+ * Return a description of the specified action of the tree node.
+ *
+ * @param i - the i-th action's description
+ * @return a description of the action
+ */
+ public String getAccessibleActionDescription(int i)
+ {
+ if (i < 0 || i >= actionList.size())
+ return (actionList.get(i)).toString();
+ return super.getAccessibleDescription();
+ }
+
+ /**
+ * Returns the Accessible child, if one exists, contained at the
+ * local coordinate Point.
+ *
+ * @param p - the point of the accessible
+ * @return the accessible at point p if it exists
+ */
+ public Accessible getAccessibleAt(Point p)
+ {
+ TreePath acc = tree.getClosestPathForLocation(p.x, p.y);
+ if (acc != null)
+ return new AccessibleJTreeNode(tree, acc, this);
+ return null;
+ }
+
+ /**
+ * Return the specified Accessible child of the object.
+ *
+ * @param i - the i-th child of the current path
+ * @return the child if it exists
+ */
+ public Accessible getAccessibleChild(int i)
+ {
+ if (mod != null)
+ {
+ Object child = mod.getChild(tp.getLastPathComponent(), i);
+ if (child != null)
+ return new AccessibleJTreeNode(tree, tp.pathByAddingChild(child),
+ acc);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the number of accessible children in the object.
+ *
+ * @return the number of children the current node has
+ */
+ public int getAccessibleChildrenCount()
+ {
+ TreeModel mod = getModel();
+ if (mod != null)
+ return mod.getChildCount(tp.getLastPathComponent());
+ return 0;
+ }
+
+ /**
+ * Get the AccessibleComponent associated with this object.
+ *
+ * @return the accessible component if it is supported.
+ */
+ public AccessibleComponent getAccessibleComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Get the AccessibleContext associated with this tree node.
+ *
+ * @return an instance of this class
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return this;
+ }
+
+ /**
+ * Get the accessible description of this object.
+ *
+ * @return the accessible description
+ */
+ public String getAccessibleDescription()
+ {
+ return super.getAccessibleDescription();
+ }
+
+ /**
+ * Get the index of this object in its accessible parent.
+ *
+ * @return the index of this in the parent.
+ */
+ public int getAccessibleIndexInParent()
+ {
+ AccessibleContext parent = getAccessibleParent().getAccessibleContext();
+ if (parent != null)
+ for (int i = 0; i < parent.getAccessibleChildrenCount(); i++)
+ {
+ if ((parent.getAccessibleChild(i)).equals(this))
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Get the accessible name of this object.
+ *
+ * @return the accessible name
+ */
+ public String getAccessibleName()
+ {
+ return super.getAccessibleName();
+ }
+
+ /**
+ * Get the Accessible parent of this object.
+ *
+ * @return the accessible parent if it exists.
+ */
+ public Accessible getAccessibleParent()
+ {
+ return super.getAccessibleParent();
+ }
+
+ /**
+ * Get the role of this object.
+ *
+ * @return the accessible role
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleJTree.this.getAccessibleRole();
+ }
+
+ /**
+ * Get the AccessibleSelection associated with this object if one exists.
+ *
+ * @return the accessible selection for this.
+ */
+ public AccessibleSelection getAccessibleSelection()
+ {
+ return this;
+ }
+
+ /**
+ * Returns an Accessible representing the specified selected item
+ * in the object.
+ *
+ * @return the accessible representing a certain selected item.
+ */
+ public Accessible getAccessibleSelection(int i)
+ {
+ if (i > 0 && i < getAccessibleSelectionCount())
+ return new AccessibleJTreeNode(tree,
+ tp.pathByAddingChild(selectionList.get(i)), acc);
+ return null;
+ }
+
+ /**
+ * Returns the number of items currently selected.
+ *
+ * @return the number of items selected.
+ */
+ public int getAccessibleSelectionCount()
+ {
+ return selectionList.size();
+ }
+
+ /**
+ * Get the state set of this object.
+ *
+ * @return the state set for this object
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ if (isVisible())
+ states.add(AccessibleState.VISIBLE);
+ if (tree.isCollapsed(tp))
+ states.add(AccessibleState.COLLAPSED);
+ if (tree.isEditable())
+ states.add(AccessibleState.EDITABLE);
+ if (mod != null &&
+ !mod.isLeaf(tp.getLastPathComponent()))
+ states.add(AccessibleState.EXPANDABLE);
+ if (tree.isExpanded(tp))
+ states.add(AccessibleState.EXPANDED);
+ if (isFocusable())
+ states.add(AccessibleState.FOCUSABLE);
+ if (hasFocus())
+ states.add(AccessibleState.FOCUSED);
+ if (tree.getSelectionModel().getSelectionMode() !=
+ TreeSelectionModel.SINGLE_TREE_SELECTION)
+ states.add(AccessibleState.MULTISELECTABLE);
+ if (tree.isOpaque())
+ states.add(AccessibleState.OPAQUE);
+ if (tree.isPathSelected(tp))
+ states.add(AccessibleState.SELECTED);
+ if (isShowing())
+ states.add(AccessibleState.SHOWING);
+
+ states.add(AccessibleState.SELECTABLE);
+ return states;
+ }
+
+ /**
+ * Get the AccessibleText associated with this object if one exists.
+ *
+ * @return the accessible text
+ */
+ public AccessibleText getAccessibleText()
+ {
+ return super.getAccessibleText();
+ }
+
+ /**
+ * Get the AccessibleValue associated with this object if one exists.
+ *
+ * @return the accessible value if it exists
+ */
+ public AccessibleValue getAccessibleValue()
+ {
+ return super.getAccessibleValue();
+ }
+
+ /**
+ * Get the background color of this object.
+ *
+ * @return the color of the background.
+ */
+ public Color getBackground()
+ {
+ return tree.getBackground();
+ }
+
+ /**
+ * Gets the bounds of this object in the form of a Rectangle object.
+ *
+ * @return the bounds of the current node.
+ */
+ public Rectangle getBounds()
+ {
+ return tree.getPathBounds(tp);
+ }
+
+ /**
+ * Gets the Cursor of this object.
+ *
+ * @return the cursor for the current node
+ */
+ public Cursor getCursor()
+ {
+ return cursor;
+ }
+
+ /**
+ * Gets the Font of this object.
+ *
+ * @return the font for the current node
+ */
+ public Font getFont()
+ {
+ return tree.getFont();
+ }
+
+ /**
+ * Gets the FontMetrics of this object.
+ *
+ * @param f - the current font.
+ * @return the font metrics for the given font.
+ */
+ public FontMetrics getFontMetrics(Font f)
+ {
+ return tree.getFontMetrics(f);
+ }
+
+ /**
+ * Get the foreground color of this object.
+ *
+ * @return the foreground for this object.
+ */
+ public Color getForeground()
+ {
+ return tree.getForeground();
+ }
+
+ /**
+ * Gets the locale of the component.
+ *
+ * @return the locale of the component.
+ */
+ public Locale getLocale()
+ {
+ return tree.getLocale();
+ }
+
+ /**
+ * Gets the location of the object relative to the
+ * parent in the form of a point specifying the object's
+ * top-left corner in the screen's coordinate space.
+ *
+ * @return the location of the current node.
+ */
+ public Point getLocation()
+ {
+ return getLocationInJTree();
+ }
+
+ /**
+ * Returns the location in the tree.
+ *
+ * @return the location in the JTree.
+ */
+ protected Point getLocationInJTree()
+ {
+ Rectangle bounds = tree.getPathBounds(tp);
+ return new Point(bounds.x, bounds.y);
+ }
+
+ /**
+ * Returns the location of the object on the screen.
+ *
+ * @return the location of the object on the screen.
+ */
+ public Point getLocationOnScreen()
+ {
+ Point loc = getLocation();
+ SwingUtilities.convertPointToScreen(loc, tree);
+ return loc;
+ }
+
+ /**
+ * Returns the size of this object in the form of a Dimension object.
+ *
+ * @return the size of the object
+ */
+ public Dimension getSize()
+ {
+ Rectangle b = getBounds();
+ return b.getSize();
+ }
+
+ /**
+ * Returns true if the current child of this object is selected.
+ *
+ * @param i - the child of the current node
+ * @return true if the child is selected.
+ */
+ public boolean isAccessibleChildSelected(int i)
+ {
+ Object child = mod.getChild(tp.getLastPathComponent(), i);
+ if (child != null)
+ return tree.isPathSelected(tp.pathByAddingChild(child));
+ return false;
+ }
+
+ /**
+ * Determines if the object is enabled.
+ *
+ * @return true if the tree is enabled
+ */
+ public boolean isEnabled()
+ {
+ return tree.isEnabled();
+ }
+
+ /**
+ * Returns whether this object can accept focus or not.
+ *
+ * @return true, it is always focus traversable
+ */
+ public boolean isFocusTraversable()
+ {
+ return true;
+ }
+
+ /**
+ * Determines if the object is showing.
+ *
+ * @return true if the object is visible and the
+ * parent is visible.
+ */
+ public boolean isShowing()
+ {
+ return isVisible() && tree.isShowing();
+ }
+
+ /**
+ * Determines if the object is visible.
+ *
+ * @return true if the object is visible.
+ */
+ public boolean isVisible()
+ {
+ return tree.isVisible(tp);
+ }
+
+ /**
+ * Removes the specified selected item in the object from the
+ * object's selection.
+ *
+ * @param i - the specified item to remove
+ */
+ public void removeAccessibleSelection(int i)
+ {
+ if (mod != null)
+ {
+ Object child = mod.getChild(tp.getLastPathComponent(), i);
+ if (child != null)
+ {
+ if (!states.contains(AccessibleState.MULTISELECTABLE))
+ clearAccessibleSelection();
+ if (selectionList.contains(child))
+ {
+ selectionList.remove(child);
+ tree.removeSelectionPath(tp.pathByAddingChild(child));
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes the specified focus listener so it no longer receives focus
+ * events from this component.
+ *
+ * @param l - the focus listener to remove
+ */
+ public void removeFocusListener(FocusListener l)
+ {
+ tree.removeFocusListener(l);
+ }
+
+ /**
+ * Remove a PropertyChangeListener from the listener list.
+ *
+ * @param l - the property change listener to remove.
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Requests focus for this object.
+ */
+ public void requestFocus()
+ {
+ tree.requestFocus();
+ }
+
+ /**
+ * Causes every selected item in the object to be selected if the object
+ * supports multiple selections.
+ */
+ public void selectAllAccessibleSelection()
+ {
+ Object parent = tp.getLastPathComponent();
+ if (mod != null)
+ {
+ for (int i = 0; i < mod.getChildCount(parent); i++)
+ {
+ Object child = mod.getChild(parent, i);
+ if (child != null)
+ {
+ if (!states.contains(AccessibleState.MULTISELECTABLE))
+ clearAccessibleSelection();
+ if (selectionList.contains(child))
+ {
+ selectionList.add(child);
+ tree.addSelectionPath(tp.pathByAddingChild(child));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Set the accessible description of this object.
+ *
+ * @param s - the string to set the accessible description to.
+ */
+ public void setAccessibleDescription(String s)
+ {
+ super.setAccessibleDescription(s);
+ }
+
+ /**
+ * Set the localized accessible name of this object.
+ *
+ * @param s - the string to set the accessible name to.
+ */
+ public void setAccessibleName(String s)
+ {
+ super.setAccessibleName(s);
+ }
+
+ /**
+ * Set the background color of this object.
+ *
+ * @param c - the color to set the background to.
+ */
+ public void setBackground(Color c)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Sets the bounds of this object in the form of a Rectangle object.
+ *
+ * @param r - the bounds to set the object o
+ */
+ public void setBounds(Rectangle r)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Sets the Cursor of this object.
+ *
+ * @param c - the new cursor
+ */
+ public void setCursor(Cursor c)
+ {
+ cursor = c;
+ }
+
+ /**
+ * Sets the enabled state of the object.
+ *
+ * @param b - boolean to enable or disable object
+ */
+ public void setEnabled(boolean b)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Sets the Font of this object.
+ *
+ * @param f - the new font.
+ */
+ public void setFont(Font f)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Sets the foreground color of this object.
+ *
+ * @param c - the new foreground color.
+ */
+ public void setForeground(Color c)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Sets the location of the object relative to the parent.
+ *
+ * @param p - the new location for the object.
+ */
+ public void setLocation(Point p)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Resizes this object so that it has width and height.
+ *
+ * @param d - the new size for the object.
+ */
+ public void setSize(Dimension d)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Sets the visible state of the object.
+ *
+ * @param b - sets the objects visibility.
+ */
+ public void setVisible(boolean b)
+ {
+ // Nothing to do here.
+ }
+ }
+
+ /**
+ * Constructor
+ */
+ public AccessibleJTree()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Adds the specified selected item in the object to the object's selection.
+ *
+ * @param i - the row to add to the tree's selection
+ */
+ public void addAccessibleSelection(int i)
+ {
+ addSelectionInterval(i, i);
+ }
+
+ /**
+ * Clears the selection in the object, so that nothing in the object is selected.
+ */
+ public void clearAccessibleSelection()
+ {
+ clearSelection();
+ }
+
+ /**
+ * Fire a visible data property change notification.
+ */
+ public void fireVisibleDataPropertyChange()
+ {
+ treeDidChange();
+ }
+
+ /**
+ * Returns the Accessible child, if one exists, contained at the local
+ * coordinate Point.
+ *
+ * @param p - the point of the accessible to get.
+ * @return the accessible at point p.
+ */
+ public Accessible getAccessibleAt(Point p)
+ {
+ TreePath tp = getClosestPathForLocation(p.x, p.y);
+ if (tp != null)
+ return new AccessibleJTreeNode(JTree.this, tp, null);
+ return null;
+ }
+
+ /**
+ * Return the nth Accessible child of the object.
+ *
+ * @param i - the accessible child to get
+ * @return the i-th child
+ */
+ public Accessible getAccessibleChild(int i)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the number of top-level children nodes of this JTree.
+ *
+ * @return the number of top-level children
+ */
+ public int getAccessibleChildrenCount()
+ {
+ TreeModel model = getModel();
+ if (model != null)
+ return model.getChildCount(model.getRoot());
+ return 0;
+ }
+
+ /**
+ * Get the index of this object in its accessible parent.
+ *
+ * @return the index of this object.
+ */
+ public int getAccessibleIndexInParent()
+ {
+ return 0;
+ }
+
+ /**
+ * Get the role of this object.
+ *
+ * @return the role of this object
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.TREE;
+ }
+
+ /**
+ * Get the AccessibleSelection associated with this object.
+ *
+ * @return the accessible selection of the tree
+ */
+ public AccessibleSelection getAccessibleSelection()
+ {
+ TreeModel mod = getModel();
+ if (mod != null)
+ return (new AccessibleJTreeNode(JTree.this,
+ new TreePath(mod.getRoot()), null)).getAccessibleSelection();
+ return null;
+ }
+
+ /**
+ * Returns an Accessible representing the specified selected item in the object.
+ *
+ * @return the i-th accessible in the selection
+ */
+ public Accessible getAccessibleSelection(int i)
+ {
+ TreeModel mod = getModel();
+ if (mod != null)
+ return (new AccessibleJTreeNode(JTree.this,
+ new TreePath(mod.getRoot()), null)).getAccessibleSelection(i);
+ return null;
+ }
+
+ /**
+ * Returns the number of items currently selected.
+ *
+ * @return the number of selected accessibles.
+ */
+ public int getAccessibleSelectionCount()
+ {
+ return getSelectionCount();
+ }
+
+ /**
+ * Returns true if the current child of this object is selected.
+ *
+ * @param i - the child of this object
+ * @return true if the i-th child is selected.
+ */
+ public boolean isAccessibleChildSelected(int i)
+ {
+ // Nothing to do here.
+ return false;
+ }
+
+ /**
+ * Removes the specified selected item in the object from the object's
+ * selection.
+ *
+ * @param i - the i-th selected item to remove
+ */
+ public void removeAccessibleSelection(int i)
+ {
+ removeSelectionInterval(i, i);
+ }
+
+ /**
+ * Causes every selected item in the object to be selected if the object
+ * supports multiple selections.
+ */
+ public void selectAllAccessibleSelection()
+ {
+ if (getSelectionModel().getSelectionMode() !=
+ TreeSelectionModel.SINGLE_TREE_SELECTION)
+ addSelectionInterval(0, getVisibleRowCount());
+ }
+
+ /**
+ * Tree Collapsed notification
+ *
+ * @param e - the event
+ */
+ public void treeCollapsed(TreeExpansionEvent e)
+ {
+ fireTreeCollapsed(e.getPath());
+ }
+
+ /**
+ * Tree Model Expansion notification.
+ *
+ * @param e - the event
+ */
+ public void treeExpanded(TreeExpansionEvent e)
+ {
+ fireTreeExpanded(e.getPath());
+ }
+
+ /**
+ * Tree Model Node change notification.
+ *
+ * @param e - the event
+ */
+ public void treeNodesChanged(TreeModelEvent e)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Tree Model Node change notification.
+ *
+ * @param e - the event
+ */
+ public void treeNodesInserted(TreeModelEvent e)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Tree Model Node change notification.
+ *
+ * @param e - the event
+ */
+ public void treeNodesRemoved(TreeModelEvent e)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Tree Model structure change change notification.
+ *
+ * @param e - the event
+ */
+ public void treeStructureChanged(TreeModelEvent e)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Tree Selection Listener value change method.
+ *
+ * @param e - the event
+ */
+ public void valueChanged(TreeSelectionEvent e)
+ {
+ fireValueChanged(e);
+ }
+ }
+
+ public static class DynamicUtilTreeNode extends DefaultMutableTreeNode
+ {
+ protected Object childValue;
+
+ protected boolean loadedChildren;
+
+ /**
+ * Currently not set or used by this class. It might be set and used in
+ * later versions of this class.
+ */
+ protected boolean hasChildren;
+
+ public DynamicUtilTreeNode(Object value, Object children)
+ {
+ super(value);
+ childValue = children;
+ loadedChildren = false;
+ }
+
+ public int getChildCount()
+ {
+ loadChildren();
+ return super.getChildCount();
+ }
+
+ protected void loadChildren()
+ {
+ if (!loadedChildren)
+ {
+ createChildren(this, childValue);
+ loadedChildren = true;
+ }
+ }
+
+ public Enumeration children()
+ {
+ loadChildren();
+ return super.children();
+ }
+
+ /**
+ * Returns the child node at position <code>pos</code>. Subclassed
+ * here to load the children if necessary.
+ *
+ * @param pos the position of the child node to fetch
+ *
+ * @return the childnode at the specified position
+ */
+ public TreeNode getChildAt(int pos)
+ {
+ loadChildren();
+ return super.getChildAt(pos);
+ }
+
+ public boolean isLeaf()
+ {
+ return (childValue == null || !(childValue instanceof Hashtable
+ || childValue instanceof Vector || childValue.getClass()
+ .isArray()));
+ }
+
+ public static void createChildren(DefaultMutableTreeNode parent,
+ Object children)
+ {
+ if (children instanceof Hashtable)
+ {
+ Hashtable tab = (Hashtable) children;
+ Enumeration e = tab.keys();
+ while (e.hasMoreElements())
+ {
+ Object key = e.nextElement();
+ Object val = tab.get(key);
+ parent.add(new DynamicUtilTreeNode(key, val));
+ }
+ }
+ else if (children instanceof Vector)
+ {
+ Iterator i = ((Vector) children).iterator();
+ while (i.hasNext())
+ {
+ Object n = i.next();
+ parent.add(new DynamicUtilTreeNode(n, n));
+ }
+ }
+ else if (children != null && children.getClass().isArray())
+ {
+ Object[] arr = (Object[]) children;
+ for (int i = 0; i < arr.length; ++i)
+ parent.add(new DynamicUtilTreeNode(arr[i], arr[i]));
+ }
+ }
+ }
+
+ /**
+ * Listens to the model of the JTree and updates the property
+ * <code>expandedState</code> if nodes are removed or changed.
+ */
+ protected class TreeModelHandler implements TreeModelListener
+ {
+
+ /**
+ * Creates a new instance of TreeModelHandler.
+ */
+ protected TreeModelHandler()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Notifies when a node has changed in some ways. This does not include
+ * that a node has changed its location or changed it's children. It
+ * only means that some attributes of the node have changed that might
+ * affect its presentation.
+ *
+ * This method is called after the actual change occured.
+ *
+ * @param ev the TreeModelEvent describing the change
+ */
+ public void treeNodesChanged(TreeModelEvent ev)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Notifies when a node is inserted into the tree.
+ *
+ * This method is called after the actual change occured.
+ *
+ * @param ev the TreeModelEvent describing the change
+ */
+ public void treeNodesInserted(TreeModelEvent ev)
+ {
+ // nothing to do here
+ }
+
+ /**
+ * Notifies when a node is removed from the tree.
+ *
+ * This method is called after the actual change occured.
+ *
+ * @param ev the TreeModelEvent describing the change
*/
- protected static class EmptySelectionModel
- extends
- DefaultTreeSelectionModel
- {
- /** The serial version UID. */
- private static final long serialVersionUID = -5815023306225701477L;
-
- /**
- * The shared instance of this model.
- */
- protected static final EmptySelectionModel sharedInstance = new EmptySelectionModel();
-
- /**
- * Creates a new instance of EmptySelectionModel.
- */
- protected EmptySelectionModel()
- {
- }
-
- /**
- * Returns the shared instance of EmptySelectionModel.
- *
- * @return the shared instance of EmptySelectionModel
- */
- public static EmptySelectionModel sharedInstance()
- {
- return sharedInstance;
- }
-
- /**
- * This catches attempts to set a selection and sets nothing instead.
- *
- * @param paths not used here
- */
- public void setSelectionPaths(TreePath[] paths)
- {
- // we don't allow selections in this class
- }
-
- /**
- * This catches attempts to add something to the selection.
- *
- * @param paths not used here
- */
- public void addSelectionPaths(TreePath[] paths)
- {
- // we don't allow selections in this class
- }
-
- /**
- * This catches attempts to remove something from the selection.
- *
- * @param paths not used here
- */
- public void removeSelectionPaths(TreePath[] paths)
- {
- // we don't allow selections in this class
- }
- }// EmptySelectionModel
-
- private static final long serialVersionUID = 7559816092864483649L;
- public static final String CELL_EDITOR_PROPERTY = "cellEditor";
- public static final String CELL_RENDERER_PROPERTY = "cellRenderer";
- public static final String EDITABLE_PROPERTY = "editable";
- public static final String INVOKES_STOP_CELL_EDITING_PROPERTY = "invokesStopCellEditing";
- public static final String LARGE_MODEL_PROPERTY = "largeModel";
- public static final String ROOT_VISIBLE_PROPERTY = "rootVisible";
- public static final String ROW_HEIGHT_PROPERTY = "rowHeight";
- public static final String SCROLLS_ON_EXPAND_PROPERTY = "scrollsOnExpand";
- public static final String SELECTION_MODEL_PROPERTY = "selectionModel";
- public static final String SHOWS_ROOT_HANDLES_PROPERTY = "showsRootHandles";
- public static final String TOGGLE_CLICK_COUNT_PROPERTY = "toggleClickCount";
- public static final String TREE_MODEL_PROPERTY = "model";
- public static final String VISIBLE_ROW_COUNT_PROPERTY = "visibleRowCount";
+ public void treeNodesRemoved(TreeModelEvent ev)
+ {
+ // TODO: The API docs suggest that this method should do something
+ // but I cannot really see what has to be done here ...
+ }
- /** @since 1.3 */
- public static final String ANCHOR_SELECTION_PATH_PROPERTY = "anchorSelectionPath";
+ /**
+ * Notifies when the structure of the tree is changed.
+ *
+ * This method is called after the actual change occured.
+ *
+ * @param ev the TreeModelEvent describing the change
+ */
+ public void treeStructureChanged(TreeModelEvent ev)
+ {
+ // Set state of new path.
+ TreePath path = ev.getTreePath();
+ setExpandedState(path, isExpanded(path));
+ }
+ }
- /** @since 1.3 */
- public static final String LEAD_SELECTION_PATH_PROPERTY = "leadSelectionPath";
+ /**
+ * This redirects TreeSelectionEvents and rewrites the source of it to be
+ * this JTree. This is typically done when the tree model generates an
+ * event, but the JTree object associated with that model should be listed
+ * as the actual source of the event.
+ */
+ protected class TreeSelectionRedirector implements TreeSelectionListener,
+ Serializable
+ {
+ /** The serial version UID. */
+ private static final long serialVersionUID = -3505069663646241664L;
+
+ /**
+ * Creates a new instance of TreeSelectionRedirector
+ */
+ protected TreeSelectionRedirector()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Notifies when the tree selection changes.
+ *
+ * @param ev the TreeSelectionEvent that describes the change
+ */
+ public void valueChanged(TreeSelectionEvent ev)
+ {
+ TreeSelectionEvent rewritten =
+ (TreeSelectionEvent) ev.cloneWithSource(JTree.this);
+ fireValueChanged(rewritten);
+ JTree.this.repaint();
+ }
+ }
+
+ /**
+ * A TreeModel that does not allow anything to be selected.
+ */
+ protected static class EmptySelectionModel extends DefaultTreeSelectionModel
+ {
+ /** The serial version UID. */
+ private static final long serialVersionUID = -5815023306225701477L;
+
+ /**
+ * The shared instance of this model.
+ */
+ protected static final EmptySelectionModel sharedInstance =
+ new EmptySelectionModel();
+
+ /**
+ * Creates a new instance of EmptySelectionModel.
+ */
+ protected EmptySelectionModel()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the shared instance of EmptySelectionModel.
+ *
+ * @return the shared instance of EmptySelectionModel
+ */
+ public static EmptySelectionModel sharedInstance()
+ {
+ return sharedInstance;
+ }
+
+ /**
+ * This catches attempts to set a selection and sets nothing instead.
+ *
+ * @param paths not used here
+ */
+ public void setSelectionPaths(TreePath[] paths)
+ {
+ // We don't allow selections in this class.
+ }
+
+ /**
+ * This catches attempts to add something to the selection.
+ *
+ * @param paths not used here
+ */
+ public void addSelectionPaths(TreePath[] paths)
+ {
+ // We don't allow selections in this class.
+ }
+
+ /**
+ * This catches attempts to remove something from the selection.
+ *
+ * @param paths not used here
+ */
+ public void removeSelectionPaths(TreePath[] paths)
+ {
+ // We don't allow selections in this class.
+ }
+ }
+
+ private static final long serialVersionUID = 7559816092864483649L;
+
+ public static final String CELL_EDITOR_PROPERTY = "cellEditor";
+
+ public static final String CELL_RENDERER_PROPERTY = "cellRenderer";
+
+ public static final String EDITABLE_PROPERTY = "editable";
+
+ public static final String INVOKES_STOP_CELL_EDITING_PROPERTY =
+ "invokesStopCellEditing";
+
+ public static final String LARGE_MODEL_PROPERTY = "largeModel";
+
+ public static final String ROOT_VISIBLE_PROPERTY = "rootVisible";
+
+ public static final String ROW_HEIGHT_PROPERTY = "rowHeight";
+
+ public static final String SCROLLS_ON_EXPAND_PROPERTY = "scrollsOnExpand";
+
+ public static final String SELECTION_MODEL_PROPERTY = "selectionModel";
+
+ public static final String SHOWS_ROOT_HANDLES_PROPERTY = "showsRootHandles";
+
+ public static final String TOGGLE_CLICK_COUNT_PROPERTY = "toggleClickCount";
+
+ public static final String TREE_MODEL_PROPERTY = "model";
+
+ public static final String VISIBLE_ROW_COUNT_PROPERTY = "visibleRowCount";
+
+ /** @since 1.3 */
+ public static final String ANCHOR_SELECTION_PATH_PROPERTY =
+ "anchorSelectionPath";
/** @since 1.3 */
- public static final String EXPANDS_SELECTED_PATHS_PROPERTY = "expandsSelectedPaths";
- private static final Object EXPANDED = new Object();
- private static final Object COLLAPSED = new Object();
- private boolean dragEnabled;
- private boolean expandsSelectedPaths;
- private TreePath anchorSelectionPath;
- private TreePath leadSelectionPath;
-
- /*
- * This contains the state of all nodes in the tree. Al/ entries map the
- * TreePath of a note to to its state. Valid states are EXPANDED and
- * COLLAPSED. Nodes not in this Hashtable are assumed state COLLAPSED.
- */
- private Hashtable nodeStates = new Hashtable();
- protected transient TreeCellEditor cellEditor;
- protected transient TreeCellRenderer cellRenderer;
- protected boolean editable;
- protected boolean invokesStopCellEditing;
- protected boolean largeModel;
- protected boolean rootVisible;
- protected int rowHeight;
- protected boolean scrollsOnExpand;
- protected transient TreeSelectionModel selectionModel;
- protected boolean showsRootHandles;
- protected int toggleClickCount;
- protected transient TreeModel treeModel;
- protected int visibleRowCount;
-
- /**
- * Handles TreeModelEvents to update the expandedState.
- */
- protected transient TreeModelListener treeModelListener;
+ public static final String LEAD_SELECTION_PATH_PROPERTY = "leadSelectionPath";
- /**
- * Redirects TreeSelectionEvents so that the source is this JTree.
- */
- protected TreeSelectionRedirector selectionRedirector =
- new TreeSelectionRedirector();
+ /** @since 1.3 */
+ public static final String EXPANDS_SELECTED_PATHS_PROPERTY =
+ "expandsSelectedPaths";
- /**
- * Creates a new <code>JTree</code> object.
- */
- public JTree()
- {
- this(createTreeModel(null));
- }
-
- /**
- * Creates a new <code>JTree</code> object.
- *
- * @param value the initial nodes in the tree
- */
- public JTree(Hashtable value)
- {
- this(createTreeModel(value));
- }
-
- /**
- * Creates a new <code>JTree</code> object.
- *
- * @param value the initial nodes in the tree
- */
- public JTree(Object[] value)
- {
- this(createTreeModel(value));
- }
-
- /**
- * Creates a new <code>JTree</code> object.
- *
- * @param model the model to use
- */
- public JTree(TreeModel model)
- {
- setModel(model);
- setSelectionModel(EmptySelectionModel.sharedInstance());
- setCellRenderer(new DefaultTreeCellRenderer());
- updateUI();
- }
-
- /**
- * Creates a new <code>JTree</code> object.
- *
- * @param root the root node
- */
- public JTree(TreeNode root)
- {
- this(root, false);
- }
-
- /**
- * Creates a new <code>JTree</code> object.
- *
- * @param root the root node
- * @param asksAllowChildren if false, all nodes without children are leaf
- * nodes. If true, only nodes that do not allow children are leaf
- * nodes.
- */
- public JTree(TreeNode root, boolean asksAllowChildren)
- {
- this(new DefaultTreeModel(root, asksAllowChildren));
- }
-
- /**
- * Creates a new <code>JTree</code> object.
- *
- * @param value the initial nodes in the tree
- */
- public JTree(Vector value)
- {
- this(createTreeModel(value));
- }
-
- public static class DynamicUtilTreeNode
- extends
- DefaultMutableTreeNode
- {
- protected Object childValue;
- protected boolean loadedChildren;
-
- /**
- * Currently not set or used by this class. It might be set and used in
- * later versions of this class.
- */
- protected boolean hasChildren;
-
- public DynamicUtilTreeNode(Object value, Object children)
- {
- super(value);
- childValue = children;
- loadedChildren = false;
- }
-
- public int getChildCount()
- {
- loadChildren();
- return super.getChildCount();
- }
-
- protected void loadChildren()
- {
- if (!loadedChildren)
- {
- createChildren(this, childValue);
- loadedChildren = true;
- }
- }
-
- public Enumeration children()
- {
- loadChildren();
- return super.children();
- }
-
- /**
- * Returns the child node at position <code>pos</code>. Subclassed
- * here to load the children if necessary.
- *
- * @param pos the position of the child node to fetch
- *
- * @return the childnode at the specified position
- */
- public TreeNode getChildAt(int pos)
- {
- loadChildren();
- return super.getChildAt(pos);
- }
-
- public boolean isLeaf()
- {
- return (childValue == null || !(childValue instanceof Hashtable
- || childValue instanceof Vector || childValue.getClass()
- .isArray()));
- }
-
- public static void createChildren(DefaultMutableTreeNode parent,
- Object children)
- {
- if (children instanceof Hashtable)
- {
- Hashtable tab = (Hashtable) children;
- Enumeration e = tab.keys();
- while (e.hasMoreElements())
- {
- Object key = e.nextElement();
- Object val = tab.get(key);
- parent.add(new DynamicUtilTreeNode(key, val));
- }
- } else if (children instanceof Vector)
- {
- Iterator i = ((Vector) children).iterator();
- while (i.hasNext())
- {
- Object n = i.next();
- parent.add(new DynamicUtilTreeNode(n, n));
- }
- } else if (children != null && children.getClass().isArray())
- {
- Object[] arr = (Object[]) children;
- for (int i = 0; i < arr.length; ++i)
- parent.add(new DynamicUtilTreeNode(arr[i], arr[i]));
- }
- }
- }
-
- public int getRowForPath(TreePath path)
- {
- TreeUI ui = getUI();
-
- if (ui != null)
- return ui.getRowForPath(this, path);
-
- return -1;
- }
-
- public TreePath getPathForRow(int row)
- {
- TreeUI ui = getUI();
- return ui != null ? ui.getPathForRow(this, row) : null;
- }
-
- protected TreePath[] getPathBetweenRows(int index0, int index1)
- {
- TreeUI ui = getUI();
-
- if (ui == null)
- return null;
-
- int minIndex = Math.min(index0, index1);
- int maxIndex = Math.max(index0, index1);
- TreePath[] paths = new TreePath[maxIndex - minIndex + 1];
-
- for (int i = minIndex; i <= maxIndex; ++i)
- paths[i - minIndex] = ui.getPathForRow(this, i);
-
- return paths;
- }
-
- /**
- * Creates a new <code>TreeModel</code> object.
- *
- * @param value the values stored in the model
- */
- protected static TreeModel createTreeModel(Object value)
- {
- return new DefaultTreeModel(new DynamicUtilTreeNode(value, value));
- }
-
- /**
- * Return the UI associated with this <code>JTree</code> object.
- *
- * @return the associated <code>TreeUI</code> object
- */
- public TreeUI getUI()
- {
- return (TreeUI) ui;
- }
-
- /**
- * Sets the UI associated with this <code>JTree</code> object.
- *
- * @param ui the <code>TreeUI</code> to associate
- */
- public void setUI(TreeUI ui)
- {
- super.setUI(ui);
- }
+ private static final Object EXPANDED = new Object();
- /**
- * This method resets the UI used to the Look and Feel defaults..
- */
- public void updateUI()
- {
- setUI((TreeUI) UIManager.getUI(this));
- revalidate();
- repaint();
- }
-
- /**
- * This method returns the String ID of the UI class of Separator.
- *
- * @return The UI class' String ID.
- */
- public String getUIClassID()
- {
- return "TreeUI";
- }
-
- /**
- * Gets the AccessibleContext associated with this
- * <code>JToggleButton</code>.
- *
- * @return the associated context
- */
- public AccessibleContext getAccessibleContext()
- {
- return null;
- }
-
- /**
- * Returns the preferred viewport size.
- *
- * @return the preferred size
- */
- public Dimension getPreferredScrollableViewportSize()
- {
- return new Dimension (getPreferredSize().width, getVisibleRowCount()*getRowHeight());
- }
-
- public int getScrollableUnitIncrement(Rectangle visibleRect,
- int orientation, int direction)
- {
- return 1;
- }
-
- public int getScrollableBlockIncrement(Rectangle visibleRect,
- int orientation, int direction)
- {
- return 1;
- }
+ private static final Object COLLAPSED = new Object();
- public boolean getScrollableTracksViewportWidth()
+ private boolean dragEnabled;
+
+ private boolean expandsSelectedPaths;
+
+ private TreePath anchorSelectionPath;
+
+ private TreePath leadSelectionPath;
+
+ /**
+ * This contains the state of all nodes in the tree. Al/ entries map the
+ * TreePath of a note to to its state. Valid states are EXPANDED and
+ * COLLAPSED. Nodes not in this Hashtable are assumed state COLLAPSED.
+ */
+ private Hashtable nodeStates = new Hashtable();
+
+ protected transient TreeCellEditor cellEditor;
+
+ protected transient TreeCellRenderer cellRenderer;
+
+ protected boolean editable;
+
+ protected boolean invokesStopCellEditing;
+
+ protected boolean largeModel;
+
+ protected boolean rootVisible;
+
+ protected int rowHeight;
+
+ protected boolean scrollsOnExpand;
+
+ protected transient TreeSelectionModel selectionModel;
+
+ protected boolean showsRootHandles;
+
+ protected int toggleClickCount;
+
+ protected transient TreeModel treeModel;
+
+ protected int visibleRowCount;
+
+ /**
+ * Handles TreeModelEvents to update the expandedState.
+ */
+ protected transient TreeModelListener treeModelListener;
+
+ /**
+ * Redirects TreeSelectionEvents so that the source is this JTree.
+ */
+ protected TreeSelectionRedirector selectionRedirector =
+ new TreeSelectionRedirector();
+
+ /**
+ * Creates a new <code>JTree</code> object.
+ */
+ public JTree()
+ {
+ this(createTreeModel(null));
+ }
+
+ /**
+ * Creates a new <code>JTree</code> object.
+ *
+ * @param value the initial nodes in the tree
+ */
+ public JTree(Hashtable value)
+ {
+ this(createTreeModel(value));
+ }
+
+ /**
+ * Creates a new <code>JTree</code> object.
+ *
+ * @param value the initial nodes in the tree
+ */
+ public JTree(Object[] value)
+ {
+ this(createTreeModel(value));
+ }
+
+ /**
+ * Creates a new <code>JTree</code> object.
+ *
+ * @param model the model to use
+ */
+ public JTree(TreeModel model)
+ {
+ updateUI();
+ setRootVisible(true);
+ setModel(model);
+ setSelectionModel(new EmptySelectionModel());
+ }
+
+ /**
+ * Creates a new <code>JTree</code> object.
+ *
+ * @param root the root node
+ */
+ public JTree(TreeNode root)
+ {
+ this(root, false);
+ }
+
+ /**
+ * Creates a new <code>JTree</code> object.
+ *
+ * @param root the root node
+ * @param asksAllowChildren if false, all nodes without children are leaf
+ * nodes. If true, only nodes that do not allow children are leaf
+ * nodes.
+ */
+ public JTree(TreeNode root, boolean asksAllowChildren)
+ {
+ this(new DefaultTreeModel(root, asksAllowChildren));
+ }
+
+ /**
+ * Creates a new <code>JTree</code> object.
+ *
+ * @param value the initial nodes in the tree
+ */
+ public JTree(Vector value)
+ {
+ this(createTreeModel(value));
+ }
+
+ public int getRowForPath(TreePath path)
+ {
+ TreeUI ui = getUI();
+
+ if (ui != null)
+ return ui.getRowForPath(this, path);
+
+ return -1;
+ }
+
+ public TreePath getPathForRow(int row)
+ {
+ TreeUI ui = getUI();
+ return ui != null ? ui.getPathForRow(this, row) : null;
+ }
+
+ protected TreePath[] getPathBetweenRows(int index0, int index1)
+ {
+ TreeUI ui = getUI();
+
+ if (ui == null)
+ return null;
+
+ int minIndex = Math.min(index0, index1);
+ int maxIndex = Math.max(index0, index1);
+ TreePath[] paths = new TreePath[maxIndex - minIndex + 1];
+
+ for (int i = minIndex; i <= maxIndex; ++i)
+ paths[i - minIndex] = ui.getPathForRow(this, i);
+
+ return paths;
+ }
+
+ /**
+ * Creates a new <code>TreeModel</code> object.
+ *
+ * @param value the values stored in the model
+ */
+ protected static TreeModel createTreeModel(Object value)
+ {
+ return new DefaultTreeModel(new DynamicUtilTreeNode(value, value));
+ }
+
+ /**
+ * Return the UI associated with this <code>JTree</code> object.
+ *
+ * @return the associated <code>TreeUI</code> object
+ */
+ public TreeUI getUI()
+ {
+ return (TreeUI) ui;
+ }
+
+ /**
+ * Sets the UI associated with this <code>JTree</code> object.
+ *
+ * @param ui the <code>TreeUI</code> to associate
+ */
+ public void setUI(TreeUI ui)
+ {
+ super.setUI(ui);
+ }
+
+ /**
+ * This method resets the UI used to the Look and Feel defaults..
+ */
+ public void updateUI()
+ {
+ setUI((TreeUI) UIManager.getUI(this));
+ }
+
+ /**
+ * This method returns the String ID of the UI class of Separator.
+ *
+ * @return The UI class' String ID.
+ */
+ public String getUIClassID()
+ {
+ return "TreeUI";
+ }
+
+ /**
+ * Gets the AccessibleContext associated with this
+ * <code>JTree</code>.
+ *
+ * @return the associated context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return new AccessibleJTree();
+ }
+
+ /**
+ * Returns the preferred viewport size.
+ *
+ * @return the preferred size
+ */
+ public Dimension getPreferredScrollableViewportSize()
+ {
+ return new Dimension (getPreferredSize().width, getVisibleRowCount()*getRowHeight());
+ }
+
+ public int getScrollableUnitIncrement(Rectangle visibleRect,
+ int orientation, int direction)
+ {
+ return 1;
+ }
+
+ public int getScrollableBlockIncrement(Rectangle visibleRect,
+ int orientation, int direction)
+ {
+ return 1;
+ }
+
+ public boolean getScrollableTracksViewportHeight()
{
if (getParent() instanceof JViewport)
return ((JViewport) getParent()).getHeight() > getPreferredSize().height;
return false;
}
-
- public boolean getScrollableTracksViewportHeight()
+
+ public boolean getScrollableTracksViewportWidth()
{
if (getParent() instanceof JViewport)
return ((JViewport) getParent()).getWidth() > getPreferredSize().width;
return false;
}
- /**
- * Adds a <code>TreeExpansionListener</code> object to the tree.
- *
- * @param listener the listener to add
- */
- public void addTreeExpansionListener(TreeExpansionListener listener)
- {
- listenerList.add(TreeExpansionListener.class, listener);
- }
-
- /**
- * Removes a <code>TreeExpansionListener</code> object from the tree.
- *
- * @param listener the listener to remove
- */
- public void removeTreeExpansionListener(TreeExpansionListener listener)
- {
- listenerList.remove(TreeExpansionListener.class, listener);
- }
-
- /**
- * Returns all added <code>TreeExpansionListener</code> objects.
- *
- * @return an array of listeners
- */
- public TreeExpansionListener[] getTreeExpansionListeners()
- {
- return (TreeExpansionListener[]) getListeners(TreeExpansionListener.class);
- }
-
- /**
- * Notifies all listeners that the tree was collapsed.
- *
- * @param path the path to the node that was collapsed
- */
- public void fireTreeCollapsed(TreePath path)
- {
- TreeExpansionEvent event = new TreeExpansionEvent(this, path);
- TreeExpansionListener[] listeners = getTreeExpansionListeners();
-
- for (int index = 0; index < listeners.length; ++index)
- listeners[index].treeCollapsed(event);
- }
-
- /**
- * Notifies all listeners that the tree was expanded.
- *
- * @param path the path to the node that was expanded
- */
- public void fireTreeExpanded(TreePath path)
- {
- TreeExpansionEvent event = new TreeExpansionEvent(this, path);
- TreeExpansionListener[] listeners = getTreeExpansionListeners();
-
- for (int index = 0; index < listeners.length; ++index)
- listeners[index].treeExpanded(event);
- }
-
- /**
- * Adds a <code>TreeSelctionListener</code> object to the tree.
- *
- * @param listener the listener to add
- */
- public void addTreeSelectionListener(TreeSelectionListener listener)
- {
- listenerList.add(TreeSelectionListener.class, listener);
- }
-
- /**
- * Removes a <code>TreeSelectionListener</code> object from the tree.
- *
- * @param listener the listener to remove
- */
- public void removeTreeSelectionListener(TreeSelectionListener listener)
- {
- listenerList.remove(TreeSelectionListener.class, listener);
- }
-
- /**
- * Returns all added <code>TreeSelectionListener</code> objects.
- *
- * @return an array of listeners
- */
- public TreeSelectionListener[] getTreeSelectionListeners()
- {
- return (TreeSelectionListener[])
- getListeners(TreeSelectionListener.class);
- }
-
- /**
- * Notifies all listeners when the selection of the tree changed.
- *
- * @param event the event to send
- */
- protected void fireValueChanged(TreeSelectionEvent event)
- {
- TreeSelectionListener[] listeners = getTreeSelectionListeners();
-
- for (int index = 0; index < listeners.length; ++index)
- listeners[index].valueChanged(event);
- }
-
- /**
- * Adds a <code>TreeWillExpandListener</code> object to the tree.
- *
- * @param listener the listener to add
- */
- public void addTreeWillExpandListener(TreeWillExpandListener listener)
- {
- listenerList.add(TreeWillExpandListener.class, listener);
- }
-
- /**
- * Removes a <code>TreeWillExpandListener</code> object from the tree.
- *
- * @param listener the listener to remove
- */
- public void removeTreeWillExpandListener(TreeWillExpandListener listener)
- {
- listenerList.remove(TreeWillExpandListener.class, listener);
- }
-
- /**
- * Returns all added <code>TreeWillExpandListener</code> objects.
- *
- * @return an array of listeners
- */
- public TreeWillExpandListener[] getTreeWillExpandListeners()
- {
- return (TreeWillExpandListener[])
- getListeners(TreeWillExpandListener.class);
- }
-
- /**
- * Notifies all listeners that the tree will collapse.
- *
- * @param path the path to the node that will collapse
- */
- public void fireTreeWillCollapse(TreePath path) throws ExpandVetoException
- {
- TreeExpansionEvent event = new TreeExpansionEvent(this, path);
- TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
-
- for (int index = 0; index < listeners.length; ++index)
- listeners[index].treeWillCollapse(event);
- }
-
- /**
- * Notifies all listeners that the tree will expand.
- *
- * @param path the path to the node that will expand
- */
- public void fireTreeWillExpand(TreePath path) throws ExpandVetoException
- {
- TreeExpansionEvent event = new TreeExpansionEvent(this, path);
- TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
-
- for (int index = 0; index < listeners.length; ++index)
- listeners[index].treeWillExpand(event);
- }
-
- /**
- * Returns the model of this <code>JTree</code> object.
- *
- * @return the associated <code>TreeModel</code>
- */
- public TreeModel getModel()
- {
- return treeModel;
- }
-
- /**
- * Sets the model to use in <code>JTree</code>.
- *
- * @param model the <code>TreeModel</code> to use
- */
- public void setModel(TreeModel model)
- {
- if (treeModel == model)
- return;
-
- // add treeModelListener to the new model
- if (treeModelListener == null)
- treeModelListener = createTreeModelListener();
- if (model != null) // as setModel(null) is allowed
- model.addTreeModelListener(treeModelListener);
-
+ /**
+ * Adds a <code>TreeExpansionListener</code> object to the tree.
+ *
+ * @param listener the listener to add
+ */
+ public void addTreeExpansionListener(TreeExpansionListener listener)
+ {
+ listenerList.add(TreeExpansionListener.class, listener);
+ }
+
+ /**
+ * Removes a <code>TreeExpansionListener</code> object from the tree.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeTreeExpansionListener(TreeExpansionListener listener)
+ {
+ listenerList.remove(TreeExpansionListener.class, listener);
+ }
+
+ /**
+ * Returns all added <code>TreeExpansionListener</code> objects.
+ *
+ * @return an array of listeners
+ */
+ public TreeExpansionListener[] getTreeExpansionListeners()
+ {
+ return (TreeExpansionListener[]) getListeners(TreeExpansionListener.class);
+ }
+
+ /**
+ * Notifies all listeners that the tree was collapsed.
+ *
+ * @param path the path to the node that was collapsed
+ */
+ public void fireTreeCollapsed(TreePath path)
+ {
+ TreeExpansionEvent event = new TreeExpansionEvent(this, path);
+ TreeExpansionListener[] listeners = getTreeExpansionListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].treeCollapsed(event);
+ }
+
+ /**
+ * Notifies all listeners that the tree was expanded.
+ *
+ * @param path the path to the node that was expanded
+ */
+ public void fireTreeExpanded(TreePath path)
+ {
+ TreeExpansionEvent event = new TreeExpansionEvent(this, path);
+ TreeExpansionListener[] listeners = getTreeExpansionListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].treeExpanded(event);
+ }
+
+ /**
+ * Adds a <code>TreeSelctionListener</code> object to the tree.
+ *
+ * @param listener the listener to add
+ */
+ public void addTreeSelectionListener(TreeSelectionListener listener)
+ {
+ listenerList.add(TreeSelectionListener.class, listener);
+ }
+
+ /**
+ * Removes a <code>TreeSelectionListener</code> object from the tree.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeTreeSelectionListener(TreeSelectionListener listener)
+ {
+ listenerList.remove(TreeSelectionListener.class, listener);
+ }
+
+ /**
+ * Returns all added <code>TreeSelectionListener</code> objects.
+ *
+ * @return an array of listeners
+ */
+ public TreeSelectionListener[] getTreeSelectionListeners()
+ {
+ return (TreeSelectionListener[])
+ getListeners(TreeSelectionListener.class);
+ }
+
+ /**
+ * Notifies all listeners when the selection of the tree changed.
+ *
+ * @param event the event to send
+ */
+ protected void fireValueChanged(TreeSelectionEvent event)
+ {
+ TreeSelectionListener[] listeners = getTreeSelectionListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].valueChanged(event);
+ }
+
+ /**
+ * Adds a <code>TreeWillExpandListener</code> object to the tree.
+ *
+ * @param listener the listener to add
+ */
+ public void addTreeWillExpandListener(TreeWillExpandListener listener)
+ {
+ listenerList.add(TreeWillExpandListener.class, listener);
+ }
+
+ /**
+ * Removes a <code>TreeWillExpandListener</code> object from the tree.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeTreeWillExpandListener(TreeWillExpandListener listener)
+ {
+ listenerList.remove(TreeWillExpandListener.class, listener);
+ }
+
+ /**
+ * Returns all added <code>TreeWillExpandListener</code> objects.
+ *
+ * @return an array of listeners
+ */
+ public TreeWillExpandListener[] getTreeWillExpandListeners()
+ {
+ return (TreeWillExpandListener[])
+ getListeners(TreeWillExpandListener.class);
+ }
+
+ /**
+ * Notifies all listeners that the tree will collapse.
+ *
+ * @param path the path to the node that will collapse
+ */
+ public void fireTreeWillCollapse(TreePath path) throws ExpandVetoException
+ {
+ TreeExpansionEvent event = new TreeExpansionEvent(this, path);
+ TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].treeWillCollapse(event);
+ }
+
+ /**
+ * Notifies all listeners that the tree will expand.
+ *
+ * @param path the path to the node that will expand
+ */
+ public void fireTreeWillExpand(TreePath path) throws ExpandVetoException
+ {
+ TreeExpansionEvent event = new TreeExpansionEvent(this, path);
+ TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].treeWillExpand(event);
+ }
+
+ /**
+ * Returns the model of this <code>JTree</code> object.
+ *
+ * @return the associated <code>TreeModel</code>
+ */
+ public TreeModel getModel()
+ {
+ return treeModel;
+ }
+
+ /**
+ * Sets the model to use in <code>JTree</code>.
+ *
+ * @param model the <code>TreeModel</code> to use
+ */
+ public void setModel(TreeModel model)
+ {
+ if (treeModel == model)
+ return;
+
+ // add treeModelListener to the new model
+ if (treeModelListener == null)
+ treeModelListener = createTreeModelListener();
+ if (model != null) // as setModel(null) is allowed
+ model.addTreeModelListener(treeModelListener);
+
TreeModel oldValue = treeModel;
treeModel = model;
firePropertyChange(TREE_MODEL_PROPERTY, oldValue, model);
- }
+ updateUI();
+ }
- /**
- * Checks if this <code>JTree</code> object is editable.
- *
- * @return <code>true</code> if this tree object is editable,
- * <code>false</code> otherwise
- */
- public boolean isEditable()
- {
- return editable;
- }
-
- /**
- * Sets the <code>editable</code> property.
- *
- * @param flag <code>true</code> to make this tree object editable,
- * <code>false</code> otherwise
- */
- public void setEditable(boolean flag)
- {
- if (editable == flag)
- return;
-
- boolean oldValue = editable;
- editable = flag;
- firePropertyChange(EDITABLE_PROPERTY, oldValue, editable);
- }
-
- /**
- * Checks if the root element is visible.
- *
- * @return <code>true</code> if the root element is visible,
- * <code>false</code> otherwise
- */
- public boolean isRootVisible()
- {
- return rootVisible;
- }
-
- public void setRootVisible(boolean flag)
- {
- if (rootVisible == flag)
- return;
-
- boolean oldValue = rootVisible;
- rootVisible = flag;
- firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, flag);
- }
-
- public boolean getShowsRootHandles()
- {
- return showsRootHandles;
- }
-
- public void setShowsRootHandles(boolean flag)
- {
- if (showsRootHandles == flag)
- return;
-
- boolean oldValue = showsRootHandles;
- showsRootHandles = flag;
- firePropertyChange(SHOWS_ROOT_HANDLES_PROPERTY, oldValue, flag);
- }
-
- public TreeCellEditor getCellEditor()
- {
-
- return cellEditor;
- }
-
- public void setCellEditor(TreeCellEditor editor)
- {
- if (cellEditor == editor)
- return;
-
- TreeCellEditor oldValue = cellEditor;
- cellEditor = editor;
- firePropertyChange(CELL_EDITOR_PROPERTY, oldValue, editor);
- }
-
- public TreeCellRenderer getCellRenderer()
- {
- return cellRenderer;
- }
-
- public void setCellRenderer(TreeCellRenderer newRenderer)
- {
- if (cellRenderer == newRenderer)
- return;
-
- TreeCellRenderer oldValue = cellRenderer;
- cellRenderer = newRenderer;
- firePropertyChange(CELL_RENDERER_PROPERTY, oldValue, newRenderer);
- }
-
- public TreeSelectionModel getSelectionModel()
- {
- return selectionModel;
- }
-
- public void setSelectionModel(TreeSelectionModel model)
- {
- if (selectionModel == model)
- return;
-
- if (selectionModel != null)
- selectionModel.removeTreeSelectionListener(selectionRedirector);
-
- TreeSelectionModel oldValue = selectionModel;
- selectionModel = model;
-
- if (selectionModel != null)
- selectionModel.addTreeSelectionListener(selectionRedirector);
-
- firePropertyChange(SELECTION_MODEL_PROPERTY, oldValue, model);
- revalidate();
- repaint();
- }
-
- public int getVisibleRowCount()
- {
- return visibleRowCount;
- }
-
- public void setVisibleRowCount(int rows)
- {
- if (visibleRowCount == rows)
- return;
-
- int oldValue = visibleRowCount;
- visibleRowCount = rows;
- firePropertyChange(VISIBLE_ROW_COUNT_PROPERTY, oldValue, rows);
- }
-
- public boolean isLargeModel()
- {
- return largeModel;
- }
-
- public void setLargeModel(boolean large)
- {
- if (largeModel == large)
- return;
-
- boolean oldValue = largeModel;
- largeModel = large;
- firePropertyChange(LARGE_MODEL_PROPERTY, oldValue, large);
- }
-
- public int getRowHeight()
- {
-
- return rowHeight;
- }
-
- public void setRowHeight(int height)
- {
- if (rowHeight == height)
- return;
-
- int oldValue = rowHeight;
- rowHeight = height;
- firePropertyChange(ROW_HEIGHT_PROPERTY, oldValue, height);
- }
-
- public boolean isFixedRowHeight()
- {
- return rowHeight > 0;
- }
-
- public boolean getInvokesStopCellEditing()
- {
- return invokesStopCellEditing;
- }
-
- public void setInvokesStopCellEditing(boolean invoke)
- {
- if (invokesStopCellEditing == invoke)
- return;
-
- boolean oldValue = invokesStopCellEditing;
- invokesStopCellEditing = invoke;
- firePropertyChange(INVOKES_STOP_CELL_EDITING_PROPERTY,
- oldValue, invoke);
- }
-
- /**
- * @since 1.3
- */
- public int getToggleClickCount()
- {
- return toggleClickCount;
- }
+ /**
+ * Checks if this <code>JTree</code> object is editable.
+ *
+ * @return <code>true</code> if this tree object is editable,
+ * <code>false</code> otherwise
+ */
+ public boolean isEditable()
+ {
+ return editable;
+ }
- /**
- * @since 1.3
- */
- public void setToggleClickCount(int count)
- {
- if (toggleClickCount == count)
- return;
-
- int oldValue = toggleClickCount;
- toggleClickCount = count;
- firePropertyChange(TOGGLE_CLICK_COUNT_PROPERTY, oldValue, count);
- }
-
- public void scrollPathToVisible(TreePath path)
- {
- if (path == null)
- return;
+ /**
+ * Sets the <code>editable</code> property.
+ *
+ * @param flag <code>true</code> to make this tree object editable,
+ * <code>false</code> otherwise
+ */
+ public void setEditable(boolean flag)
+ {
+ if (editable == flag)
+ return;
- Rectangle rect = getPathBounds(path);
-
- if (rect == null)
- return;
-
- scrollRectToVisible(rect);
- }
+ boolean oldValue = editable;
+ editable = flag;
+ firePropertyChange(EDITABLE_PROPERTY, oldValue, editable);
+ }
- public void scrollRowToVisible(int row)
- {
- scrollPathToVisible(getPathForRow(row));
- }
-
- public boolean getScrollsOnExpand()
- {
- return scrollsOnExpand;
- }
-
- public void setScrollsOnExpand(boolean scroll)
- {
- if (scrollsOnExpand == scroll)
- return;
-
- boolean oldValue = scrollsOnExpand;
- scrollsOnExpand = scroll;
- firePropertyChange(SCROLLS_ON_EXPAND_PROPERTY, oldValue, scroll);
- }
-
- public void setSelectionPath(TreePath path)
- {
- selectionModel.setSelectionPath(path);
- }
-
- public void setSelectionPaths(TreePath[] paths)
- {
- selectionModel.setSelectionPaths(paths);
- }
-
- public void setSelectionRow(int row)
- {
- TreePath path = getPathForRow(row);
-
- if (path != null)
- selectionModel.setSelectionPath(path);
- }
-
- public void setSelectionRows(int[] rows)
- {
- // Make sure we have an UI so getPathForRow() does not return null.
- if (rows == null || getUI() == null)
- return;
-
- TreePath[] paths = new TreePath[rows.length];
-
- for (int i = rows.length - 1; i >= 0; --i)
- paths[i] = getPathForRow(rows[i]);
-
- setSelectionPaths(paths);
- }
-
- public void setSelectionInterval(int index0, int index1)
- {
- TreePath[] paths = getPathBetweenRows(index0, index1);
-
- if (paths != null)
- setSelectionPaths(paths);
- }
-
- public void addSelectionPath(TreePath path)
- {
- selectionModel.addSelectionPath(path);
- }
-
- public void addSelectionPaths(TreePath[] paths)
- {
- selectionModel.addSelectionPaths(paths);
- }
-
- public void addSelectionRow(int row)
- {
- TreePath path = getPathForRow(row);
-
- if (path != null)
- selectionModel.addSelectionPath(path);
- }
-
- public void addSelectionRows(int[] rows)
- {
- // Make sure we have an UI so getPathForRow() does not return null.
- if (rows == null || getUI() == null)
- return;
-
- TreePath[] paths = new TreePath[rows.length];
+ /**
+ * Checks if the root element is visible.
+ *
+ * @return <code>true</code> if the root element is visible,
+ * <code>false</code> otherwise
+ */
+ public boolean isRootVisible()
+ {
+ return rootVisible;
+ }
- for (int i = rows.length - 1; i >= 0; --i)
- paths[i] = getPathForRow(rows[i]);
-
- addSelectionPaths(paths);
- }
+ public void setRootVisible(boolean flag)
+ {
+ if (rootVisible == flag)
+ return;
- public void addSelectionInterval(int index0, int index1)
- {
- TreePath[] paths = getPathBetweenRows(index0, index1);
-
- if (paths != null)
- addSelectionPaths(paths);
- }
-
- public void removeSelectionPath(TreePath path)
- {
- selectionModel.removeSelectionPath(path);
- }
-
- public void removeSelectionPaths(TreePath[] paths)
- {
- selectionModel.removeSelectionPaths(paths);
- }
+ boolean oldValue = rootVisible;
+ rootVisible = flag;
+ firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, flag);
+ }
- public void removeSelectionRow(int row)
- {
- TreePath path = getPathForRow(row);
+ public boolean getShowsRootHandles()
+ {
+ return showsRootHandles;
+ }
- if (path != null)
- selectionModel.removeSelectionPath(path);
- }
+ public void setShowsRootHandles(boolean flag)
+ {
+ if (showsRootHandles == flag)
+ return;
+
+ boolean oldValue = showsRootHandles;
+ showsRootHandles = flag;
+ firePropertyChange(SHOWS_ROOT_HANDLES_PROPERTY, oldValue, flag);
+ }
- public void removeSelectionRows(int[] rows)
- {
- if (rows == null || getUI() == null)
- return;
+ public TreeCellEditor getCellEditor()
+ {
+ return cellEditor;
+ }
- TreePath[] paths = new TreePath[rows.length];
+ public void setCellEditor(TreeCellEditor editor)
+ {
+ if (cellEditor == editor)
+ return;
- for (int i = rows.length - 1; i >= 0; --i)
- paths[i] = getPathForRow(rows[i]);
+ TreeCellEditor oldValue = cellEditor;
+ cellEditor = editor;
+ firePropertyChange(CELL_EDITOR_PROPERTY, oldValue, editor);
+ }
- removeSelectionPaths(paths);
- }
+ public TreeCellRenderer getCellRenderer()
+ {
+ return cellRenderer;
+ }
- public void removeSelectionInterval(int index0, int index1)
- {
- TreePath[] paths = getPathBetweenRows(index0, index1);
+ public void setCellRenderer(TreeCellRenderer newRenderer)
+ {
+ if (cellRenderer == newRenderer)
+ return;
- if (paths != null)
- removeSelectionPaths(paths);
- }
+ TreeCellRenderer oldValue = cellRenderer;
+ cellRenderer = newRenderer;
+ firePropertyChange(CELL_RENDERER_PROPERTY, oldValue, newRenderer);
+ }
- public void clearSelection()
- {
- selectionModel.clearSelection();
- setLeadSelectionPath(null);
- }
+ public TreeSelectionModel getSelectionModel()
+ {
+ return selectionModel;
+ }
- public TreePath getLeadSelectionPath()
- {
- return leadSelectionPath;
- }
+ public void setSelectionModel(TreeSelectionModel model)
+ {
+ if (selectionModel == model)
+ return;
- /**
- * @since 1.3
- */
- public void setLeadSelectionPath(TreePath path)
- {
- if (leadSelectionPath == path)
- return;
-
- TreePath oldValue = leadSelectionPath;
- leadSelectionPath = path;
- firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, path);
- }
-
- /**
- * @since 1.3
- */
- public TreePath getAnchorSelectionPath()
- {
- return anchorSelectionPath;
- }
+ if (selectionModel != null)
+ selectionModel.removeTreeSelectionListener(selectionRedirector);
- /**
- * @since 1.3
- */
- public void setAnchorSelectionPath(TreePath path)
- {
- if (anchorSelectionPath == path)
- return;
-
- TreePath oldValue = anchorSelectionPath;
- anchorSelectionPath = path;
- firePropertyChange(ANCHOR_SELECTION_PATH_PROPERTY, oldValue, path);
- }
-
- public int getLeadSelectionRow()
- {
- return selectionModel.getLeadSelectionRow();
- }
-
- public int getMaxSelectionRow()
- {
- return selectionModel.getMaxSelectionRow();
- }
-
- public int getMinSelectionRow()
- {
- return selectionModel.getMinSelectionRow();
- }
-
- public int getSelectionCount()
- {
- return selectionModel.getSelectionCount();
- }
-
- public TreePath getSelectionPath()
- {
- return selectionModel.getSelectionPath();
- }
-
- public TreePath[] getSelectionPaths()
- {
- return selectionModel.getSelectionPaths();
- }
-
- public int[] getSelectionRows()
- {
- return selectionModel.getSelectionRows();
- }
-
- public boolean isPathSelected(TreePath path)
- {
- return selectionModel.isPathSelected(path);
- }
-
- public boolean isRowSelected(int row)
- {
- return selectionModel.isPathSelected(getPathForRow(row));
- }
-
- public boolean isSelectionEmpty()
- {
- return selectionModel.isSelectionEmpty();
- }
-
- /**
- * Return the value of the <code>dragEnabled</code> property.
- *
- * @return the value
- *
- * @since 1.4
- */
- public boolean getDragEnabled()
- {
- return dragEnabled;
- }
-
- /**
- * Set the <code>dragEnabled</code> property.
- *
- * @param enabled new value
- *
- * @since 1.4
- */
- public void setDragEnabled(boolean enabled)
- {
+ TreeSelectionModel oldValue = selectionModel;
+ selectionModel = model;
- dragEnabled = enabled;
- }
+ if (selectionModel != null)
+ selectionModel.addTreeSelectionListener(selectionRedirector);
- public int getRowCount()
- {
- TreeUI ui = getUI();
+ firePropertyChange(SELECTION_MODEL_PROPERTY, oldValue, model);
+ revalidate();
+ repaint();
+ }
- if (ui != null)
- return ui.getRowCount(this);
+ public int getVisibleRowCount()
+ {
+ return visibleRowCount;
+ }
- return 0;
- }
+ public void setVisibleRowCount(int rows)
+ {
+ if (visibleRowCount == rows)
+ return;
- public void collapsePath(TreePath path)
- {
- try
- {
- fireTreeWillCollapse(path);
- }
- catch (ExpandVetoException ev)
- {
- }
- setExpandedState(path, false);
- fireTreeCollapsed(path);
- }
+ int oldValue = visibleRowCount;
+ visibleRowCount = rows;
+ firePropertyChange(VISIBLE_ROW_COUNT_PROPERTY, oldValue, rows);
+ }
- public void collapseRow(int row)
- {
- if (row < 0 || row >= getRowCount())
- return;
+ public boolean isLargeModel()
+ {
+ return largeModel;
+ }
- TreePath path = getPathForRow(row);
+ public void setLargeModel(boolean large)
+ {
+ if (largeModel == large)
+ return;
- if (path != null)
- collapsePath(path);
- }
+ boolean oldValue = largeModel;
+ largeModel = large;
+ firePropertyChange(LARGE_MODEL_PROPERTY, oldValue, large);
+ }
- public void expandPath(TreePath path)
- {
- // Don't expand if last path component is a leaf node.
- if ((path == null) || (treeModel.isLeaf(path.getLastPathComponent())))
- return;
-
- try
- {
- fireTreeWillExpand(path);
- }
- catch (ExpandVetoException ev)
- {
- }
-
- setExpandedState(path, true);
- fireTreeExpanded(path);
- }
+ public int getRowHeight()
+ {
+ return rowHeight;
+ }
- public void expandRow(int row)
- {
- if (row < 0 || row >= getRowCount())
- return;
+ public void setRowHeight(int height)
+ {
+ if (rowHeight == height)
+ return;
- TreePath path = getPathForRow(row);
+ int oldValue = rowHeight;
+ rowHeight = height;
+ firePropertyChange(ROW_HEIGHT_PROPERTY, oldValue, height);
+ }
- if (path != null)
- expandPath(path);
- }
+ public boolean isFixedRowHeight()
+ {
+ return rowHeight > 0;
+ }
- public boolean isCollapsed(TreePath path)
- {
- return !isExpanded(path);
- }
+ public boolean getInvokesStopCellEditing()
+ {
+ return invokesStopCellEditing;
+ }
- public boolean isCollapsed(int row)
- {
- if (row < 0 || row >= getRowCount())
- return false;
+ public void setInvokesStopCellEditing(boolean invoke)
+ {
+ if (invokesStopCellEditing == invoke)
+ return;
- TreePath path = getPathForRow(row);
+ boolean oldValue = invokesStopCellEditing;
+ invokesStopCellEditing = invoke;
+ firePropertyChange(INVOKES_STOP_CELL_EDITING_PROPERTY,
+ oldValue, invoke);
+ }
- if (path != null)
- return isCollapsed(path);
+ /**
+ * @since 1.3
+ */
+ public int getToggleClickCount()
+ {
+ return toggleClickCount;
+ }
- return false;
- }
+ /**
+ * @since 1.3
+ */
+ public void setToggleClickCount(int count)
+ {
+ if (toggleClickCount == count)
+ return;
- public boolean isExpanded(TreePath path)
- {
- if (path == null)
- return false;
+ int oldValue = toggleClickCount;
+ toggleClickCount = count;
+ firePropertyChange(TOGGLE_CLICK_COUNT_PROPERTY, oldValue, count);
+ }
- Object state = nodeStates.get(path);
+ public void scrollPathToVisible(TreePath path)
+ {
+ if (path == null)
+ return;
+
+ Object[] oPath = path.getPath();
+ TreePath temp = new TreePath(oPath[0]);
+ boolean stop = false;
+ int i = 1;
+ while (!stop)
+ {
+ while (isVisible(temp))
+ if (i < oPath.length)
+ temp = temp.pathByAddingChild(oPath[i++]);
+ else
+ {
+ stop = true;
+ break;
+ }
+ makeVisible(temp);
+ }
+ Rectangle rect = getPathBounds(path);
+ scrollRectToVisible(rect);
+ revalidate();
+ repaint();
+ }
- if ((state == null) || (state != EXPANDED))
- return false;
+ public void scrollRowToVisible(int row)
+ {
+ scrollPathToVisible(getPathForRow(row));
+ }
- TreePath parent = path.getParentPath();
+ public boolean getScrollsOnExpand()
+ {
+ return scrollsOnExpand;
+ }
- if (parent != null)
- return isExpanded(parent);
+ public void setScrollsOnExpand(boolean scroll)
+ {
+ if (scrollsOnExpand == scroll)
+ return;
- return true;
- }
+ boolean oldValue = scrollsOnExpand;
+ scrollsOnExpand = scroll;
+ firePropertyChange(SCROLLS_ON_EXPAND_PROPERTY, oldValue, scroll);
+ }
- public boolean isExpanded(int row)
- {
- if (row < 0 || row >= getRowCount())
- return false;
+ public void setSelectionPath(TreePath path)
+ {
+ selectionModel.setSelectionPath(path);
+ }
- TreePath path = getPathForRow(row);
+ public void setSelectionPaths(TreePath[] paths)
+ {
+ selectionModel.setSelectionPaths(paths);
+ }
- if (path != null)
- return isExpanded(path);
+ public void setSelectionRow(int row)
+ {
+ TreePath path = getPathForRow(row);
- return false;
- }
+ if (path != null)
+ selectionModel.setSelectionPath(path);
+ }
- /**
- * @since 1.3
- */
- public boolean getExpandsSelectedPaths()
- {
- return expandsSelectedPaths;
- }
+ public void setSelectionRows(int[] rows)
+ {
+ // Make sure we have an UI so getPathForRow() does not return null.
+ if (rows == null || getUI() == null)
+ return;
- /**
- * @since 1.3
- */
- public void setExpandsSelectedPaths(boolean flag)
- {
- if (expandsSelectedPaths == flag)
- return;
+ TreePath[] paths = new TreePath[rows.length];
- boolean oldValue = expandsSelectedPaths;
- expandsSelectedPaths = flag;
- firePropertyChange(EXPANDS_SELECTED_PATHS_PROPERTY, oldValue, flag);
- }
+ for (int i = rows.length - 1; i >= 0; --i)
+ paths[i] = getPathForRow(rows[i]);
- public Rectangle getPathBounds(TreePath path)
- {
- TreeUI ui = getUI();
+ setSelectionPaths(paths);
+ }
- if (ui == null)
- return null;
+ public void setSelectionInterval(int index0, int index1)
+ {
+ TreePath[] paths = getPathBetweenRows(index0, index1);
- return ui.getPathBounds(this, path);
- }
+ if (paths != null)
+ setSelectionPaths(paths);
+ }
- public Rectangle getRowBounds(int row)
- {
- TreePath path = getPathForRow(row);
+ public void addSelectionPath(TreePath path)
+ {
+ selectionModel.addSelectionPath(path);
+ }
- if (path != null)
- return getPathBounds(path);
+ public void addSelectionPaths(TreePath[] paths)
+ {
+ selectionModel.addSelectionPaths(paths);
+ }
- return null;
- }
+ public void addSelectionRow(int row)
+ {
+ TreePath path = getPathForRow(row);
- public boolean isEditing()
- {
- TreeUI ui = getUI();
+ if (path != null)
+ selectionModel.addSelectionPath(path);
+ }
- if (ui != null)
- return ui.isEditing(this);
+ public void addSelectionRows(int[] rows)
+ {
+ // Make sure we have an UI so getPathForRow() does not return null.
+ if (rows == null || getUI() == null)
+ return;
- return false;
- }
+ TreePath[] paths = new TreePath[rows.length];
- public boolean stopEditing()
- {
- TreeUI ui = getUI();
+ for (int i = rows.length - 1; i >= 0; --i)
+ paths[i] = getPathForRow(rows[i]);
- if (ui != null)
- return ui.stopEditing(this);
+ addSelectionPaths(paths);
+ }
- return false;
- }
+ public void addSelectionInterval(int index0, int index1)
+ {
+ TreePath[] paths = getPathBetweenRows(index0, index1);
- public void cancelEditing()
- {
- TreeUI ui = getUI();
+ if (paths != null)
+ addSelectionPaths(paths);
+ }
- if (ui != null)
- ui.cancelEditing(this);
- }
+ public void removeSelectionPath(TreePath path)
+ {
+ selectionModel.removeSelectionPath(path);
+ }
- public void startEditingAtPath(TreePath path)
- {
- TreeUI ui = getUI();
+ public void removeSelectionPaths(TreePath[] paths)
+ {
+ selectionModel.removeSelectionPaths(paths);
+ }
- if (ui != null)
- ui.startEditingAtPath(this, path);
- }
+ public void removeSelectionRow(int row)
+ {
+ TreePath path = getPathForRow(row);
- public TreePath getEditingPath()
- {
- TreeUI ui = getUI();
+ if (path != null)
+ selectionModel.removeSelectionPath(path);
+ }
- if (ui != null)
- return ui.getEditingPath(this);
+ public void removeSelectionRows(int[] rows)
+ {
+ if (rows == null || getUI() == null)
+ return;
- return null;
- }
+ TreePath[] paths = new TreePath[rows.length];
- public TreePath getPathForLocation(int x, int y)
- {
- TreePath path = getClosestPathForLocation(x, y);
+ for (int i = rows.length - 1; i >= 0; --i)
+ paths[i] = getPathForRow(rows[i]);
- if (path != null)
- {
- Rectangle rect = getPathBounds(path);
+ removeSelectionPaths(paths);
+ }
- if ((rect != null) && rect.contains(x, y))
- return path;
- }
+ public void removeSelectionInterval(int index0, int index1)
+ {
+ TreePath[] paths = getPathBetweenRows(index0, index1);
- return null;
- }
+ if (paths != null)
+ removeSelectionPaths(paths);
+ }
- public int getRowForLocation(int x, int y)
- {
- TreePath path = getPathForLocation(x, y);
+ public void clearSelection()
+ {
+ selectionModel.clearSelection();
+ setLeadSelectionPath(null);
+ }
- if (path != null)
- return getRowForPath(path);
+ public TreePath getLeadSelectionPath()
+ {
+ return leadSelectionPath;
+ }
- return -1;
- }
+ /**
+ * @since 1.3
+ */
+ public void setLeadSelectionPath(TreePath path)
+ {
+ if (leadSelectionPath == path)
+ return;
+
+ TreePath oldValue = leadSelectionPath;
+ leadSelectionPath = path;
+ firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, path);
+ }
- public TreePath getClosestPathForLocation(int x, int y)
- {
- TreeUI ui = getUI();
+ /**
+ * @since 1.3
+ */
+ public TreePath getAnchorSelectionPath()
+ {
+ return anchorSelectionPath;
+ }
- if (ui != null)
- return ui.getClosestPathForLocation(this, x, y);
+ /**
+ * @since 1.3
+ */
+ public void setAnchorSelectionPath(TreePath path)
+ {
+ if (anchorSelectionPath == path)
+ return;
- return null;
- }
+ TreePath oldValue = anchorSelectionPath;
+ anchorSelectionPath = path;
+ firePropertyChange(ANCHOR_SELECTION_PATH_PROPERTY, oldValue, path);
+ }
- public int getClosestRowForLocation(int x, int y)
- {
- TreePath path = getClosestPathForLocation(x, y);
+ public int getLeadSelectionRow()
+ {
+ return selectionModel.getLeadSelectionRow();
+ }
- if (path != null)
- return getRowForPath(path);
+ public int getMaxSelectionRow()
+ {
+ return selectionModel.getMaxSelectionRow();
+ }
- return -1;
- }
+ public int getMinSelectionRow()
+ {
+ return selectionModel.getMinSelectionRow();
+ }
- public Object getLastSelectedPathComponent()
- {
- TreePath path = getSelectionPath();
+ public int getSelectionCount()
+ {
+ return selectionModel.getSelectionCount();
+ }
- if (path != null)
- return path.getLastPathComponent();
+ public TreePath getSelectionPath()
+ {
+ return selectionModel.getSelectionPath();
+ }
- return null;
- }
+ public TreePath[] getSelectionPaths()
+ {
+ return selectionModel.getSelectionPaths();
+ }
- private void doExpandParents(TreePath path, boolean state)
- {
- TreePath parent = path.getParentPath();
-
- if (!isExpanded(parent) && parent != null)
- doExpandParents(parent, false);
+ public int[] getSelectionRows()
+ {
+ return selectionModel.getSelectionRows();
+ }
- nodeStates.put(path, state ? EXPANDED : COLLAPSED);
- }
+ public boolean isPathSelected(TreePath path)
+ {
+ return selectionModel.isPathSelected(path);
+ }
- protected void setExpandedState(TreePath path, boolean state)
- {
- if (path == null)
- return;
- TreePath parent = path.getParentPath();
+ public boolean isRowSelected(int row)
+ {
+ return selectionModel.isPathSelected(getPathForRow(row));
+ }
- doExpandParents(path, state);
- }
+ public boolean isSelectionEmpty()
+ {
+ return selectionModel.isSelectionEmpty();
+ }
- protected void clearToggledPaths()
- {
- nodeStates.clear();
- }
+ /**
+ * Return the value of the <code>dragEnabled</code> property.
+ *
+ * @return the value
+ *
+ * @since 1.4
+ */
+ public boolean getDragEnabled()
+ {
+ return dragEnabled;
+ }
- protected Enumeration getDescendantToggledPaths(TreePath parent)
- {
- if (parent == null)
- return null;
+ /**
+ * Set the <code>dragEnabled</code> property.
+ *
+ * @param enabled new value
+ *
+ * @since 1.4
+ */
+ public void setDragEnabled(boolean enabled)
+ {
+ dragEnabled = enabled;
+ }
- Enumeration nodes = nodeStates.keys();
- Vector result = new Vector();
+ public int getRowCount()
+ {
+ TreeUI ui = getUI();
- while (nodes.hasMoreElements())
- {
- TreePath path = (TreePath) nodes.nextElement();
+ if (ui != null)
+ return ui.getRowCount(this);
- if (path.isDescendant(parent))
- result.addElement(path);
- }
+ return 0;
+ }
- return result.elements();
- }
+ public void collapsePath(TreePath path)
+ {
+ try
+ {
+ fireTreeWillCollapse(path);
+ }
+ catch (ExpandVetoException ev)
+ {
+ // We do nothing if attempt has been vetoed.
+ }
+ setExpandedState(path, false);
+ fireTreeCollapsed(path);
+ }
- public boolean hasBeenExpanded(TreePath path)
- {
- if (path == null)
- return false;
+ public void collapseRow(int row)
+ {
+ if (row < 0 || row >= getRowCount())
+ return;
- return nodeStates.get(path) != null;
- }
+ TreePath path = getPathForRow(row);
- public boolean isVisible(TreePath path)
- {
- if (path == null)
- return false;
+ if (path != null)
+ collapsePath(path);
+ }
- TreePath parent = path.getParentPath();
+ public void expandPath(TreePath path)
+ {
+ // Don't expand if path is null
+ if (path == null)
+ return;
+
+ try
+ {
+ fireTreeWillExpand(path);
+ }
+ catch (ExpandVetoException ev)
+ {
+ // We do nothing if attempt has been vetoed.
+ }
+
+ setExpandedState(path, true);
+ fireTreeExpanded(path);
+ }
- if (parent == null)
- return true; // Is root node.
+ public void expandRow(int row)
+ {
+ if (row < 0 || row >= getRowCount())
+ return;
- return isExpanded(parent);
- }
+ TreePath path = getPathForRow(row);
- public void makeVisible(TreePath path)
- {
- if (path == null)
- return;
+ if (path != null)
+ expandPath(path);
+ }
- expandPath(path.getParentPath());
- }
+ public boolean isCollapsed(TreePath path)
+ {
+ return !isExpanded(path);
+ }
- public boolean isPathEditable(TreePath path)
- {
- return isEditable();
- }
+ public boolean isCollapsed(int row)
+ {
+ if (row < 0 || row >= getRowCount())
+ return false;
- /**
- * Creates and returns an instance of {@link TreeModelHandler}.
- *
- * @returns an instance of {@link TreeModelHandler}
- */
- protected TreeModelListener createTreeModelListener()
- {
- return new TreeModelHandler();
- }
-
- /**
- * Returns a sample TreeModel that can be used in a JTree. This can be used
- * in Bean- or GUI-Builders to show something interesting.
- *
- * @return a sample TreeModel that can be used in a JTree
- */
- protected static TreeModel getDefaultTreeModel()
- {
- DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root node");
- DefaultMutableTreeNode child1 = new DefaultMutableTreeNode(
- "Child node 1");
- DefaultMutableTreeNode child11 = new DefaultMutableTreeNode(
- "Child node 1.1");
- DefaultMutableTreeNode child12 = new DefaultMutableTreeNode(
- "Child node 1.2");
- DefaultMutableTreeNode child13 = new DefaultMutableTreeNode(
- "Child node 1.3");
- DefaultMutableTreeNode child2 = new DefaultMutableTreeNode(
- "Child node 2");
- DefaultMutableTreeNode child21 = new DefaultMutableTreeNode(
- "Child node 2.1");
- DefaultMutableTreeNode child22 = new DefaultMutableTreeNode(
- "Child node 2.2");
- DefaultMutableTreeNode child23 = new DefaultMutableTreeNode(
- "Child node 2.3");
- DefaultMutableTreeNode child24 = new DefaultMutableTreeNode(
- "Child node 2.4");
-
- DefaultMutableTreeNode child3 = new DefaultMutableTreeNode(
- "Child node 3");
- root.add(child1);
- root.add(child2);
- root.add(child3);
- child1.add(child11);
- child1.add(child12);
- child1.add(child13);
- child2.add(child21);
- child2.add(child22);
- child2.add(child23);
- child2.add(child24);
- return new DefaultTreeModel(root);
- }
-
- /**
- * Converts the specified value to a String. This is used by the renderers
- * of this JTree and its nodes.
- *
- * This implementation simply returns <code>value.toString()</code> and
- * ignores all other parameters. Subclass this method to control the
- * conversion.
- *
- * @param value the value that is converted to a String
- * @param selected indicates if that value is selected or not
- * @param expanded indicates if that value is expanded or not
- * @param leaf indicates if that value is a leaf node or not
- * @param row the row of the node
- * @param hasFocus indicates if that node has focus or not
- */
- public String convertValueToText(Object value, boolean selected,
- boolean expanded, boolean leaf, int row, boolean hasFocus)
- {
- return value.toString();
- }
-
- /**
- * A String representation of this JTree. This is intended to be used for
- * debugging. The returned string may be empty but may not be
- * <code>null</code>.
- *
- * @return a String representation of this JTree
- */
- public String paramString()
- {
- // TODO: this is completely legal, but it would possibly be nice
- // to return some more content, like the tree structure, some properties
- // etc ...
- return "";
- }
-
- /**
- * Returns all TreePath objects which are a descendants of the given path
- * and are exapanded at the moment of the execution of this method. If the
- * state of any node is beeing toggled while this method is executing this
- * change may be left unaccounted.
- *
- * @param path The parent of this request
- * @return An Enumeration containing TreePath objects
- */
- public Enumeration getExpandedDescendants(TreePath path)
- {
- Enumeration paths = nodeStates.keys();
- Vector relevantPaths = new Vector();
- while (paths.hasMoreElements())
- {
- TreePath nextPath = (TreePath) paths.nextElement();
- if (nodeStates.get(nextPath) == EXPANDED
- && path.isDescendant(nextPath))
- {
- relevantPaths.add(nextPath);
- }
- }
- return relevantPaths.elements();
- }
-
- /**
- * Returns the next table element (beginning from the row
- * <code>startingRow</code> that starts with <code>prefix</code>.
- * Searching is done in the direction specified by <code>bias</code>.
- *
- * @param prefix the prefix to search for in the cell values
- * @param startingRow the index of the row where to start searching from
- * @param bias the search direction, either {@link Position.Bias#Forward} or
- * {@link Position.Bias#Backward}
- *
- * @return the path to the found element or -1 if no such element has been
- * found
- *
- * @throws IllegalArgumentException if prefix is <code>null</code> or
- * startingRow is not valid
- *
- * @since 1.4
- */
- public TreePath getNextMatch(String prefix, int startingRow,
- Position.Bias bias)
- {
- if (prefix == null)
- throw new IllegalArgumentException(
- "The argument 'prefix' must not be" + " null.");
- if (startingRow < 0)
- throw new IllegalArgumentException(
- "The argument 'startingRow' must not"
- + " be less than zero.");
-
- int size = getRowCount();
- if (startingRow > size)
- throw new IllegalArgumentException(
- "The argument 'startingRow' must not"
- + " be greater than the number of"
- + " elements in the TreeModel.");
-
- TreePath foundPath = null;
- if (bias == Position.Bias.Forward)
- {
- for (int i = startingRow; i < size; i++)
- {
- TreePath path = getPathForRow(i);
- Object o = path.getLastPathComponent();
- // FIXME: in the following call to convertValueToText the
- // last argument (hasFocus) should be done right.
- String item = convertValueToText(o, isRowSelected(i),
- isExpanded(i), treeModel.isLeaf(o), i, false);
- if (item.startsWith(prefix))
- {
- foundPath = path;
- break;
- }
- }
- } else
- {
- for (int i = startingRow; i >= 0; i--)
- {
- TreePath path = getPathForRow(i);
- Object o = path.getLastPathComponent();
- // FIXME: in the following call to convertValueToText the
- // last argument (hasFocus) should be done right.
- String item = convertValueToText(o, isRowSelected(i),
- isExpanded(i), treeModel.isLeaf(o), i, false);
- if (item.startsWith(prefix))
- {
- foundPath = path;
- break;
- }
- }
- }
- return foundPath;
- }
-
- /**
- * Removes any paths in the current set of selected paths that are
- * descendants of <code>path</code>. If <code>includePath</code> is set
- * to <code>true</code> and <code>path</code> itself is selected, then
- * it will be removed too.
- *
- * @param path the path from which selected descendants are to be removed
- * @param includeSelected if <code>true</code> then <code>path</code> itself
- * will also be remove if it's selected
- *
- * @return <code>true</code> if something has been removed,
- * <code>false</code> otherwise
- *
- * @since 1.3
- */
- protected boolean removeDescendantSelectedPaths(TreePath path,
- boolean includeSelected)
- {
- boolean removedSomething = false;
- TreePath[] selected = getSelectionPaths();
- for (int index = 0; index < selected.length; index++)
- {
- if ((selected[index] == path && includeSelected)
- || (selected[index].isDescendant(path)))
- {
- removeSelectionPath(selected[index]);
- removedSomething = true;
- }
- }
- return removedSomething;
- }
+ TreePath path = getPathForRow(row);
+
+ if (path != null)
+ return isCollapsed(path);
+
+ return false;
+ }
+
+ public boolean isExpanded(TreePath path)
+ {
+ if (path == null)
+ return false;
+
+ Object state = nodeStates.get(path);
+
+ if ((state == null) || (state != EXPANDED))
+ return false;
+
+ TreePath parent = path.getParentPath();
+
+ if (parent != null)
+ return isExpanded(parent);
+
+ return true;
+ }
+
+ public boolean isExpanded(int row)
+ {
+ if (row < 0 || row >= getRowCount())
+ return false;
+
+ TreePath path = getPathForRow(row);
+
+ if (path != null)
+ return isExpanded(path);
+
+ return false;
+ }
+
+ /**
+ * @since 1.3
+ */
+ public boolean getExpandsSelectedPaths()
+ {
+ return expandsSelectedPaths;
+ }
+
+ /**
+ * @since 1.3
+ */
+ public void setExpandsSelectedPaths(boolean flag)
+ {
+ if (expandsSelectedPaths == flag)
+ return;
+
+ boolean oldValue = expandsSelectedPaths;
+ expandsSelectedPaths = flag;
+ firePropertyChange(EXPANDS_SELECTED_PATHS_PROPERTY, oldValue, flag);
+ }
+
+ public Rectangle getPathBounds(TreePath path)
+ {
+ TreeUI ui = getUI();
+
+ if (ui == null)
+ return null;
+
+ return ui.getPathBounds(this, path);
+ }
+
+ public Rectangle getRowBounds(int row)
+ {
+ TreePath path = getPathForRow(row);
+
+ if (path != null)
+ return getPathBounds(path);
+
+ return null;
+ }
+
+ public boolean isEditing()
+ {
+ TreeUI ui = getUI();
+
+ if (ui != null)
+ return ui.isEditing(this);
+
+ return false;
+ }
+
+ public boolean stopEditing()
+ {
+ TreeUI ui = getUI();
+
+ if (ui != null)
+ return ui.stopEditing(this);
+
+ return false;
+ }
+
+ public void cancelEditing()
+ {
+ TreeUI ui = getUI();
+
+ if (ui != null)
+ ui.cancelEditing(this);
+ }
+
+ public void startEditingAtPath(TreePath path)
+ {
+ TreeUI ui = getUI();
+
+ if (ui != null)
+ ui.startEditingAtPath(this, path);
+ }
+
+ public TreePath getEditingPath()
+ {
+ TreeUI ui = getUI();
+
+ if (ui != null)
+ return ui.getEditingPath(this);
+
+ return null;
+ }
+
+ public TreePath getPathForLocation(int x, int y)
+ {
+ TreePath path = getClosestPathForLocation(x, y);
+
+ if (path != null)
+ {
+ Rectangle rect = getPathBounds(path);
+
+ if ((rect != null) && rect.contains(x, y))
+ return path;
+ }
+
+ return null;
+ }
+
+ public int getRowForLocation(int x, int y)
+ {
+ TreePath path = getPathForLocation(x, y);
+
+ if (path != null)
+ return getRowForPath(path);
+
+ return -1;
+ }
+
+ public TreePath getClosestPathForLocation(int x, int y)
+ {
+ TreeUI ui = getUI();
+
+ if (ui != null)
+ return ui.getClosestPathForLocation(this, x, y);
+
+ return null;
+ }
+
+ public int getClosestRowForLocation(int x, int y)
+ {
+ TreePath path = getClosestPathForLocation(x, y);
+
+ if (path != null)
+ return getRowForPath(path);
+
+ return -1;
+ }
+
+ public Object getLastSelectedPathComponent()
+ {
+ TreePath path = getSelectionPath();
+
+ if (path != null)
+ return path.getLastPathComponent();
+
+ return null;
+ }
+
+ private void doExpandParents(TreePath path, boolean state)
+ {
+ TreePath parent = path.getParentPath();
+
+ if (!isExpanded(parent) && parent != null)
+ doExpandParents(parent, false);
+
+ nodeStates.put(path, state ? EXPANDED : COLLAPSED);
+ }
+
+ protected void setExpandedState(TreePath path, boolean state)
+ {
+ if (path == null)
+ return;
+
+ doExpandParents(path, state);
+ }
+
+ protected void clearToggledPaths()
+ {
+ nodeStates.clear();
+ }
+
+ protected Enumeration getDescendantToggledPaths(TreePath parent)
+ {
+ if (parent == null)
+ return null;
+
+ Enumeration nodes = nodeStates.keys();
+ Vector result = new Vector();
+
+ while (nodes.hasMoreElements())
+ {
+ TreePath path = (TreePath) nodes.nextElement();
+
+ if (path.isDescendant(parent))
+ result.addElement(path);
+ }
+
+ return result.elements();
+ }
+
+ public boolean hasBeenExpanded(TreePath path)
+ {
+ if (path == null)
+ return false;
+
+ return nodeStates.get(path) != null;
+ }
+
+ public boolean isVisible(TreePath path)
+ {
+ if (path == null)
+ return false;
+
+ TreePath parent = path.getParentPath();
+
+ if (parent == null)
+ return true; // Is root node.
+
+ return isExpanded(parent);
+ }
+
+ public void makeVisible(TreePath path)
+ {
+ if (path == null)
+ return;
+
+ expandPath(path.getParentPath());
+ }
+
+ public boolean isPathEditable(TreePath path)
+ {
+ return isEditable();
+ }
+
+ /**
+ * Creates and returns an instance of {@link TreeModelHandler}.
+ *
+ * @return an instance of {@link TreeModelHandler}
+ */
+ protected TreeModelListener createTreeModelListener()
+ {
+ return new TreeModelHandler();
+ }
+
+ /**
+ * Returns a sample TreeModel that can be used in a JTree. This can be used
+ * in Bean- or GUI-Builders to show something interesting.
+ *
+ * @return a sample TreeModel that can be used in a JTree
+ */
+ protected static TreeModel getDefaultTreeModel()
+ {
+ DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root node");
+ DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child node 1");
+ DefaultMutableTreeNode child11 =
+ new DefaultMutableTreeNode("Child node 1.1");
+ DefaultMutableTreeNode child12 =
+ new DefaultMutableTreeNode("Child node 1.2");
+ DefaultMutableTreeNode child13 =
+ new DefaultMutableTreeNode("Child node 1.3");
+ DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child node 2");
+ DefaultMutableTreeNode child21 =
+ new DefaultMutableTreeNode("Child node 2.1");
+ DefaultMutableTreeNode child22 =
+ new DefaultMutableTreeNode("Child node 2.2");
+ DefaultMutableTreeNode child23 =
+ new DefaultMutableTreeNode("Child node 2.3");
+ DefaultMutableTreeNode child24 =
+ new DefaultMutableTreeNode("Child node 2.4");
+
+ DefaultMutableTreeNode child3 = new DefaultMutableTreeNode("Child node 3");
+ root.add(child1);
+ root.add(child2);
+ root.add(child3);
+ child1.add(child11);
+ child1.add(child12);
+ child1.add(child13);
+ child2.add(child21);
+ child2.add(child22);
+ child2.add(child23);
+ child2.add(child24);
+ return new DefaultTreeModel(root);
+ }
+
+ /**
+ * Converts the specified value to a String. This is used by the renderers
+ * of this JTree and its nodes.
+ *
+ * This implementation simply returns <code>value.toString()</code> and
+ * ignores all other parameters. Subclass this method to control the
+ * conversion.
+ *
+ * @param value the value that is converted to a String
+ * @param selected indicates if that value is selected or not
+ * @param expanded indicates if that value is expanded or not
+ * @param leaf indicates if that value is a leaf node or not
+ * @param row the row of the node
+ * @param hasFocus indicates if that node has focus or not
+ */
+ public String convertValueToText(Object value, boolean selected,
+ boolean expanded, boolean leaf, int row, boolean hasFocus)
+ {
+ return value.toString();
+ }
+
+ /**
+ * A String representation of this JTree. This is intended to be used for
+ * debugging. The returned string may be empty but may not be
+ * <code>null</code>.
+ *
+ * @return a String representation of this JTree
+ */
+ public String paramString()
+ {
+ // TODO: this is completely legal, but it would possibly be nice
+ // to return some more content, like the tree structure, some properties
+ // etc ...
+ return "";
+ }
+
+ /**
+ * Returns all TreePath objects which are a descendants of the given path
+ * and are exapanded at the moment of the execution of this method. If the
+ * state of any node is beeing toggled while this method is executing this
+ * change may be left unaccounted.
+ *
+ * @param path The parent of this request
+ *
+ * @return An Enumeration containing TreePath objects
+ */
+ public Enumeration getExpandedDescendants(TreePath path)
+ {
+ Enumeration paths = nodeStates.keys();
+ Vector relevantPaths = new Vector();
+ while (paths.hasMoreElements())
+ {
+ TreePath nextPath = (TreePath) paths.nextElement();
+ if (nodeStates.get(nextPath) == EXPANDED
+ && path.isDescendant(nextPath))
+ {
+ relevantPaths.add(nextPath);
+ }
+ }
+ return relevantPaths.elements();
+ }
+
+ /**
+ * Returns the next table element (beginning from the row
+ * <code>startingRow</code> that starts with <code>prefix</code>.
+ * Searching is done in the direction specified by <code>bias</code>.
+ *
+ * @param prefix the prefix to search for in the cell values
+ * @param startingRow the index of the row where to start searching from
+ * @param bias the search direction, either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward}
+ *
+ * @return the path to the found element or -1 if no such element has been
+ * found
+ *
+ * @throws IllegalArgumentException if prefix is <code>null</code> or
+ * startingRow is not valid
+ *
+ * @since 1.4
+ */
+ public TreePath getNextMatch(String prefix, int startingRow,
+ Position.Bias bias)
+ {
+ if (prefix == null)
+ throw new IllegalArgumentException("The argument 'prefix' must not be"
+ + " null.");
+ if (startingRow < 0)
+ throw new IllegalArgumentException("The argument 'startingRow' must not"
+ + " be less than zero.");
+
+ int size = getRowCount();
+ if (startingRow > size)
+ throw new IllegalArgumentException("The argument 'startingRow' must not"
+ + " be greater than the number of"
+ + " elements in the TreeModel.");
+
+ TreePath foundPath = null;
+ if (bias == Position.Bias.Forward)
+ {
+ for (int i = startingRow; i < size; i++)
+ {
+ TreePath path = getPathForRow(i);
+ Object o = path.getLastPathComponent();
+ // FIXME: in the following call to convertValueToText the
+ // last argument (hasFocus) should be done right.
+ String item = convertValueToText(o, isRowSelected(i),
+ isExpanded(i), treeModel.isLeaf(o),
+ i, false);
+ if (item.startsWith(prefix))
+ {
+ foundPath = path;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (int i = startingRow; i >= 0; i--)
+ {
+ TreePath path = getPathForRow(i);
+ Object o = path.getLastPathComponent();
+ // FIXME: in the following call to convertValueToText the
+ // last argument (hasFocus) should be done right.
+ String item = convertValueToText(o, isRowSelected(i),
+ isExpanded(i), treeModel.isLeaf(o), i, false);
+ if (item.startsWith(prefix))
+ {
+ foundPath = path;
+ break;
+ }
+ }
+ }
+ return foundPath;
+ }
+
+ /**
+ * Removes any paths in the current set of selected paths that are
+ * descendants of <code>path</code>. If <code>includePath</code> is set
+ * to <code>true</code> and <code>path</code> itself is selected, then
+ * it will be removed too.
+ *
+ * @param path the path from which selected descendants are to be removed
+ * @param includeSelected if <code>true</code> then <code>path</code> itself
+ * will also be remove if it's selected
+ *
+ * @return <code>true</code> if something has been removed,
+ * <code>false</code> otherwise
+ *
+ * @since 1.3
+ */
+ protected boolean removeDescendantSelectedPaths(TreePath path,
+ boolean includeSelected)
+ {
+ boolean removedSomething = false;
+ TreePath[] selected = getSelectionPaths();
+ for (int index = 0; index < selected.length; index++)
+ {
+ if ((selected[index] == path && includeSelected)
+ || (selected[index].isDescendant(path)))
+ {
+ removeSelectionPath(selected[index]);
+ removedSomething = true;
+ }
+ }
+ return removedSomething;
+ }
+
+ /**
+ * Removes any descendants of the TreePaths in toRemove that have been
+ * expanded.
+ *
+ * @param toRemove - Enumeration of TreePaths that need to be removed from
+ * cache of toggled tree paths.
+ */
+ protected void removeDescendantToggledPaths(Enumeration toRemove)
+ {
+ while (toRemove.hasMoreElements())
+ {
+ TreePath current = (TreePath) toRemove.nextElement();
+ Enumeration descendants = getDescendantToggledPaths(current);
+
+ while (descendants.hasMoreElements())
+ {
+ TreePath currentDes = (TreePath) descendants.nextElement();
+ if (isExpanded(currentDes))
+ nodeStates.remove(currentDes);
+ }
+ }
+ }
+
+ /**
+ * Sent when the tree has changed enough that we need to resize the bounds,
+ * but not enough that we need to remove the expanded node set (e.g nodes
+ * were expanded or collapsed, or nodes were inserted into the tree). You
+ * should never have to invoke this, the UI will invoke this as it needs to.
+ */
+ public void treeDidChange()
+ {
+ repaint();
+ }
}
diff --git a/libjava/classpath/javax/swing/JViewport.java b/libjava/classpath/javax/swing/JViewport.java
index d750bad29cc..5f20f0aa60a 100644
--- a/libjava/classpath/javax/swing/JViewport.java
+++ b/libjava/classpath/javax/swing/JViewport.java
@@ -41,6 +41,7 @@ package javax.swing;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
+import java.awt.Image;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Point;
@@ -49,6 +50,9 @@ import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.Serializable;
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@@ -95,17 +99,41 @@ import javax.swing.plaf.ViewportUI;
* the underlying child at position <code>(-VX,-VY)</code></p>
*
*/
-public class JViewport extends JComponent
+public class JViewport extends JComponent implements Accessible
{
+ /**
+ * Provides accessibility support for <code>JViewport</code>.
+ *
+ * @author Roman Kennke (roman@kennke.org)
+ */
+ protected class AccessibleJViewport extends AccessibleJComponent
+ {
+ /**
+ * Creates a new instance of <code>AccessibleJViewport</code>.
+ */
+ public AccessibleJViewport()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the accessible role of <code>JViewport</code>, which is
+ * {@link AccessibleRole#VIEWPORT}.
+ *
+ * @return the accessible role of <code>JViewport</code>
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.VIEWPORT;
+ }
+ }
/**
* A {@link java.awt.event.ComponentListener} that listens for
- * changes of the view's size. This class forbids changes of the view
- * component's size that would exceed the viewport's size.
+ * changes of the view's size. This triggers a revalidate() call on the
+ * viewport.
*/
- protected class ViewListener
- extends ComponentAdapter
- implements Serializable
+ protected class ViewListener extends ComponentAdapter implements Serializable
{
private static final long serialVersionUID = -2812489404285958070L;
@@ -114,57 +142,53 @@ public class JViewport extends JComponent
*/
protected ViewListener()
{
+ // Nothing to do here.
}
/**
* Receives notification when a component (in this case: the view
- * component) changes it's size.
+ * component) changes it's size. This simply triggers a revalidate() on the
+ * viewport.
*
* @param ev the ComponentEvent describing the change
*/
public void componentResized(ComponentEvent ev)
{
- // According to some tests that I did with Sun's implementation
- // this class is supposed to make sure that the view component
- // is not resized to a larger size than the viewport.
- // This is not documented anywhere. What I did is: I subclassed JViewport
- // and ViewListener and 'disabled' the componentResized method by
- // overriding it and not calling super.componentResized().
- // When this method is disabled I can set the size on the view component
- // normally, when it is enabled, it gets immediatly resized back,
- // after a resize attempt that would exceed the Viewport's size.
- Component comp = ev.getComponent();
- Dimension newSize = comp.getSize();
- Dimension viewportSize = getSize();
- boolean revert = false;
- if (newSize.width > viewportSize.width)
- {
- newSize.width = viewportSize.width;
- revert = true;
- }
- if (newSize.height > viewportSize.height)
- {
- newSize.height = viewportSize.height;
- revert = true;
- }
- if (revert == true)
- comp.setSize(newSize);
+ revalidate();
}
}
- private static final long serialVersionUID = -6925142919680527970L;
-
public static final int SIMPLE_SCROLL_MODE = 0;
public static final int BLIT_SCROLL_MODE = 1;
public static final int BACKINGSTORE_SCROLL_MODE = 2;
+ private static final long serialVersionUID = -6925142919680527970L;
+
+ protected boolean scrollUnderway;
+ protected boolean isViewSizeSet;
+
+ /**
+ * This flag indicates whether we use a backing store for drawing.
+ *
+ * @deprecated since JDK 1.3
+ */
+ protected boolean backingStore;
+
+ /**
+ * The backingstore image used for the backingstore and blit scroll methods.
+ */
+ protected Image backingStoreImage;
+
+ /**
+ * The position at which the view has been drawn the last time. This is used
+ * to determine the bittable area.
+ */
+ protected Point lastPaintPosition;
+
ChangeEvent changeEvent = new ChangeEvent(this);
int scrollMode;
- protected boolean scrollUnderway;
- protected boolean isViewSizeSet;
-
/**
* The width and height of the Viewport's area in terms of view
* coordinates. Typically this will be the same as the width and height
@@ -172,29 +196,75 @@ public class JViewport extends JComponent
* width and height, which it may do, for example if it magnifies or
* rotates its view.
*
- * @see #toViewCoordinates
+ * @see #toViewCoordinates(Dimension)
*/
Dimension extentSize;
/**
* The width and height of the view in its own coordinate space.
*/
-
Dimension viewSize;
- Point lastPaintPosition;
-
/**
* The ViewListener instance.
*/
ViewListener viewListener;
+ /**
+ * Stores the location from where to blit. This is a cached Point object used
+ * in blitting calculations.
+ */
+ Point cachedBlitFrom;
+
+ /**
+ * Stores the location where to blit to. This is a cached Point object used
+ * in blitting calculations.
+ */
+ Point cachedBlitTo;
+
+ /**
+ * Stores the width of the blitted area. This is a cached Dimension object
+ * used in blitting calculations.
+ */
+ Dimension cachedBlitSize;
+
+ /**
+ * Stores the bounds of the area that needs to be repainted. This is a cached
+ * Rectangle object used in blitting calculations.
+ */
+ Rectangle cachedBlitPaint;
+
+ boolean damaged = true;
+
+ /**
+ * A flag indicating if the size of the viewport has changed since the
+ * last repaint. This is used in double buffered painting to check if we
+ * need a new double buffer, or can reuse the old one.
+ */
+ boolean sizeChanged = true;
+
public JViewport()
{
setOpaque(true);
- setScrollMode(BLIT_SCROLL_MODE);
- setLayout(createLayoutManager());
+ String scrollModeProp =
+ System.getProperty("gnu.javax.swing.JViewport.scrollMode",
+ "BLIT");
+ int myScrollMode;
+ if (scrollModeProp.equalsIgnoreCase("simple"))
+ myScrollMode = SIMPLE_SCROLL_MODE;
+ else if (scrollModeProp.equalsIgnoreCase("backingstore"))
+ myScrollMode = BACKINGSTORE_SCROLL_MODE;
+ else
+ myScrollMode = BLIT_SCROLL_MODE;
+ setScrollMode(myScrollMode);
+
updateUI();
+ setLayout(createLayoutManager());
+ lastPaintPosition = new Point();
+ cachedBlitFrom = new Point();
+ cachedBlitTo = new Point();
+ cachedBlitSize = new Dimension();
+ cachedBlitPaint = new Rectangle();
}
public Dimension getExtentSize()
@@ -248,9 +318,14 @@ public class JViewport extends JComponent
viewSize = newSize;
Component view = getView();
if (view != null)
- view.setSize(viewSize);
+ {
+ if (newSize != view.getSize())
+ {
+ view.setSize(viewSize);
+ fireStateChanged();
+ }
+ }
isViewSizeSet = true;
- fireStateChanged();
}
/**
@@ -275,13 +350,17 @@ public class JViewport extends JComponent
public void setViewPosition(Point p)
{
+ if (getViewPosition().equals(p))
+ return;
Component view = getView();
if (view != null)
{
Point q = new Point(-p.x, -p.y);
view.setLocation(q);
+ isViewSizeSet = false;
fireStateChanged();
}
+ repaint();
}
public Rectangle getViewRect()
@@ -331,12 +410,8 @@ public class JViewport extends JComponent
public void setView(Component v)
{
- while (getComponentCount() > 0)
- {
- if (viewListener != null)
- getView().removeComponentListener(viewListener);
- remove(0);
- }
+ if (viewListener != null)
+ getView().removeComponentListener(viewListener);
if (v != null)
{
@@ -346,37 +421,25 @@ public class JViewport extends JComponent
add(v);
fireStateChanged();
}
- }
-
- public void revalidate()
- {
- fireStateChanged();
- super.revalidate();
+ revalidate();
+ repaint();
}
public void reshape(int x, int y, int w, int h)
{
- boolean changed =
- (x != getX())
- || (y != getY())
- || (w != getWidth())
- || (h != getHeight());
+ if (w != getWidth() || h != getHeight())
+ sizeChanged = true;
super.reshape(x, y, w, h);
- if (changed)
- fireStateChanged();
- }
-
- protected void addImpl(Component comp, Object constraints, int index)
- {
- if (getComponentCount() > 0)
- remove(getComponents()[0]);
-
- super.addImpl(comp, constraints, index);
+ if (sizeChanged)
+ {
+ damaged = true;
+ fireStateChanged();
+ }
}
- public final Insets getInsets()
+ public final Insets getInsets()
{
- return new Insets(0,0,0,0);
+ return new Insets(0, 0, 0, 0);
}
public final Insets getInsets(Insets insets)
@@ -390,6 +453,14 @@ public class JViewport extends JComponent
return insets;
}
+
+ /**
+ * Overridden to return <code>false</code>, so the JViewport's paint method
+ * gets called instead of directly calling the children. This is necessary
+ * in order to get a useful clipping and translation on the children.
+ *
+ * @return <code>false</code>
+ */
public boolean isOptimizedDrawingEnabled()
{
return false;
@@ -397,7 +468,36 @@ public class JViewport extends JComponent
public void paint(Graphics g)
{
- paintComponent(g);
+ Component view = getView();
+
+ if (view == null)
+ return;
+
+ Point pos = getViewPosition();
+ Rectangle viewBounds = view.getBounds();
+ Rectangle portBounds = getBounds();
+
+ if (viewBounds.width == 0
+ || viewBounds.height == 0
+ || portBounds.width == 0
+ || portBounds.height == 0)
+ return;
+
+ switch (getScrollMode())
+ {
+
+ case JViewport.BACKINGSTORE_SCROLL_MODE:
+ paintBackingStore(g);
+ break;
+ case JViewport.BLIT_SCROLL_MODE:
+ paintBlit(g);
+ break;
+ case JViewport.SIMPLE_SCROLL_MODE:
+ default:
+ paintSimple(g);
+ break;
+ }
+ damaged = false;
}
public void addChangeListener(ChangeListener listener)
@@ -415,13 +515,6 @@ public class JViewport extends JComponent
return (ChangeListener[]) getListeners(ChangeListener.class);
}
- protected void fireStateChanged()
- {
- ChangeListener[] listeners = getChangeListeners();
- for (int i = 0; i < listeners.length; ++i)
- listeners[i].stateChanged(changeEvent);
- }
-
/**
* This method returns the String ID of the UI class of Separator.
*
@@ -467,6 +560,90 @@ public class JViewport extends JComponent
}
/**
+ * Scrolls the view so that contentRect becomes visible.
+ *
+ * @param contentRect the rectangle to make visible within the view
+ */
+ public void scrollRectToVisible(Rectangle contentRect)
+ {
+ Component view = getView();
+ if (view == null)
+ return;
+
+ Point pos = getViewPosition();
+ Rectangle viewBounds = getView().getBounds();
+ Rectangle portBounds = getBounds();
+
+ if (isShowing())
+ getView().validate();
+
+ // If the bottom boundary of contentRect is below the port
+ // boundaries, scroll up as necessary.
+ if (contentRect.y + contentRect.height + viewBounds.y > portBounds.height)
+ pos.y = contentRect.y + contentRect.height - portBounds.height;
+ // If contentRect.y is above the port boundaries, scroll down to
+ // contentRect.y.
+ if (contentRect.y + viewBounds.y < 0)
+ pos.y = contentRect.y;
+ // If the right boundary of contentRect is right from the port
+ // boundaries, scroll left as necessary.
+ if (contentRect.x + contentRect.width + viewBounds.x > portBounds.width)
+ pos.x = contentRect.x + contentRect.width - portBounds.width;
+ // If contentRect.x is left from the port boundaries, scroll right to
+ // contentRect.x.
+ if (contentRect.x + viewBounds.x < 0)
+ pos.x = contentRect.x;
+ setViewPosition(pos);
+ }
+
+ /**
+ * Returns the accessible context for this <code>JViewport</code>. This
+ * will be an instance of {@link AccessibleJViewport}.
+ *
+ * @return the accessible context for this <code>JViewport</code>
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJViewport();
+ return accessibleContext;
+ }
+
+ /**
+ * Forward repaint to parent to make sure only one paint is performed by the
+ * RepaintManager.
+ *
+ * @param tm number of milliseconds to defer the repaint request
+ * @param x the X coordinate of the upper left corner of the dirty area
+ * @param y the Y coordinate of the upper left corner of the dirty area
+ * @param w the width of the dirty area
+ * @param h the height of the dirty area
+ */
+ public void repaint(long tm, int x, int y, int w, int h)
+ {
+ Component parent = getParent();
+ if (parent != null)
+ {
+ parent.repaint(tm, x + getX(), y + getY(), w, h);
+ }
+ }
+
+ protected void addImpl(Component comp, Object constraints, int index)
+ {
+ if (getComponentCount() > 0)
+ remove(getComponents()[0]);
+
+ super.addImpl(comp, constraints, index);
+ }
+
+ protected void fireStateChanged()
+ {
+ ChangeListener[] listeners = getChangeListeners();
+ for (int i = 0; i < listeners.length; ++i)
+ listeners[i].stateChanged(changeEvent);
+ }
+
+ /**
* Creates a {@link ViewListener} that is supposed to listen for
* size changes on the view component.
*
@@ -489,43 +666,217 @@ public class JViewport extends JComponent
}
/**
- * Scrolls the view so that contentRect becomes visible.
+ * Computes the parameters for the blitting scroll method. <code>dx</code>
+ * and <code>dy</code> specifiy the X and Y offset by which the viewport
+ * is scrolled. All other arguments are output parameters and are filled by
+ * this method.
*
- * @param contentRect the rectangle to make visible within the view
+ * <code>blitFrom</code> holds the position of the blit rectangle in the
+ * viewport rectangle before scrolling, <code>blitTo</code> where the blitArea
+ * is copied to.
+ *
+ * <code>blitSize</code> holds the size of the blit area and
+ * <code>blitPaint</code> is the area of the view that needs to be painted.
+ *
+ * This method returns <code>true</code> if blitting is possible and
+ * <code>false</code> if the viewport has to be repainted completetly without
+ * blitting.
+ *
+ * @param dx the horizontal delta
+ * @param dy the vertical delta
+ * @param blitFrom the position from where to blit; set by this method
+ * @param blitTo the position where to blit area is copied to; set by this
+ * method
+ * @param blitSize the size of the blitted area; set by this method
+ * @param blitPaint the area that needs repainting; set by this method
+ *
+ * @return <code>true</code> if blitting is possible,
+ * <code>false</code> otherwise
*/
- public void scrollRectToVisible(Rectangle contentRect)
+ protected boolean computeBlit(int dx, int dy, Point blitFrom, Point blitTo,
+ Dimension blitSize, Rectangle blitPaint)
+ {
+ if ((dx != 0 && dy != 0) || damaged)
+ // We cannot blit if the viewport is scrolled in both directions at
+ // once.
+ return false;
+
+ Rectangle portBounds = SwingUtilities.calculateInnerArea(this, getBounds());
+
+ // Compute the blitFrom and blitTo parameters.
+ blitFrom.x = portBounds.x;
+ blitFrom.y = portBounds.y;
+ blitTo.x = portBounds.x;
+ blitTo.y = portBounds.y;
+
+ if (dy > 0)
+ {
+ blitFrom.y = portBounds.y + dy;
+ }
+ else if (dy < 0)
+ {
+ blitTo.y = portBounds.y - dy;
+ }
+ else if (dx > 0)
+ {
+ blitFrom.x = portBounds.x + dx;
+ }
+ else if (dx < 0)
+ {
+ blitTo.x = portBounds.x - dx;
+ }
+
+ // Compute size of the blit area.
+ if (dx != 0)
+ {
+ blitSize.width = portBounds.width - Math.abs(dx);
+ blitSize.height = portBounds.height;
+ }
+ else if (dy != 0)
+ {
+ blitSize.width = portBounds.width;
+ blitSize.height = portBounds.height - Math.abs(dy);
+ }
+
+ // Compute the blitPaint parameter.
+ blitPaint.setBounds(portBounds);
+ if (dy > 0)
+ {
+ blitPaint.y = portBounds.y + portBounds.height - dy;
+ blitPaint.height = dy;
+ }
+ else if (dy < 0)
+ {
+ blitPaint.height = -dy;
+ }
+ if (dx > 0)
+ {
+ blitPaint.x = portBounds.x + portBounds.width - dx;
+ blitPaint.width = dx;
+ }
+ else if (dx < 0)
+ {
+ blitPaint.width = -dx;
+ }
+
+ return true;
+ }
+
+ /**
+ * Paints the viewport in case we have a scrollmode of
+ * {@link #SIMPLE_SCROLL_MODE}.
+ *
+ * This simply paints the view directly on the surface of the viewport.
+ *
+ * @param g the graphics context to use
+ */
+ void paintSimple(Graphics g)
{
Point pos = getViewPosition();
- Rectangle viewBounds = getView().getBounds();
- Rectangle portBounds = getBounds();
-
- // FIXME: should validate the view if it is not valid, however
- // this may cause excessive validation when the containment
- // hierarchy is being created.
-
- // if contentRect is larger than the portBounds, center the view
- if (contentRect.height > portBounds.height ||
- contentRect.width > portBounds.width)
+ Component view = getView();
+ boolean translated = false;
+ try
+ {
+ g.translate(-pos.x, -pos.y);
+ translated = true;
+ view.paint(g);
+ }
+ finally
{
- setViewPosition(new Point(contentRect.x, contentRect.y));
- return;
+ if (translated)
+ g.translate (pos.x, pos.y);
}
-
- // Y-DIRECTION
- if (contentRect.y < -viewBounds.y)
- setViewPosition(new Point(pos.x, contentRect.y));
- else if (contentRect.y + contentRect.height >
- -viewBounds.y + portBounds.height)
- setViewPosition (new Point(pos.x, contentRect.y -
- (portBounds.height - contentRect.height)));
-
- // X-DIRECTION
- pos = getViewPosition();
- if (contentRect.x < -viewBounds.x)
- setViewPosition(new Point(contentRect.x, pos.y));
- else if (contentRect.x + contentRect.width >
- -viewBounds.x + portBounds.width)
- setViewPosition (new Point(contentRect.x -
- (portBounds.width - contentRect.width), pos.y));
+ }
+
+ /**
+ * Paints the viewport in case we have a scroll mode of
+ * {@link #BACKINGSTORE_SCROLL_MODE}.
+ *
+ * This method uses a backing store image to paint the view to, which is then
+ * subsequently painted on the screen. This should make scrolling more
+ * smooth.
+ *
+ * @param g the graphics context to use
+ */
+ void paintBackingStore(Graphics g)
+ {
+ // If we have no backing store image yet or the size of the component has
+ // changed, we need to rebuild the backing store.
+ if (backingStoreImage == null || sizeChanged)
+ {
+ backingStoreImage = createImage(getWidth(), getHeight());
+ sizeChanged = false;
+ Graphics g2 = backingStoreImage.getGraphics();
+ paintSimple(g2);
+ g2.dispose();
+ }
+ // Otherwise we can perform the blitting on the backing store image:
+ // First we move the part that remains visible after scrolling, then
+ // we only need to paint the bit that becomes newly visible.
+ else
+ {
+ Graphics g2 = backingStoreImage.getGraphics();
+ Point viewPosition = getViewPosition();
+ int dx = viewPosition.x - lastPaintPosition.x;
+ int dy = viewPosition.y - lastPaintPosition.y;
+ boolean canBlit = computeBlit(dx, dy, cachedBlitFrom, cachedBlitTo,
+ cachedBlitSize, cachedBlitPaint);
+ if (canBlit)
+ {
+ // Copy the part that remains visible during scrolling.
+ g2.copyArea(cachedBlitFrom.x, cachedBlitFrom.y,
+ cachedBlitSize.width, cachedBlitSize.height,
+ cachedBlitTo.x - cachedBlitFrom.x,
+ cachedBlitTo.y - cachedBlitFrom.y);
+ // Now paint the part that becomes newly visible.
+ g2.setClip(cachedBlitPaint.x, cachedBlitPaint.y,
+ cachedBlitPaint.width, cachedBlitPaint.height);
+ paintSimple(g2);
+ }
+ // If blitting is not possible for some reason, fall back to repainting
+ // everything.
+ else
+ {
+ paintSimple(g2);
+ }
+ g2.dispose();
+ }
+ // Actually draw the backingstore image to the graphics context.
+ g.drawImage(backingStoreImage, 0, 0, this);
+ // Update the lastPaintPosition so that we know what is already drawn when
+ // we paint the next time.
+ lastPaintPosition.setLocation(getViewPosition());
+ }
+
+ /**
+ * Paints the viewport in case we have a scrollmode of
+ * {@link #BLIT_SCROLL_MODE}.
+ *
+ * This paints the viewport using a backingstore and a blitting algorithm.
+ * Only the newly exposed area of the view is painted from the view painting
+ * methods, the remainder is copied from the backing store.
+ *
+ * @param g the graphics context to use
+ */
+ void paintBlit(Graphics g)
+ {
+ // We cannot perform blitted painting as it is described in Sun's API docs.
+ // There it is suggested that this painting method should blit directly
+ // on the parent window's surface. This is not possible because when using
+ // Swing's double buffering (at least our implementation), it would
+ // immediatly be painted when the buffer is painted on the screen. For this
+ // to work we would need a kind of hole in the buffer image. And honestly
+ // I find this method not very elegant.
+ // The alternative, blitting directly on the buffer image, is also not
+ // possible because the buffer image gets cleared everytime when an opaque
+ // parent component is drawn on it.
+
+ // What we do instead is falling back to the backing store approach which
+ // is in fact a mixed blitting/backing store approach where the blitting
+ // is performed on the backing store image and this is then drawn to the
+ // graphics context. This is very robust and works independent of the
+ // painting mechanism that is used by Swing. And it should have comparable
+ // performance characteristics as the blitting method.
+ paintBackingStore(g);
}
}
diff --git a/libjava/classpath/javax/swing/JWindow.java b/libjava/classpath/javax/swing/JWindow.java
index 449900370c6..cc0ac7fd95a 100644
--- a/libjava/classpath/javax/swing/JWindow.java
+++ b/libjava/classpath/javax/swing/JWindow.java
@@ -60,6 +60,21 @@ import javax.accessibility.AccessibleContext;
*/
public class JWindow extends Window implements Accessible, RootPaneContainer
{
+ /**
+ * Provides accessibility support for <code>JWindow</code>.
+ */
+ protected class AccessibleJWindow extends Window.AccessibleAWTWindow
+ {
+ /**
+ * Creates a new instance of <code>AccessibleJWindow</code>.
+ */
+ public AccessibleJWindow()
+ {
+ super();
+ // Nothing to do here.
+ }
+ }
+
private static final long serialVersionUID = 5420698392125238833L;
protected JRootPane rootPane;
@@ -71,13 +86,6 @@ public class JWindow extends Window implements Accessible, RootPaneContainer
protected AccessibleContext accessibleContext;
- /**
- * Tells us if we're in the initialization stage.
- * If so, adds go to top-level Container, otherwise they go
- * to the content pane for this container.
- */
- private boolean initStageDone = false;
-
public JWindow()
{
super(SwingUtilities.getOwnerFrame());
@@ -113,7 +121,7 @@ public class JWindow extends Window implements Accessible, RootPaneContainer
super.setLayout(new BorderLayout(1, 1));
getRootPane(); // will do set/create
// Now we're done init stage, adds and layouts go to content pane.
- initStageDone = true;
+ setRootPaneCheckingEnabled(true);
}
public Dimension getPreferredSize()
@@ -125,13 +133,8 @@ public class JWindow extends Window implements Accessible, RootPaneContainer
{
// Check if we're in initialization stage. If so, call super.setLayout
// otherwise, valid calls go to the content pane.
- if (initStageDone)
- {
- if (isRootPaneCheckingEnabled())
- throw new Error("Cannot set layout. Use getContentPane().setLayout()"
- + " instead.");
- getContentPane().setLayout(manager);
- }
+ if (isRootPaneCheckingEnabled())
+ getContentPane().setLayout(manager);
else
super.setLayout(manager);
}
@@ -192,15 +195,10 @@ public class JWindow extends Window implements Accessible, RootPaneContainer
{
// If we're adding in the initialization stage use super.add.
// otherwise pass the add onto the content pane.
- if (!initStageDone)
- super.addImpl(comp, constraints, index);
+ if (isRootPaneCheckingEnabled())
+ getContentPane().add(comp, constraints, index);
else
- {
- if (isRootPaneCheckingEnabled())
- throw new Error("Do not use add() on JWindow directly. Use "
- + "getContentPane().add() instead");
- getContentPane().add(comp, constraints, index);
- }
+ super.addImpl(comp, constraints, index);
}
public void remove(Component comp)
@@ -235,7 +233,9 @@ public class JWindow extends Window implements Accessible, RootPaneContainer
public AccessibleContext getAccessibleContext()
{
- return null;
+ if (accessibleContext == null)
+ accessibleContext = new AccessibleJWindow();
+ return accessibleContext;
}
protected String paramString()
diff --git a/libjava/classpath/javax/swing/KeyStroke.java b/libjava/classpath/javax/swing/KeyStroke.java
index 12a280c217a..b57a7119207 100644
--- a/libjava/classpath/javax/swing/KeyStroke.java
+++ b/libjava/classpath/javax/swing/KeyStroke.java
@@ -51,6 +51,7 @@ public class KeyStroke
// Called by java.awt.AWTKeyStroke.registerSubclass via reflection.
private KeyStroke()
{
+ // Nothing to do here.
}
private KeyStroke(char keyChar, int keyCode, int modifiers,
diff --git a/libjava/classpath/javax/swing/KeyboardManager.java b/libjava/classpath/javax/swing/KeyboardManager.java
new file mode 100644
index 00000000000..d3868309d08
--- /dev/null
+++ b/libjava/classpath/javax/swing/KeyboardManager.java
@@ -0,0 +1,280 @@
+/* KeyboardManager.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing;
+
+import java.applet.Applet;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Window;
+import java.awt.event.KeyEvent;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * This class maintains a mapping from top-level containers to a
+ * Hashtable. The Hashtable maps KeyStrokes to Components to be used when
+ * Components register keyboard actions with the condition
+ * JComponent.WHEN_IN_FOCUSED_WINDOW.
+ *
+ * @author Anthony Balkissoon <abalkiss@redhat.com>
+ *
+ */
+class KeyboardManager
+{
+ /** Shared instance of KeyboardManager **/
+ static KeyboardManager manager = new KeyboardManager();
+
+ /**
+ * A mapping between top level containers and Hashtables that
+ * map KeyStrokes to Components.
+ */
+ Hashtable topLevelLookup = new Hashtable();
+
+ /**
+ * A mapping between top level containers and Vectors of JMenuBars
+ * used to allow all the JMenuBars within a top level container
+ * a chance to consume key events.
+ */
+ Hashtable menuBarLookup = new Hashtable();
+ /**
+ * Returns the shared instance of KeyboardManager.
+ * @return the shared instance of KeybaordManager.
+ */
+ public static KeyboardManager getManager()
+ {
+ return manager;
+ }
+ /**
+ * Returns the top-level ancestor for the given JComponent.
+ * @param c the JComponent whose top-level ancestor we want
+ * @return the top-level ancestor for the given JComponent.
+ */
+ static Container findTopLevel (Component c)
+ {
+ Container topLevel = (c instanceof Container) ? (Container) c
+ : c.getParent();
+ while (topLevel != null &&
+ !(topLevel instanceof Window) &&
+ !(topLevel instanceof Applet) &&
+ !(topLevel instanceof JInternalFrame))
+ topLevel = topLevel.getParent();
+ return topLevel;
+ }
+
+ /**
+ * Returns the Hashtable that maps KeyStrokes to Components, for
+ * the specified top-level container c. If no Hashtable exists
+ * we create and register it here and return the newly created
+ * Hashtable.
+ *
+ * @param c the top-level container whose Hashtable we want
+ * @return the Hashtable mapping KeyStrokes to Components for the
+ * specified top-level container
+ */
+ Hashtable getHashtableForTopLevel (Container c)
+ {
+ Hashtable keyToComponent = (Hashtable)topLevelLookup.get(c);
+ if (keyToComponent == null)
+ {
+ keyToComponent = new Hashtable();
+ topLevelLookup.put(c, keyToComponent);
+ }
+ return keyToComponent;
+ }
+
+ /**
+ * Registers a KeyStroke with a Component. This does not register
+ * the KeyStroke to a specific Action. When searching for a
+ * WHEN_IN_FOCUSED_WINDOW binding we will first go up to the focused
+ * top-level Container, then get the Hashtable that maps KeyStrokes
+ * to components for that particular top-level Container, then
+ * call processKeyBindings on that component with the condition
+ * JComponent.WHEN_IN_FOCUSED_WINDOW.
+ * @param comp the JComponent associated with the KeyStroke
+ * @param key the KeyStroke
+ */
+ public void registerBinding(JComponent comp, KeyStroke key)
+ {
+ // This method associates a KeyStroke with a particular JComponent
+ // When the KeyStroke occurs, if this component's top-level ancestor
+ // has focus (one of its children is the focused Component) then
+ // comp.processKeyBindings will be called with condition
+ // JComponent.WHEN_IN_FOCUSED_WINDOW.
+
+ // Look for the JComponent's top-level parent and return if it is null
+ Container topLevel = findTopLevel(comp);
+ if (topLevel == null)
+ return;
+
+ // Now get the Hashtable for this top-level container
+ Hashtable keyToComponent = getHashtableForTopLevel(topLevel);
+
+ // And add the new binding to this Hashtable
+ // FIXME: should allow more than one JComponent to be associated
+ // with a KeyStroke, in case one of them is disabled
+ keyToComponent.put(key, comp);
+ }
+
+ public void clearBindingsForComp(JComponent comp)
+ {
+ // This method clears all the WHEN_IN_FOCUSED_WINDOW bindings associated
+ // with <code>comp</code>. This is used for a terribly ineffcient
+ // strategy in which JComponent.updateComponentInputMap simply clears
+ // all bindings associated with its component and then reloads all the
+ // bindings from the updated ComponentInputMap. This is only a preliminary
+ // strategy and should be improved upon once the WHEN_IN_FOCUSED_WINDOW
+ // bindings work.
+
+ // Find the top-level ancestor
+
+ Container topLevel = findTopLevel(comp);
+ if (topLevel == null)
+ return;
+ // And now get its Hashtable
+ Hashtable keyToComponent = getHashtableForTopLevel(topLevel);
+
+ Enumeration keys = keyToComponent.keys();
+ Object temp;
+
+ // Iterate through the keys and remove any key whose value is comp
+ while (keys.hasMoreElements())
+ {
+ temp = keys.nextElement();
+ if (comp == (JComponent)keyToComponent.get(temp))
+ keyToComponent.remove(temp);
+ }
+ }
+
+ /**
+ * This method registers all the bindings in the given ComponentInputMap.
+ * Rather than call registerBinding on all the keys, we do the work here
+ * so that we don't duplicate finding the top-level container and
+ * getting its Hashtable.
+ *
+ * @param map the ComponentInputMap whose bindings we want to register
+ */
+ public void registerEntireMap (ComponentInputMap map)
+ {
+ if (map == null)
+ return;
+ JComponent comp = map.getComponent();
+ KeyStroke[] keys = map.keys();
+ if (keys == null)
+ return;
+ // Find the top-level container associated with this ComponentInputMap
+ Container topLevel = findTopLevel(comp);
+ if (topLevel == null)
+ return;
+
+ // Register the KeyStrokes in the top-level container's Hashtable
+ Hashtable keyToComponent = getHashtableForTopLevel(topLevel);
+ for (int i = 0; i < keys.length; i++)
+ keyToComponent.put(keys[i], comp);
+ }
+
+ public boolean processKeyStroke (Component comp, KeyStroke key, KeyEvent e)
+ {
+ boolean pressed = e.getID() == KeyEvent.KEY_PRESSED;
+
+ // Look for the top-level ancestor
+ Container topLevel = findTopLevel(comp);
+ if (topLevel == null)
+ return false;
+ // Now get the Hashtable for that top-level container
+ Hashtable keyToComponent = getHashtableForTopLevel(topLevel);
+ Enumeration keys = keyToComponent.keys();
+ JComponent target = (JComponent)keyToComponent.get(key);
+ if (target != null && target.processKeyBinding
+ (key, e, JComponent.WHEN_IN_FOCUSED_WINDOW, pressed))
+ return true;
+
+ // Have to give all the JMenuBars a chance to consume the event
+ Vector menuBars = getVectorForTopLevel(topLevel);
+ for (int i = 0; i < menuBars.size(); i++)
+ if (((JMenuBar)menuBars.elementAt(i)).processKeyBinding(key, e, JComponent.WHEN_IN_FOCUSED_WINDOW, pressed))
+ return true;
+ return false;
+ }
+
+ /**
+ * Returns the Vector of JMenuBars associated with the top-level
+ * @param c the top-level container whose JMenuBar Vector we want
+ * @return the Vector of JMenuBars for this top level container
+ */
+ Vector getVectorForTopLevel(Container c)
+ {
+ Vector result = (Vector) menuBarLookup.get(c);
+ if (result == null)
+ {
+ result = new Vector();
+ menuBarLookup.put (c, result);
+ }
+ return result;
+ }
+
+ /**
+ * In processKeyStroke, KeyManager must give all JMenuBars in the
+ * focused top-level container a chance to process the event. So,
+ * JMenuBars must be registered in KeyManager and associated with a
+ * top-level container. That's what this method is for.
+ * @param menuBar the JMenuBar to register
+ */
+ public void registerJMenuBar (JMenuBar menuBar)
+ {
+ Container topLevel = findTopLevel(menuBar);
+ Vector menuBars = getVectorForTopLevel(topLevel);
+ if (!menuBars.contains(menuBar))
+ menuBars.add(menuBar);
+ }
+
+ /**
+ * Unregisters a JMenuBar from its top-level container. This is
+ * called before the JMenuBar is actually removed from the container
+ * so findTopLevel will still find us the correct top-level container.
+ * @param menuBar the JMenuBar to unregister.
+ */
+ public void unregisterJMenuBar (JMenuBar menuBar)
+ {
+ Container topLevel = findTopLevel(menuBar);
+ Vector menuBars = getVectorForTopLevel(topLevel);
+ if (menuBars.contains(menuBar))
+ menuBars.remove(menuBar);
+ }
+}
diff --git a/libjava/classpath/javax/swing/ListCellRenderer.java b/libjava/classpath/javax/swing/ListCellRenderer.java
index 6ce115ea70c..e234d184dfd 100644
--- a/libjava/classpath/javax/swing/ListCellRenderer.java
+++ b/libjava/classpath/javax/swing/ListCellRenderer.java
@@ -44,9 +44,7 @@ import java.awt.Component;
*/
public interface ListCellRenderer
{
- Component getListCellRendererComponent(JList list,
- Object value,
- int index,
- boolean isSelected,
- boolean cellHasFocus);
+ Component getListCellRendererComponent(JList list, Object value, int index,
+ boolean isSelected,
+ boolean cellHasFocus);
}
diff --git a/libjava/classpath/javax/swing/ListSelectionModel.java b/libjava/classpath/javax/swing/ListSelectionModel.java
index f4680d737fb..324c056431b 100644
--- a/libjava/classpath/javax/swing/ListSelectionModel.java
+++ b/libjava/classpath/javax/swing/ListSelectionModel.java
@@ -46,41 +46,51 @@ import javax.swing.event.ListSelectionListener;
*/
public interface ListSelectionModel
{
+
int SINGLE_SELECTION = 0;
+
int SINGLE_INTERVAL_SELECTION = 1;
+
int MULTIPLE_INTERVAL_SELECTION = 2;
void setSelectionMode(int a);
+
int getSelectionMode();
-
+
void clearSelection();
-
+
int getMinSelectionIndex();
+
int getMaxSelectionIndex();
boolean isSelectedIndex(int a);
boolean isSelectionEmpty();
+
void setSelectionInterval(int index0, int index1);
- void addSelectionInterval(int index0,
- int index1);
- void removeSelectionInterval(int index0,
- int index1);
- void insertIndexInterval(int index,
- int length,
- boolean before);
- void removeIndexInterval(int index0,
- int index1);
+
+ void addSelectionInterval(int index0, int index1);
+
+ void removeSelectionInterval(int index0, int index1);
+
+ void insertIndexInterval(int index, int length, boolean before);
+
+ void removeIndexInterval(int index0, int index1);
int getAnchorSelectionIndex();
+
void setAnchorSelectionIndex(int index);
+
int getLeadSelectionIndex();
+
void setLeadSelectionIndex(int index);
void setValueIsAdjusting(boolean valueIsAdjusting);
+
boolean getValueIsAdjusting();
void addListSelectionListener(ListSelectionListener listener);
- void removeListSelectionListener(ListSelectionListener listener);
+
+ void removeListSelectionListener(ListSelectionListener listener);
}
diff --git a/libjava/classpath/javax/swing/LookAndFeel.java b/libjava/classpath/javax/swing/LookAndFeel.java
index 8858742711d..1a67e849735 100644
--- a/libjava/classpath/javax/swing/LookAndFeel.java
+++ b/libjava/classpath/javax/swing/LookAndFeel.java
@@ -38,9 +38,17 @@ exception statement from your version. */
package javax.swing;
+import java.awt.Color;
import java.awt.Component;
+import java.awt.Font;
import java.awt.Toolkit;
+import java.net.URL;
+import javax.swing.border.Border;
+import javax.swing.plaf.ComponentInputMapUIResource;
+import javax.swing.plaf.IconUIResource;
+import javax.swing.plaf.InputMapUIResource;
+import javax.swing.plaf.UIResource;
import javax.swing.text.JTextComponent;
public abstract class LookAndFeel
@@ -104,6 +112,8 @@ public abstract class LookAndFeel
*/
public void initialize()
{
+ // We do nothing here. This method is meant to be overridden by
+ // LookAndFeel implementations.
}
/**
@@ -113,14 +123,27 @@ public abstract class LookAndFeel
*/
public static void installBorder(JComponent c, String defaultBorderName)
{
+ Border b = c.getBorder();
+ if (b == null || b instanceof UIResource)
+ c.setBorder(UIManager.getBorder(defaultBorderName));
}
/**
* Convenience method for initializing a component's foreground and
* background color properties with values from the current defaults table.
*/
- public static void installColors(JComponent c, String defaultBgName, String defaultFgName)
+ public static void installColors(JComponent c, String defaultBgName,
+ String defaultFgName)
{
+ // Install background.
+ Color bg = c.getBackground();
+ if (bg == null || bg instanceof UIResource)
+ c.setBackground(UIManager.getColor(defaultBgName));
+
+ // Install foreground.
+ Color fg = c.getForeground();
+ if (fg == null || fg instanceof UIResource)
+ c.setForeground(UIManager.getColor(defaultFgName));
}
/**
@@ -128,10 +151,16 @@ public abstract class LookAndFeel
* and font properties with values from the current defaults table.
*/
public static void installColorsAndFont(JComponent component,
- String defaultBgName,
- String defaultFgName,
- String defaultFontName)
+ String defaultBgName,
+ String defaultFgName,
+ String defaultFontName)
{
+ // Install colors.
+ installColors(component, defaultBgName, defaultFgName);
+ // Install font.
+ Font f = component.getFont();
+ if (f == null || f instanceof UIResource)
+ component.setFont(UIManager.getFont(defaultFontName));
}
/**
@@ -156,19 +185,47 @@ public abstract class LookAndFeel
public abstract boolean isSupportedLookAndFeel();
/**
- * Loads the bindings in keys into retMap.
+ * Loads the bindings in keys into retMap. Does not remove existing entries
+ * from retMap. <code>keys</code> describes the InputMap, every even indexed
+ * item is either a KeyStroke or a String representing a KeyStroke and every
+ * odd indexed item is the Object associated with that KeyStroke in an
+ * ActionMap.
+ *
+ * @param retMap the InputMap into which we load bindings
+ * @param keys the Object array describing the InputMap as above
*/
public static void loadKeyBindings(InputMap retMap, Object[] keys)
{
+ if (keys == null)
+ return;
+ for (int i = 0; i < keys.length - 1; i+= 2)
+ {
+ Object key = keys[i];
+ KeyStroke keyStroke;
+ if (key instanceof KeyStroke)
+ keyStroke = (KeyStroke)key;
+ else
+ keyStroke = KeyStroke.getKeyStroke((String)key);
+ retMap.put(keyStroke, keys[i+1]);
+ }
}
/**
- * Creates a ComponentInputMap from keys.
+ * Creates a ComponentInputMap from keys.
+ * <code>keys</code> describes the InputMap, every even indexed
+ * item is either a KeyStroke or a String representing a KeyStroke and every
+ * odd indexed item is the Object associated with that KeyStroke in an
+ * ActionMap.
+ *
+ * @param c the JComponent associated with the ComponentInputMap
+ * @param keys the Object array describing the InputMap as above
*/
public static ComponentInputMap makeComponentInputMap(JComponent c,
Object[] keys)
{
- return null;
+ ComponentInputMap retMap = new ComponentInputMapUIResource(c);
+ loadKeyBindings(retMap, keys);
+ return retMap;
}
/**
@@ -177,23 +234,55 @@ public abstract class LookAndFeel
*/
public static Object makeIcon(Class baseClass, String gifFile)
{
- return null;
+ final URL file = baseClass.getResource(gifFile);
+ return new UIDefaults.LazyValue()
+ {
+ public Object createValue(UIDefaults table)
+ {
+ return new IconUIResource(new ImageIcon(file));
+ }
+ };
}
/**
* Creates a InputMap from keys.
+ * <code>keys</code> describes the InputMap, every even indexed
+ * item is either a KeyStroke or a String representing a KeyStroke and every
+ * odd indexed item is the Object associated with that KeyStroke in an
+ * ActionMap.
+ *
+ * @param keys the Object array describing the InputMap as above
*/
public static InputMap makeInputMap(Object[] keys)
{
- return null;
+ InputMap retMap = new InputMapUIResource();
+ loadKeyBindings(retMap, keys);
+ return retMap;
}
/**
- * Convenience method for building lists of KeyBindings.
+ * Convenience method for building lists of KeyBindings.
+ * <code>keyBindingList</code> is an array of KeyStroke-Action pairs where
+ * even indexed elements are KeyStrokes or Strings representing KeyStrokes
+ * and odd indexed elements are the associated Actions.
+ *
+ * @param keyBindingList the array of KeyStroke-Action pairs
+ * @return a JTextComponent.KeyBinding array
*/
public static JTextComponent.KeyBinding[] makeKeyBindings(Object[] keyBindingList)
{
- return null;
+ JTextComponent.KeyBinding[] retBindings =
+ new JTextComponent.KeyBinding[keyBindingList.length / 2];
+ for (int i = 0; i < keyBindingList.length - 1; i+= 2)
+ {
+ KeyStroke stroke;
+ if (keyBindingList[i] instanceof KeyStroke)
+ stroke = (KeyStroke)keyBindingList[i];
+ else
+ stroke = KeyStroke.getKeyStroke((String)keyBindingList[i]);
+ retBindings[i/2] = new JTextComponent.KeyBinding(stroke, (String)keyBindingList[i+1]);
+ }
+ return retBindings;
}
/**
@@ -224,6 +313,8 @@ public abstract class LookAndFeel
*/
public void uninitialize()
{
+ // We do nothing here. This method is meant to be overridden by
+ // LookAndFeel implementations.
}
/**
@@ -232,5 +323,7 @@ public abstract class LookAndFeel
*/
public static void uninstallBorder(JComponent c)
{
+ if (c.getBorder() instanceof UIResource)
+ c.setBorder(null);
}
}
diff --git a/libjava/classpath/javax/swing/MenuElement.java b/libjava/classpath/javax/swing/MenuElement.java
index 46eb8c2a5fe..dab7b9cf1ad 100644
--- a/libjava/classpath/javax/swing/MenuElement.java
+++ b/libjava/classpath/javax/swing/MenuElement.java
@@ -47,47 +47,43 @@ import java.awt.event.MouseEvent;
*
* @author Andrew Selkirk
*/
-public interface MenuElement {
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * processMouseEvent
- * @param event TODO
- * @param path TODO
- * @param manager TODO
- */
- void processMouseEvent(MouseEvent event,
- MenuElement[] path, MenuSelectionManager manager);
-
- /**
- * processKeyEvent
- * @param event TODO
- * @param path TODO
- * @param manager TODO
- */
- void processKeyEvent(KeyEvent event,
- MenuElement[] path, MenuSelectionManager manager);
-
- /**
- * menuSelectionChanged
- * @param included TODO
- */
- void menuSelectionChanged(boolean included);
-
- /**
- * getSubElements
- * @returns MenuElement[]
- */
- MenuElement[] getSubElements();
-
- /**
- * getComponent
- * @returns Component
- */
- Component getComponent();
-
-
-} // MenuElement
+public interface MenuElement
+{
+
+ /**
+ * processMouseEvent
+ * @param event TODO
+ * @param path TODO
+ * @param manager TODO
+ */
+ void processMouseEvent(MouseEvent event, MenuElement[] path,
+ MenuSelectionManager manager);
+
+ /**
+ * processKeyEvent
+ * @param event TODO
+ * @param path TODO
+ * @param manager TODO
+ */
+ void processKeyEvent(KeyEvent event, MenuElement[] path,
+ MenuSelectionManager manager);
+
+ /**
+ * menuSelectionChanged
+ * @param included TODO
+ */
+ void menuSelectionChanged(boolean included);
+
+ /**
+ * getSubElements
+ * @returns MenuElement[]
+ */
+ MenuElement[] getSubElements();
+
+ /**
+ * getComponent
+ * @returns Component
+ */
+ Component getComponent();
+
+}
diff --git a/libjava/classpath/javax/swing/MenuSelectionManager.java b/libjava/classpath/javax/swing/MenuSelectionManager.java
index 32d56b958a1..4e52751065a 100644
--- a/libjava/classpath/javax/swing/MenuSelectionManager.java
+++ b/libjava/classpath/javax/swing/MenuSelectionManager.java
@@ -146,7 +146,9 @@ public class MenuSelectionManager
{
// Convert sourcePoint to screen coordinates.
Point sourcePointOnScreen = sourcePoint;
- SwingUtilities.convertPointToScreen(sourcePointOnScreen, source);
+
+ if (source.isShowing())
+ SwingUtilities.convertPointToScreen(sourcePointOnScreen, source);
Point compPointOnScreen;
Component resultComp = null;
@@ -168,7 +170,10 @@ public class MenuSelectionManager
&& sourcePointOnScreen.y < compPointOnScreen.y + size.height)
{
Point p = sourcePointOnScreen;
- SwingUtilities.convertPointFromScreen(p, comp);
+
+ if (comp.isShowing())
+ SwingUtilities.convertPointFromScreen(p, comp);
+
resultComp = SwingUtilities.getDeepestComponentAt(comp, p.x, p.y);
break;
}
diff --git a/libjava/classpath/javax/swing/MutableComboBoxModel.java b/libjava/classpath/javax/swing/MutableComboBoxModel.java
index ee79dac03a5..93091786e53 100644
--- a/libjava/classpath/javax/swing/MutableComboBoxModel.java
+++ b/libjava/classpath/javax/swing/MutableComboBoxModel.java
@@ -76,7 +76,7 @@ public interface MutableComboBoxModel extends ComboBoxModel
/**
* This method removes given element from the data model
*
- * @param element to remove.
+ * @param object element to remove.
*/
void removeElement(Object object);
-} // MutableComboBoxModel
+}
diff --git a/libjava/classpath/javax/swing/OverlayLayout.java b/libjava/classpath/javax/swing/OverlayLayout.java
index e8aef98a521..56b8c8bb67a 100644
--- a/libjava/classpath/javax/swing/OverlayLayout.java
+++ b/libjava/classpath/javax/swing/OverlayLayout.java
@@ -1,5 +1,5 @@
-/* OverlayLayout.java --
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+/* OverlayLayout.java -- A layout manager
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,155 +37,376 @@ exception statement from your version. */
package javax.swing;
+import java.awt.AWTError;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
+import java.awt.Insets;
import java.awt.LayoutManager2;
import java.io.Serializable;
/**
- * OverlayLayout
- * @author Andrew Selkirk
- * @version 1.0
+ * A layout manager that lays out the components of a container one over
+ * another.
+ *
+ * The components take as much space as is available in the container, but not
+ * more than specified by their maximum size.
+ *
+ * The overall layout is mainly affected by the components
+ * <code>alignmentX</code> and <code>alignmentY</code> properties. All
+ * components are aligned, so that their alignment points (for either
+ * direction) are placed in one line (the baseline for this direction).
+ *
+ * For example: An X alignment of 0.0 means that the component's alignment
+ * point is at it's left edge, an X alignment of 0.5 means that the alignment
+ * point is in the middle, an X alignment of 1.0 means, the aligment point is
+ * at the right edge. So if you have three components, the first with 0.0, the
+ * second with 0.5 and the third with 1.0, then they are laid out like this:
+ *
+ * <pre>
+ * +-------+
+ * | 1 |
+ * +-------+
+ * +-------+
+ * | 2 |
+ * +-------+
+ * +---------+
+ * | 3 +
+ * +---------+
+ * </pre>
+ * The above picture shows the X alignment between the components. An Y
+ * alignment like shown above cannot be achieved with this layout manager. The
+ * components are place on top of each other, with the X alignment shown above.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ * @author Andrew Selkirk
*/
-public class OverlayLayout
- implements LayoutManager2, Serializable
+public class OverlayLayout implements LayoutManager2, Serializable
{
private static final long serialVersionUID = 18082829169631543L;
- //-------------------------------------------------------------
- // Variables --------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * target
- */
- private Container target;
-
- /**
- * xChildren
- */
- private SizeRequirements[] xChildren;
-
- /**
- * yChildren
- */
- private SizeRequirements[] yChildren;
-
- /**
- * xTotal
- */
- private SizeRequirements xTotal;
-
- /**
- * yTotal
- */
- private SizeRequirements yTotal;
-
-
- //-------------------------------------------------------------
- // Initialization ---------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * Constructor OverlayLayout
- * @param target TODO
- */
- public OverlayLayout(Container target) {
- // TODO
- } // OverlayLayout()
-
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * invalidateLayout
- * @param target TODO
- */
- public void invalidateLayout(Container target) {
- // TODO
- } // invalidateLayout()
-
- /**
- * addLayoutComponent
- * @param string TODO
- * @param component TODO
- */
- public void addLayoutComponent(String string, Component component) {
- // TODO
- } // addLayoutComponent()
-
- /**
- * addLayoutComponent
- * @param component TODO
- * @param constraints TODO
- */
- public void addLayoutComponent(Component component, Object constraints) {
- // TODO
- } // addLayoutComponent()
-
- /**
- * removeLayoutComponent
- * @param component TODO
- */
- public void removeLayoutComponent(Component component) {
- // TODO
- } // removeLayoutComponent()
-
- /**
- * preferredLayoutSize
- * @param target TODO
- * @returns Dimension
- */
- public Dimension preferredLayoutSize(Container target) {
- return null; // TODO
- } // preferredLayoutSize()
-
- /**
- * minimumLayoutSize
- * @param target TODO
- * @returns Dimension
- */
- public Dimension minimumLayoutSize(Container target) {
- return null; // TODO
- } // minimumLayoutSize()
-
- /**
- * maximumLayoutSize
- * @param target TODO
- * @returns Dimension
- */
- public Dimension maximumLayoutSize(Container target) {
- return null; // TODO
- } // maximumLayoutSize()
-
- /**
- * getLayoutAlignmentX
- * @param target TODO
- * @returns float
- */
- public float getLayoutAlignmentX(Container target) {
- return (float) 0.0; // TODO
- } // getLayoutAlignmentX()
-
- /**
- * getLayoutAlignmentY
- * @param target TODO
- * @returns float
- */
- public float getLayoutAlignmentY(Container target) {
- return (float) 0.0; // TODO
- } // getLayoutAlignmentY()
-
- /**
- * layoutContainer
- * @param target TODO
- */
- public void layoutContainer(Container target) {
- // TODO
- } // layoutContainer()
-
-
-} // OverlayLayout
+ /**
+ * The container to be laid out.
+ */
+ private Container target;
+
+ /**
+ * The size requirements of the containers children for the X direction.
+ */
+ private SizeRequirements[] xChildren;
+
+ /**
+ * The size requirements of the containers children for the Y direction.
+ */
+ private SizeRequirements[] yChildren;
+
+ /**
+ * The size requirements of the container to be laid out for the X direction.
+ */
+ private SizeRequirements xTotal;
+
+ /**
+ * The size requirements of the container to be laid out for the Y direction.
+ */
+ private SizeRequirements yTotal;
+
+ /**
+ * The offsets of the child components in the X direction.
+ */
+ private int[] offsetsX;
+
+ /**
+ * The offsets of the child components in the Y direction.
+ */
+ private int[] offsetsY;
+
+ /**
+ * The spans of the child components in the X direction.
+ */
+ private int[] spansX;
+
+ /**
+ * The spans of the child components in the Y direction.
+ */
+ private int[] spansY;
+
+ /**
+ * Creates a new OverlayLayout for the specified container.
+ *
+ * @param target the container to be laid out
+ */
+ public OverlayLayout(Container target)
+ {
+ this.target = target;
+ }
+
+ /**
+ * Notifies the layout manager that the layout has become invalid. It throws
+ * away cached layout information and recomputes it the next time it is
+ * requested.
+ *
+ * @param target not used here
+ */
+ public void invalidateLayout(Container target)
+ {
+ xChildren = null;
+ yChildren = null;
+ xTotal = null;
+ yTotal = null;
+ offsetsX = null;
+ offsetsY = null;
+ spansX = null;
+ spansY = null;
+ }
+
+ /**
+ * This method is not used in this layout manager.
+ *
+ * @param string not used here
+ * @param component not used here
+ */
+ public void addLayoutComponent(String string, Component component)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * This method is not used in this layout manager.
+ *
+ * @param component not used here
+ * @param constraints not used here
+ */
+ public void addLayoutComponent(Component component, Object constraints)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * This method is not used in this layout manager.
+ *
+ * @param component not used here
+ */
+ public void removeLayoutComponent(Component component)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the preferred size of the container that is laid out. This is
+ * computed by the children's preferred sizes, taking their alignments into
+ * account.
+ *
+ * @param target not used here
+ *
+ * @returns the preferred size of the container that is laid out
+ */
+ public Dimension preferredLayoutSize(Container target)
+ {
+ if (target != this.target)
+ throw new AWTError("OverlayLayout can't be shared");
+
+ checkTotalRequirements();
+ return new Dimension(xTotal.preferred, yTotal.preferred);
+ }
+
+ /**
+ * Returns the minimum size of the container that is laid out. This is
+ * computed by the children's minimum sizes, taking their alignments into
+ * account.
+ *
+ * @param target not used here
+ *
+ * @returns the minimum size of the container that is laid out
+ */
+ public Dimension minimumLayoutSize(Container target)
+ {
+ if (target != this.target)
+ throw new AWTError("OverlayLayout can't be shared");
+
+ checkTotalRequirements();
+ return new Dimension(xTotal.minimum, yTotal.minimum);
+ }
+
+ /**
+ * Returns the maximum size of the container that is laid out. This is
+ * computed by the children's maximum sizes, taking their alignments into
+ * account.
+ *
+ * @param target not used here
+ *
+ * @returns the maximum size of the container that is laid out
+ */
+ public Dimension maximumLayoutSize(Container target)
+ {
+ if (target != this.target)
+ throw new AWTError("OverlayLayout can't be shared");
+
+ checkTotalRequirements();
+ return new Dimension(xTotal.maximum, yTotal.maximum);
+ }
+
+ /**
+ * Returns the X alignment of the container that is laid out. This is
+ * computed by the children's preferred sizes, taking their alignments into
+ * account.
+ *
+ * @param target not used here
+ *
+ * @returns the X alignment of the container that is laid out
+ */
+ public float getLayoutAlignmentX(Container target)
+ {
+ if (target != this.target)
+ throw new AWTError("OverlayLayout can't be shared");
+
+ checkTotalRequirements();
+ return xTotal.alignment;
+ }
+
+ /**
+ * Returns the Y alignment of the container that is laid out. This is
+ * computed by the children's preferred sizes, taking their alignments into
+ * account.
+ *
+ * @param target not used here
+ *
+ * @returns the X alignment of the container that is laid out
+ */
+ public float getLayoutAlignmentY(Container target)
+ {
+ if (target != this.target)
+ throw new AWTError("OverlayLayout can't be shared");
+
+ checkTotalRequirements();
+ return yTotal.alignment;
+ }
+
+ /**
+ * Lays out the container and it's children.
+ *
+ * The children are laid out one over another.
+ *
+ * The components take as much space as is available in the container, but
+ * not more than specified by their maximum size.
+ *
+ * The overall layout is mainly affected by the components
+ * <code>alignmentX</code> and <code>alignmentY</code> properties. All
+ * components are aligned, so that their alignment points (for either
+ * direction) are placed in one line (the baseline for this direction).
+ *
+ * For example: An X alignment of 0.0 means that the component's alignment
+ * point is at it's left edge, an X alignment of 0.5 means that the alignment
+ * point is in the middle, an X alignment of 1.0 means, the aligment point is
+ * at the right edge. So if you have three components, the first with 0.0,
+ * the second with 0.5 and the third with 1.0, then they are laid out like
+ * this:
+ *
+ * <pre>
+ * +-------+
+ * | 1 |
+ * +-------+
+ * +-------+
+ * | 2 |
+ * +-------+
+ * +---------+
+ * | 3 +
+ * +---------+
+ * </pre>
+ * The above picture shows the X alignment between the components. An Y
+ * alignment like shown above cannot be achieved with this layout manager.
+ * The components are place on top of each other, with the X alignment shown
+ * above.
+ *
+ * @param target not used here
+ */
+ public void layoutContainer(Container target)
+ {
+ if (target != this.target)
+ throw new AWTError("OverlayLayout can't be shared");
+
+ checkLayout();
+ Component[] children = target.getComponents();
+ for (int i = 0; i < children.length; i++)
+ children[i].setBounds(offsetsX[i], offsetsY[i], spansX[i], spansY[i]);
+ }
+
+ /**
+ * Makes sure that the xChildren and yChildren fields are correctly set up.
+ * A call to {@link #invalidateLayout(Container)} sets these fields to null,
+ * so they have to be set up again.
+ */
+ private void checkRequirements()
+ {
+ if (xChildren == null || yChildren == null)
+ {
+ Component[] children = target.getComponents();
+ xChildren = new SizeRequirements[children.length];
+ yChildren = new SizeRequirements[children.length];
+ for (int i = 0; i < children.length; i++)
+ {
+ if (! children[i].isVisible())
+ {
+ xChildren[i] = new SizeRequirements();
+ yChildren[i] = new SizeRequirements();
+ }
+ else
+ {
+ xChildren[i] =
+ new SizeRequirements(children[i].getMinimumSize().width,
+ children[i].getPreferredSize().width,
+ children[i].getMaximumSize().width,
+ children[i].getAlignmentX());
+ yChildren[i] =
+ new SizeRequirements(children[i].getMinimumSize().height,
+ children[i].getPreferredSize().height,
+ children[i].getMaximumSize().height,
+ children[i].getAlignmentY());
+ }
+ }
+ }
+ }
+
+ /**
+ * Makes sure that the xTotal and yTotal fields are set up correctly. A call
+ * to {@link #invalidateLayout} sets these fields to null and they have to be
+ * recomputed.
+ */
+ private void checkTotalRequirements()
+ {
+ if (xTotal == null || yTotal == null)
+ {
+ checkRequirements();
+ xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren);
+ yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren);
+ }
+ }
+
+ /**
+ * Makes sure that the offsetsX, offsetsY, spansX and spansY fields are set
+ * up correctly. A call to {@link #invalidateLayout} sets these fields
+ * to null and they have to be recomputed.
+ */
+ private void checkLayout()
+ {
+ if (offsetsX == null || offsetsY == null || spansX == null
+ || spansY == null)
+ {
+ checkRequirements();
+ checkTotalRequirements();
+ int len = target.getComponents().length;
+ offsetsX = new int[len];
+ offsetsY = new int[len];
+ spansX = new int[len];
+ spansY = new int[len];
+
+ Insets in = target.getInsets();
+ int width = target.getWidth() - in.left - in.right;
+ int height = target.getHeight() - in.top - in.bottom;
+
+ SizeRequirements.calculateAlignedPositions(width, xTotal,
+ xChildren, offsetsX, spansX);
+ SizeRequirements.calculateAlignedPositions(height, yTotal,
+ yChildren, offsetsY, spansY);
+ }
+ }
+}
diff --git a/libjava/classpath/javax/swing/Popup.java b/libjava/classpath/javax/swing/Popup.java
index 69e1f516802..cbb243e285a 100644
--- a/libjava/classpath/javax/swing/Popup.java
+++ b/libjava/classpath/javax/swing/Popup.java
@@ -39,6 +39,8 @@ exception statement from your version. */
package javax.swing;
import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.Point;
/**
@@ -89,6 +91,7 @@ public class Popup
*/
protected Popup()
{
+ // Nothing to do here.
}
@@ -129,6 +132,7 @@ public class Popup
*/
JWindow window;
+ private Component contents;
/**
* Constructs a new <code>JWindowPopup</code> given its owner,
@@ -155,10 +159,11 @@ public class Popup
/* Checks whether contents is null. */
super(owner, contents, x, y);
+ this.contents = contents;
window = new JWindow();
- window.getRootPane().add(contents);
+ window.getContentPane().add(contents);
window.setLocation(x, y);
- window.pack();
+ window.setFocusableWindowState(false);
}
@@ -168,6 +173,7 @@ public class Popup
*/
public void show()
{
+ window.setSize(contents.getSize());
window.show();
}
@@ -186,4 +192,106 @@ public class Popup
window.dispose();
}
}
+
+ /**
+ * A popup that displays itself within the JLayeredPane of a JRootPane of
+ * the containment hierarchy of the owner component.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ static class LightweightPopup extends Popup
+ {
+ /**
+ * The owner component for this popup.
+ */
+ Component owner;
+
+ /**
+ * The contents that should be shown.
+ */
+ Component contents;
+
+ /**
+ * The X location in screen coordinates.
+ */
+ int x;
+
+ /**
+ * The Y location in screen coordinates.
+ */
+ int y;
+
+ /**
+ * The panel that holds the content.
+ */
+ private JPanel panel;
+
+ /**
+ * The layered pane of the owner.
+ */
+ private JLayeredPane layeredPane;
+
+ /**
+ * Constructs a new <code>LightweightPopup</code> given its owner,
+ * contents and the screen position where the popup
+ * will appear.
+ *
+ * @param owner the component that should own the popup window; this
+ * provides the JRootPane in which we place the popup window
+ *
+ * @param contents the contents that will be displayed inside
+ * the <code>Popup</code>.
+ *
+ * @param x the horizontal position where the Popup will appear in screen
+ * coordinates
+ *
+ * @param y the vertical position where the Popup will appear in screen
+ * coordinates
+ *
+ * @throws IllegalArgumentException if <code>contents</code>
+ * is <code>null</code>.
+ */
+ public LightweightPopup(Component owner, Component contents, int x, int y)
+ {
+ super(owner, contents, x, y);
+ this.owner = owner;
+ this.contents = contents;
+ this.x = x;
+ this.y = y;
+
+ JRootPane rootPane = SwingUtilities.getRootPane(owner);
+ JLayeredPane layeredPane = rootPane.getLayeredPane();
+ this.layeredPane = layeredPane;
+ }
+
+ /**
+ * Places the popup within the JLayeredPane of the owner component and
+ * makes it visible.
+ */
+ public void show()
+ {
+ // We insert a JPanel between the layered pane and the contents so we
+ // can fiddle with the setLocation() method without disturbing a
+ // JPopupMenu (which overrides setLocation in an unusual manner).
+ if (panel == null)
+ {
+ panel = new JPanel();
+ panel.setLayout(new FlowLayout(0, 0, 0));
+ }
+
+ panel.add(contents);
+ panel.setSize(contents.getSize());
+ Point layeredPaneLoc = layeredPane.getLocationOnScreen();
+ panel.setLocation(x - layeredPaneLoc.x, y - layeredPaneLoc.y);
+ layeredPane.add(panel, JLayeredPane.POPUP_LAYER);
+ }
+
+ /**
+ * Removes the popup from the JLayeredPane thus making it invisible.
+ */
+ public void hide()
+ {
+ layeredPane.remove(panel);
+ }
+ }
}
diff --git a/libjava/classpath/javax/swing/PopupFactory.java b/libjava/classpath/javax/swing/PopupFactory.java
index 29cf86d5530..7bb2529cd54 100644
--- a/libjava/classpath/javax/swing/PopupFactory.java
+++ b/libjava/classpath/javax/swing/PopupFactory.java
@@ -39,6 +39,8 @@ exception statement from your version. */
package javax.swing;
import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Point;
/**
@@ -55,8 +57,8 @@ public class PopupFactory
/**
* The shared factory object.
*
- * @see #getSharedFactory
- * @see #setSharedFactory
+ * @see #getSharedInstance
+ * @see #setSharedInstance
*/
private static PopupFactory sharedFactory;
@@ -69,6 +71,7 @@ public class PopupFactory
*/
public PopupFactory()
{
+ // Nothing to do here.
}
@@ -134,6 +137,30 @@ public class PopupFactory
public Popup getPopup(Component owner, Component contents,
int x, int y)
{
- return new Popup.JWindowPopup(owner, contents, x, y);
+ Popup popup = null;
+ // By default we enable lightweight popups since they are more efficient
+ // than heavyweight popups.
+ boolean lightweightEnabled = true;
+ // Special case JPopupMenu here, since it supports a lightweightEnabled
+ // flag that we must respect.
+ if (contents instanceof JPopupMenu)
+ {
+ JPopupMenu menu = (JPopupMenu) contents;
+ lightweightEnabled = menu.isLightWeightPopupEnabled();
+ }
+
+ // If we have a root pane and the contents fits within the root pane and
+ // lightweight popups are enabled, than we can use a lightweight popup.
+ JRootPane root = SwingUtilities.getRootPane(owner);
+ Point rootLoc = root.getLocationOnScreen();
+ Dimension contentsSize = contents.getSize();
+ Dimension rootSize = root.getSize();
+ if (x >= rootLoc.x && y > rootLoc.y
+ && (x - rootLoc.x) + contentsSize.width < rootSize.width
+ && (y - rootLoc.y) + contentsSize.height < rootSize.height)
+ popup = new Popup.LightweightPopup(owner, contents, x, y);
+ else
+ popup = new Popup.JWindowPopup(owner, contents, x, y);
+ return popup;
}
}
diff --git a/libjava/classpath/javax/swing/ProgressMonitor.java b/libjava/classpath/javax/swing/ProgressMonitor.java
index 844258f1b90..60f1c7145c0 100644
--- a/libjava/classpath/javax/swing/ProgressMonitor.java
+++ b/libjava/classpath/javax/swing/ProgressMonitor.java
@@ -1,5 +1,5 @@
/* ProgressMonitor.java --
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,191 +38,386 @@ exception statement from your version. */
package javax.swing;
import java.awt.Component;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
/**
- * ProgressMonitor
- * @author Andrew Selkirk
- * @version 1.0
+ * <p>Using this class you can easily monitor tasks where you cannot
+ * estimate the duration exactly.</p>
+ *
+ * <p>A ProgressMonitor instance waits until the first time setProgress
+ * is called. When <code>millisToDecideToPopup</code> time elapsed the
+ * instance estimates the duration until the whole operation is completed.
+ * If this duration exceeds <code>millisToPopup</code> a non-modal dialog
+ * with a message and a progress bar is shown.</p>
+ *
+ * <p>The value of <code>millisToDecideToPopup</code> defaults to
+ * <code>500</code> and <code>millisToPopup</code> to
+ * <code>2000</code>.</p>
+ *
+ * @author Andrew Selkirk
+ * @author Robert Schuster (robertschuster@fsfe.org)
+ * @since 1.2
+ * @status updated to 1.2
*/
-public class ProgressMonitor {
-
- //-------------------------------------------------------------
- // Variables --------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * parentComponent
- */
- private Component component;
-
- /**
- * note
- */
- private String note;
-
- /**
- * message
- */
- private Object message;
-
- /**
- * millisToDecideToPopup
- */
- private int millisToDecideToPopup;
-
- /**
- * millisToPopup
- */
- private int millisToPopup;
-
- /**
- * min
- */
- private int minimum;
-
- /**
- * max
- */
- private int maximum;
-
-
- //-------------------------------------------------------------
- // Initialization ---------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * Constructor ProgressMonitor
- * @param component TODO
- * @param message TODO
- * @param note TODO
- * @param minimum TODO
- * @param maximum TODO
- */
- public ProgressMonitor(Component component, Object message,
- String note, int minimum, int maximum) {
-
- // Set Data
- this.component = component;
- this.message = message;
- this.note = note;
- this.minimum = minimum;
- this.maximum = maximum;
-
- // TODO
- } // ProgressMonitor()
-
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * close
- */
- public void close() {
- // TODO
- } // close()
-
- /**
- * setProgress
- * @param progress TODO
- */
- public void setProgress(int progress) {
- // TODO
- } // setProgress()
-
- /**
- * getMinimum
- * @returns int
- */
- public int getMinimum() {
- return minimum; // TODO
- } // getMinimum()
-
- /**
- * setMinimum
- * @param minimum TODO
- */
- public void setMinimum(int minimum) {
- this.minimum = minimum;
- // TODO
- } // setMinimum()
-
- /**
- * getMaximum
- * @returns int
- */
- public int getMaximum() {
- return maximum; // TODO
- } // getMaximum()
-
- /**
- * setMaximum
- * @param maximum TODO
- */
- public void setMaximum(int maximum) {
- this.maximum = maximum;
- // TODO
- } // setMaximum()
-
- /**
- * isCanceled
- * @returns boolean
- */
- public boolean isCanceled() {
- return false; // TODO
- } // isCanceled()
-
- /**
- * getMillisToDecideToPopup
- * @returns int
- */
- public int getMillisToDecideToPopup() {
- return millisToDecideToPopup; // TODO
- } // getMillisToDecideToPopup()
-
- /**
- * setMillisToDecideToPopup
- * @param time TODO
- */
- public void setMillisToDecideToPopup(int time) {
- millisToDecideToPopup = time;
- // TODO
- } // setMillisToDecideToPopup()
-
- /**
- * getMillisToPopup
- * @returns int
- */
- public int getMillisToPopup() {
- return millisToPopup; // TODO
- } // getMillisToPopup()
-
- /**
- * setMillisToPopup
- * @param time TODO
- */
- public void setMillisToPopup(int time) {
- millisToPopup = time;
- // TODO
- } // setMillisToPopup()
-
- /**
- * getNote
- * @returns String
- */
- public String getNote() {
- return note; // TODO
- } // getNote()
-
- /**
- * setNote
- * @param note TODO
- */
- public void setNote(String note) {
- this.note = note;
- // TODO
- } // setNote()
-
-
-} // ProgressMonitor
+public class ProgressMonitor
+{
+ /**
+ * parentComponent
+ */
+ Component component;
+
+ /**
+ * note
+ */
+ String note;
+
+ /**
+ * message
+ */
+ Object message;
+
+ /**
+ * millisToDecideToPopup
+ */
+ int millisToDecideToPopup = 500;
+
+ /**
+ * millisToPopup
+ */
+ int millisToPopup = 2000;
+
+ int min, max, progress;
+
+ JProgressBar progressBar;
+
+ JLabel noteLabel;
+
+ JDialog progressDialog;
+
+ Timer timer;
+
+ boolean canceled;
+
+ /**
+ * Constructor ProgressMonitor
+ * @param component The parent component of the progress dialog or <code>null</code>.
+ * @param message A constant message object which works in the way it does in <code>JOptionPane</code>.
+ * @param note A string message which can be changed while the operation goes on.
+ * @param minimum The minimum value for the operation (start value).
+ * @param maximum The maximum value for the operation (end value).
+ */
+ public ProgressMonitor(Component component, Object message,
+ String note, int minimum, int maximum)
+ {
+
+ // Set data.
+ this.component = component;
+ this.message = message;
+ this.note = note;
+
+ min = minimum;
+ max = maximum;
+ }
+
+ /**
+ * <p>Hides the dialog and stops any measurements.</p>
+ *
+ * <p>Has no effect when <code>setProgress</code> is not at least
+ * called once.</p>
+ */
+ public void close()
+ {
+ if ( progressDialog != null )
+ {
+ progressDialog.setVisible(false);
+ }
+
+ if ( timer != null )
+ {
+ timer.stop();
+ timer = null;
+ }
+ }
+
+ /**
+ * <p>Updates the progress value.</p>
+ *
+ * <p>When called for the first time this initializes a timer
+ * which decides after <code>millisToDecideToPopup</code> time
+ * whether to show a progress dialog or not.</p>
+ *
+ * <p>If the progress value equals or exceeds the maximum
+ * value the progress dialog is closed automatically.</p>
+ *
+ * @param progress New progress value.
+ */
+ public void setProgress(int progress)
+ {
+ this.progress = progress;
+
+ // Initializes and starts a timer with a task
+ // which measures the duration and displays
+ // a progress dialog if neccessary.
+ if ( timer == null && progressDialog == null )
+ {
+ timer = new Timer(25, null);
+ timer.addActionListener(new TimerListener());
+ timer.start();
+ }
+
+ // Cancels timer and hides progress dialog if the
+ // maximum value is reached.
+ if ( progressBar != null && this.progress >= progressBar.getMaximum() )
+ {
+ // The reason for using progressBar.getMaximum() instead of max is that
+ // we want to prevent that changes to the value have any effect after the
+ // progress dialog is visible (This is how the JDK behaves.).
+ close();
+ }
+
+ }
+
+ /** Returns the minimum or start value of the operation.
+ *
+ * @returns Minimum or start value of the operation.
+ */
+ public int getMinimum()
+ {
+ return min;
+ }
+
+ /**
+ * <p>Use this method to set the minimum or start value of
+ * your operation.</p>
+ *
+ * <p>For typical application like copy operation this will be
+ * zero.</p>
+ *
+ * <p>Keep in mind that changing this value after the progress
+ * dialog is made visible has no effect upon the progress bar.</p>
+ *
+ * @param minimum The new minimum value.
+ */
+ public void setMinimum(int minimum)
+ {
+ min = minimum;
+ }
+
+ /**
+ * Return the maximum or end value of your operation.
+ *
+ * @returns Maximum or end value.
+ */
+ public int getMaximum()
+ {
+ return max;
+ }
+
+ /**
+ * <p>Sets the maximum or end value of the operation to the
+ * given integer.</p>
+ *
+ * @param maximum
+ */
+ public void setMaximum(int maximum)
+ {
+ max = maximum;
+ }
+
+ /**
+ * Returns whether the user canceled the operation.
+ *
+ * @returns Whether the operation was canceled.
+ */
+ public boolean isCanceled()
+ {
+ // The value is predefined to false
+ // and changes only when the user clicks
+ // the cancel button in the progress dialog.
+ return canceled;
+ }
+
+ /**
+ * Returns the amount of milliseconds to wait
+ * until the ProgressMonitor should decide whether
+ * a progress dialog is to be shown or not.
+ *
+ * @returns The duration in milliseconds.
+ */
+ public int getMillisToDecideToPopup()
+ {
+ return millisToDecideToPopup;
+ }
+
+ /**
+ * Sets the amount of milliseconds to wait until the
+ * ProgressMonitor should decide whether a progress dialog
+ * is to be shown or not.
+ *
+ * <p>This method has no effect when the progress dialog
+ * is already visible.</p>
+ *
+ * @param time The duration in milliseconds.
+ */
+ public void setMillisToDecideToPopup(int time)
+ {
+ millisToDecideToPopup = time;
+ }
+
+ /**
+ * getMillisToPopup
+ * @returns int
+ */
+ public int getMillisToPopup()
+ {
+ return millisToPopup;
+ }
+
+ /**
+ * setMillisToPopup
+ * @param time TODO
+ */
+ public void setMillisToPopup(int time)
+ {
+ millisToPopup = time;
+ }
+
+ /**
+ * Returns a message which is shown in the progress dialog.
+ *
+ * @returns The changeable message visible in the progress dialog.
+ */
+ public String getNote()
+ {
+ return note;
+ }
+
+ /**
+ * <p>Set the message shown in the progess dialog.</p>
+ *
+ * <p>Changing the note while the progress dialog is visible
+ * is possible.</p>
+ *
+ * @param note A message shown in the progress dialog.
+ */
+ public void setNote(String note)
+ {
+ if ( noteLabel != null )
+ {
+ noteLabel.setText(note);
+ }
+ else
+ {
+ this.note = note;
+ }
+ }
+
+ /** Internal method that creates the progress dialog.
+ */
+ void createDialog()
+ {
+ // If there is no note we suppress the generation of the
+ // label.
+ Object[] tmp = (note == null) ?
+ new Object[]
+ {
+ message,
+ progressBar = new JProgressBar(min, max)
+ }
+ :
+ new Object[]
+ {
+ message,
+ noteLabel = new JLabel(note),
+ progressBar = new JProgressBar(min, max)
+ };
+
+ JOptionPane pane = new JOptionPane(tmp, JOptionPane.INFORMATION_MESSAGE);
+
+ // FIXME: Internationalize the button
+ JButton cancelButton = new JButton("Cancel");
+ cancelButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ae)
+ {
+ canceled = true;
+ }
+ });
+
+ pane.setOptions(new Object[] { cancelButton });
+
+ // FIXME: Internationalize the title
+ progressDialog = pane.createDialog(component, "Progress ...");
+ progressDialog.setModal(false);
+ progressDialog.setResizable(true);
+
+ progressDialog.pack();
+ progressDialog.setVisible(true);
+
+ }
+
+ /** An ActionListener implementation which does the measurements
+ * and estimations of the ProgressMonitor.
+ */
+ class TimerListener implements ActionListener
+ {
+ long timestamp;
+
+ int lastProgress;
+
+ boolean first = true;
+
+ TimerListener()
+ {
+ timestamp = System.currentTimeMillis();
+ }
+
+ public void actionPerformed(ActionEvent ae)
+ {
+ long now = System.currentTimeMillis();
+
+ if ( first )
+ {
+ if (( now - timestamp ) > millisToDecideToPopup )
+ {
+ first = false;
+ long expected = ( now - timestamp ) * ( max - min ) / ( progress - min );
+
+ if ( expected > millisToPopup )
+ {
+ createDialog();
+ }
+ }
+ else
+ {
+ // We have not waited long enough to make a decision,
+ // so return and try again when the timer is invoked.
+ return;
+ }
+ }
+ else if ( progressDialog != null )
+ {
+ // The progress dialog is being displayed. We now calculate
+ // whether setting the progress bar to the current progress
+ // value would result in a visual difference.
+ int delta = progress - progressBar.getValue();
+
+ if ( ( delta * progressBar.getWidth() / (max - min) ) > 0 )
+ {
+ // At least one pixel would change.
+ progressBar.setValue(progress);
+ }
+ }
+ else
+ {
+ // No dialog necessary
+ timer.stop();
+ timer = null;
+ }
+
+ timestamp = now;
+ }
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/ProgressMonitorInputStream.java b/libjava/classpath/javax/swing/ProgressMonitorInputStream.java
index 2022a1c24a3..02ac597b3a4 100644
--- a/libjava/classpath/javax/swing/ProgressMonitorInputStream.java
+++ b/libjava/classpath/javax/swing/ProgressMonitorInputStream.java
@@ -1,5 +1,5 @@
/* ProgressMonitorInputStream.java --
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,122 +39,187 @@ exception statement from your version. */
package javax.swing;
import java.awt.Component;
+
import java.io.FilterInputStream;
-import java.io.IOException;
import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.IOException;
/**
* ProgressMonitorInputStream
* @author Andrew Selkirk
- * @version 1.0
+ * @author Robert Schuster (robertschuster@fsfe.org)
+ * @status updated to 1.2
+ * @since 1.2
*/
-public class ProgressMonitorInputStream extends FilterInputStream {
-
- //-------------------------------------------------------------
- // Variables --------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * monitor
- */
- private ProgressMonitor monitor;
-
- /**
- * nread
- */
- private int nread;
-
- /**
- * size
- */
- private int size;
-
-
- //-------------------------------------------------------------
- // Initialization ---------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * Constructor ProgressMonitorInputStream
- * @param component TODO
- * @param message TODO
- * @param stream TODO
- */
- public ProgressMonitorInputStream(Component component, Object message,
- InputStream stream) {
- super(stream);
- // TODO
- } // ProgressMonitorInputStream()
-
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * reset
- * @exception IOException TODO
- */
- public synchronized void reset() throws IOException {
- // TODO
- } // reset()
-
- /**
- * read
- * @exception IOException TODO
- * @returns int
- */
- public int read() throws IOException {
- return 0; // TODO
- } // read()
-
- /**
- * read
- * @param data TODO
- * @exception IOException TODO
- * @returns int
- */
- public int read(byte[] data) throws IOException {
- return 0; // TODO
- } // read()
-
- /**
- * read
- * @param data TODO
- * @param offset TODO
- * @param length TODO
- * @exception IOException TODO
- * @returns int
- */
- public int read(byte[] data, int offset, int length) throws IOException {
- return 0; // TODO
- } // read()
-
- /**
- * skip
- * @param length TODO
- * @exception IOException TODO
- * @returns long
- */
- public long skip(long length) throws IOException {
- return 0; // TODO
- } // skip()
-
- /**
- * close
- * @exception IOException TODO
- */
- public void close() throws IOException {
- // TODO
- } // close()
-
- /**
- * getProgressMonitor
- * @returns ProgressMonitor
- */
- public ProgressMonitor getProgressMonitor() {
- return null; // TODO
- } // getProgressMonitor()
-
-
-} // ProgressMonitorInputStream
+public class ProgressMonitorInputStream extends FilterInputStream
+{
+
+ /**
+ * monitor
+ */
+ private ProgressMonitor monitor;
+
+ /**
+ * read
+ */
+ private int read;
+
+ /**
+ * Constructor ProgressMonitorInputStream
+ * @param component TODO
+ * @param message TODO
+ * @param stream TODO
+ */
+ public ProgressMonitorInputStream(Component component, Object message,
+ InputStream stream)
+ {
+ super(stream);
+
+ int max = 0;
+
+ try
+ {
+ max = stream.available();
+ }
+ catch ( IOException ioe )
+ {
+ // Behave like the JDK here.
+ }
+
+ monitor = new ProgressMonitor(
+ component, message, null, 0, max );
+ }
+
+ /**
+ * reset
+ * @exception IOException TODO
+ */
+ public void reset() throws IOException
+ {
+ super.reset();
+
+ checkMonitorCanceled();
+
+ // TODO: The docs says the monitor should be resetted. But to which
+ // value? (mark is not overridden)
+ }
+
+ /**
+ * read
+ * @exception IOException TODO
+ * @returns int
+ */
+ public int read() throws IOException
+ {
+ int t = super.read();
+
+ monitor.setProgress(++read);
+
+ checkMonitorCanceled();
+
+ return t;
+ }
+
+ /**
+ * read
+ * @param data TODO
+ * @exception IOException TODO
+ * @returns int
+ */
+ public int read(byte[] data) throws IOException
+ {
+ int t = super.read(data);
+
+ if ( t > 0 )
+ {
+ read += t;
+ monitor.setProgress(read);
+
+ checkMonitorCanceled();
+ }
+ else
+ {
+ monitor.close();
+ }
+
+ return t;
+ }
+
+ /**
+ * read
+ * @param data TODO
+ * @param offset TODO
+ * @param length TODO
+ * @exception IOException TODO
+ * @returns int
+ */
+ public int read(byte[] data, int offset, int length) throws IOException
+ {
+ int t = super.read(data, offset, length);
+
+ if ( t > 0 )
+ {
+ read += t;
+ monitor.setProgress(read);
+
+ checkMonitorCanceled();
+ }
+ else
+ {
+ monitor.close();
+ }
+
+ return t;
+ }
+
+ /**
+ * skip
+ * @param length TODO
+ * @exception IOException TODO
+ * @returns long
+ */
+ public long skip(long length) throws IOException
+ {
+ long t = super.skip(length);
+
+ // 'read' may overflow here in rare situations.
+ assert ( (long) read + t <= (long) Integer.MAX_VALUE );
+
+ read += (int) t;
+
+ monitor.setProgress(read);
+
+ checkMonitorCanceled();
+
+ return t;
+ }
+
+ /**
+ * close
+ * @exception IOException TODO
+ */
+ public void close() throws IOException
+ {
+ super.close();
+ monitor.close();
+ }
+
+ /**
+ * getProgressMonitor
+ * @returns ProgressMonitor
+ */
+ public ProgressMonitor getProgressMonitor()
+ {
+ return monitor;
+ }
+
+ private void checkMonitorCanceled() throws InterruptedIOException
+ {
+ if ( monitor.isCanceled() )
+ {
+ throw new InterruptedIOException("ProgressMonitor was canceled");
+ }
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/Renderer.java b/libjava/classpath/javax/swing/Renderer.java
index c803e38fcc0..9a0e81a9f36 100644
--- a/libjava/classpath/javax/swing/Renderer.java
+++ b/libjava/classpath/javax/swing/Renderer.java
@@ -49,24 +49,20 @@ import java.awt.Component;
*
* @author Andrew Selkirk
*/
-public interface Renderer {
+public interface Renderer
+{
+ /**
+ * setValue
+ * @param value TODO
+ * @param selected TODO
+ */
+ void setValue(Object value, boolean selected);
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
+ /**
+ * getComponent
+ * @returns Component
+ */
+ Component getComponent();
- /**
- * setValue
- * @param value TODO
- * @param selected TODO
- */
- void setValue(Object value, boolean selected);
- /**
- * getComponent
- * @returns Component
- */
- Component getComponent();
-
-
-} // Renderer
+}
diff --git a/libjava/classpath/javax/swing/RepaintManager.java b/libjava/classpath/javax/swing/RepaintManager.java
index 698dbe8e898..b857b126180 100644
--- a/libjava/classpath/javax/swing/RepaintManager.java
+++ b/libjava/classpath/javax/swing/RepaintManager.java
@@ -1,5 +1,5 @@
/* RepaintManager.java --
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -43,12 +43,11 @@ import java.awt.Dimension;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.VolatileImage;
-import java.util.Enumeration;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
-import java.util.Hashtable;
import java.util.Iterator;
-import java.util.Map;
-import java.util.Vector;
/**
* <p>The repaint manager holds a set of dirty regions, invalid components,
@@ -66,7 +65,11 @@ import java.util.Vector;
*/
public class RepaintManager
{
-
+ /**
+ * The current repaint managers, indexed by their ThreadGroups.
+ */
+ static HashMap currentRepaintManagers;
+
/**
* <p>A helper class which is placed into the system event queue at
* various times in order to facilitate repainting and layout. There is
@@ -80,33 +83,95 @@ public class RepaintManager
* 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;
+ ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
+ RepaintManager rm =
+ (RepaintManager) currentRepaintManagers.get(threadGroup);
setLive(false);
rm.validateInvalidComponents();
rm.paintDirtyRegions();
}
+
+ }
+
+ /**
+ * Compares two components using their depths in the component hierarchy.
+ * A component with a lesser depth (higher level components) are sorted
+ * before components with a deeper depth (low level components). This is used
+ * to order paint requests, so that the higher level components are painted
+ * before the low level components get painted.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class ComponentComparator implements Comparator
+ {
+
+ /**
+ * Compares two components.
+ *
+ * @param o1 the first component
+ * @param o2 the second component
+ *
+ * @return a negative integer, if <code>o1</code> is higher in the
+ * hierarchy than <code>o2</code>, zero, if both are at the same
+ * level and a positive integer, if <code>o1</code> is deeper in
+ * the hierarchy than <code>o2</code>
+ */
+ public int compare(Object o1, Object o2)
+ {
+ if (o1 instanceof JComponent && o2 instanceof JComponent)
+ {
+ JComponent c1 = (JComponent) o1;
+ JComponent c2 = (JComponent) o2;
+ return getDepth(c1) - getDepth(c2);
+ }
+ else
+ throw new ClassCastException("This comparator can only be used with "
+ + "JComponents");
+ }
+
+ /**
+ * Computes the depth for a given JComponent.
+ *
+ * @param c the component to compute the depth for
+ *
+ * @return the depth of the component
+ */
+ private int getDepth(JComponent c)
+ {
+ Component comp = c;
+ int depth = 0;
+ while (comp != null)
+ {
+ comp = comp.getParent();
+ depth++;
+ }
+ return depth;
+ }
}
-
/**
* A table storing the dirty regions of components. The keys of this
* table are components, the values are rectangles. Each component maps
@@ -119,7 +184,20 @@ public class RepaintManager
* @see #markCompletelyClean
* @see #markCompletelyDirty
*/
- Hashtable dirtyComponents;
+ HashMap dirtyComponents;
+
+ HashMap workDirtyComponents;
+
+ /**
+ * Stores the order in which the components get repainted.
+ */
+ ArrayList repaintOrder;
+ ArrayList workRepaintOrder;
+
+ /**
+ * The comparator used for ordered inserting into the repaintOrder list.
+ */
+ Comparator comparator;
/**
* A single, shared instance of the helper class. Any methods which mark
@@ -142,14 +220,15 @@ public class RepaintManager
* @see #removeInvalidComponent
* @see #validateInvalidComponents
*/
- Vector invalidComponents;
+ ArrayList invalidComponents;
+ ArrayList workInvalidComponents;
/**
* 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 #isDoubleBufferingEnabled
* @see #setDoubleBufferingEnabled
*/
boolean doubleBufferingEnabled;
@@ -176,53 +255,62 @@ public class RepaintManager
/**
- * The global, shared RepaintManager instance. This is reused for all
- * components in all windows. This is package-private to avoid an accessor
- * method.
- *
- * @see #currentManager
- * @see #setCurrentManager
- */
- static RepaintManager globalManager;
-
- /**
* Create a new RepaintManager object.
*/
public RepaintManager()
{
- dirtyComponents = new Hashtable();
- invalidComponents = new Vector();
+ dirtyComponents = new HashMap();
+ workDirtyComponents = new HashMap();
+ repaintOrder = new ArrayList();
+ workRepaintOrder = new ArrayList();
+ invalidComponents = new ArrayList();
+ workInvalidComponents = new ArrayList();
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.
+ * Returns the <code>RepaintManager</code> for the current thread's
+ * thread group. The default implementation ignores the
+ * <code>component</code> parameter and returns the same repaint manager
+ * for all components.
*
- * @param component A component to look up the manager of
+ * @param component a component to look up the manager of
*
- * @return The current repaint manager
+ * @return the current repaint manager for the calling thread's thread group
+ * and the specified component
*
* @see #setCurrentManager
*/
public static RepaintManager currentManager(Component component)
{
- if (globalManager == null)
- globalManager = new RepaintManager();
- return globalManager;
+ if (currentRepaintManagers == null)
+ currentRepaintManagers = new HashMap();
+ ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
+ RepaintManager currentManager =
+ (RepaintManager) currentRepaintManagers.get(threadGroup);
+ if (currentManager == null)
+ {
+ currentManager = new RepaintManager();
+ currentRepaintManagers.put(threadGroup, currentManager);
+ }
+ return currentManager;
}
/**
- * 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.
+ * Returns the <code>RepaintManager</code> for the current thread's
+ * thread group. The default implementation ignores the
+ * <code>component</code> parameter and returns the same repaint manager
+ * for all components.
*
- * @param component A component to look up the manager of
+ * This method is only here for backwards compatibility with older versions
+ * of Swing and simply forwards to {@link #currentManager(Component)}.
*
- * @return The current repaint manager
+ * @param component a component to look up the manager of
+ *
+ * @return the current repaint manager for the calling thread's thread group
+ * and the specified component
*
* @see #setCurrentManager
*/
@@ -232,15 +320,20 @@ public class RepaintManager
}
/**
- * Set the value of the shared {@link #globalManager} instance.
+ * Sets the repaint manager for the calling thread's thread group.
*
- * @param manager The new value of the shared instance
+ * @param manager the repaint manager to set for the current thread's thread
+ * group
*
- * @see #currentManager(JComponent)
+ * @see #currentManager(Component)
*/
public static void setCurrentManager(RepaintManager manager)
{
- globalManager = manager;
+ if (currentRepaintManagers == null)
+ currentRepaintManagers = new HashMap();
+
+ ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
+ currentRepaintManagers.put(threadGroup, manager);
}
/**
@@ -287,7 +380,7 @@ public class RepaintManager
*/
public synchronized void removeInvalidComponent(JComponent component)
{
- invalidComponents.removeElement(component);
+ invalidComponents.remove(component);
}
/**
@@ -311,12 +404,13 @@ public class RepaintManager
public synchronized void addDirtyRegion(JComponent component, int x, int y,
int w, int h)
{
- if (w == 0 || h == 0)
+ if (w == 0 || h == 0 || !component.isShowing())
return;
-
Rectangle r = new Rectangle(x, y, w, h);
if (dirtyComponents.containsKey(component))
r = r.union((Rectangle)dirtyComponents.get(component));
+ else
+ insertInRepaintOrder(component);
dirtyComponents.put(component, r);
if (! repaintWorker.isLive())
{
@@ -324,7 +418,23 @@ public class RepaintManager
SwingUtilities.invokeLater(repaintWorker);
}
}
-
+
+ /**
+ * Inserts a component into the repaintOrder list in an ordered fashion,
+ * using a binary search.
+ *
+ * @param c the component to be inserted
+ */
+ private void insertInRepaintOrder(JComponent c)
+ {
+ if (comparator == null)
+ comparator = new ComponentComparator();
+ int insertIndex = Collections.binarySearch(repaintOrder, c, comparator);
+ if (insertIndex < 0)
+ insertIndex = -(insertIndex + 1);
+ repaintOrder.add(insertIndex, c);
+ }
+
/**
* Get the dirty region associated with a component, or <code>null</code>
* if the component has no dirty region.
@@ -341,7 +451,10 @@ public class RepaintManager
*/
public Rectangle getDirtyRegion(JComponent component)
{
- return (Rectangle) dirtyComponents.get(component);
+ Rectangle dirty = (Rectangle) dirtyComponents.get(component);
+ if (dirty == null)
+ dirty = new Rectangle();
+ return dirty;
}
/**
@@ -359,6 +472,7 @@ public class RepaintManager
{
Rectangle r = component.getBounds();
addDirtyRegion(component, r.x, r.y, r.width, r.height);
+ component.isCompletelyDirty = true;
}
/**
@@ -374,7 +488,11 @@ public class RepaintManager
*/
public void markCompletelyClean(JComponent component)
{
- dirtyComponents.remove(component);
+ synchronized (this)
+ {
+ dirtyComponents.remove(component);
+ }
+ component.isCompletelyDirty = false;
}
/**
@@ -393,13 +511,9 @@ public class RepaintManager
*/
public boolean isCompletelyDirty(JComponent component)
{
- Rectangle dirty = (Rectangle) dirtyComponents.get(component);
- if (dirty == null)
+ if (! dirtyComponents.containsKey(component))
return false;
- Rectangle r = component.getBounds();
- if (r == null)
- return true;
- return dirty.contains(r);
+ return component.isCompletelyDirty;
}
/**
@@ -408,58 +522,56 @@ public class RepaintManager
*/
public void validateInvalidComponents()
{
- for (Enumeration e = invalidComponents.elements(); e.hasMoreElements(); )
+ // In order to keep the blocking of application threads minimal, we switch
+ // the invalidComponents field with the workInvalidComponents field and
+ // work with the workInvalidComponents field.
+ synchronized(this)
+ {
+ ArrayList swap = invalidComponents;
+ invalidComponents = workInvalidComponents;
+ workInvalidComponents = swap;
+ }
+ for (Iterator i = workInvalidComponents.iterator(); i.hasNext(); )
{
- JComponent comp = (JComponent) e.nextElement();
+ JComponent comp = (JComponent) i.next();
if (! (comp.isVisible() && comp.isShowing()))
continue;
comp.validate();
}
- invalidComponents.clear();
+ workInvalidComponents.clear();
}
/**
* Repaint all regions of all components which have been marked dirty in
* the {@link #dirtyComponents} table.
*/
- public void paintDirtyRegions()
+ public synchronized void paintDirtyRegions()
{
- // step 1: pull out roots and calculate spanning damage
-
- HashMap roots = new HashMap();
- for (Enumeration e = dirtyComponents.keys(); e.hasMoreElements(); )
+ // In order to keep the blocking of application threads minimal, we switch
+ // the dirtyComponents field with the workdirtyComponents field and the
+ // repaintOrder field with the workRepaintOrder field and work with the
+ // work* fields.
+ synchronized(this)
+ {
+ ArrayList swap = workRepaintOrder;
+ workRepaintOrder = repaintOrder;
+ repaintOrder = swap;
+ HashMap swap2 = workDirtyComponents;
+ workDirtyComponents = dirtyComponents;
+ dirtyComponents = swap2;
+ }
+ for (Iterator i = workRepaintOrder.iterator(); i.hasNext();)
{
- JComponent comp = (JComponent) e.nextElement();
- if (! (comp.isVisible() && comp.isShowing()))
- continue;
- Rectangle damaged = getDirtyRegion(comp);
- if (damaged.width == 0 || damaged.height == 0)
+ JComponent comp = (JComponent) i.next();
+ // If a component is marked completely clean in the meantime, then skip
+ // it.
+ Rectangle damaged = (Rectangle) workDirtyComponents.get(comp);
+ if (damaged == null || damaged.isEmpty())
continue;
- JRootPane root = comp.getRootPane();
- // If the component has no root, no repainting will occur.
- if (root == null)
- continue;
- 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.entrySet().iterator();
- while(i.hasNext())
- {
- Map.Entry ent = (Map.Entry) i.next();
- JRootPane root = (JRootPane) ent.getKey();
- Rectangle rect = (Rectangle) ent.getValue();
- root.paintImmediately(rect);
+ comp.paintImmediately(damaged);
}
+ workRepaintOrder.clear();
+ workDirtyComponents.clear();
}
/**
diff --git a/libjava/classpath/javax/swing/RootPaneContainer.java b/libjava/classpath/javax/swing/RootPaneContainer.java
index b121f958a92..4b1bece214d 100644
--- a/libjava/classpath/javax/swing/RootPaneContainer.java
+++ b/libjava/classpath/javax/swing/RootPaneContainer.java
@@ -48,53 +48,49 @@ import java.awt.Container;
*
* @author Andrew Selkirk
*/
-public interface RootPaneContainer {
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * getRootPane
- * @returns JRootPane
- */
- JRootPane getRootPane();
-
- /**
- * setContentPane
- * @param contentPane TODO
- */
- void setContentPane(Container contentPane);
-
- /**
- * getContentPane
- * @returns Container
- */
- Container getContentPane();
-
- /**
- * setLayeredPane
- * @param layeredPane TODO
- */
- void setLayeredPane(JLayeredPane layeredPane);
-
- /**
- * getLayeredPane
- * @returns JLayeredPane
- */
- JLayeredPane getLayeredPane();
-
- /**
- * setGlassPane
- * @param glassPane TODO
- */
- void setGlassPane(Component glassPane);
-
- /**
- * getGlassPane
- * @returns Component
- */
- Component getGlassPane();
-
-
-} // RootPaneContainer
+public interface RootPaneContainer
+{
+
+ /**
+ * getRootPane
+ * @returns JRootPane
+ */
+ JRootPane getRootPane();
+
+ /**
+ * setContentPane
+ * @param contentPane TODO
+ */
+ void setContentPane(Container contentPane);
+
+ /**
+ * getContentPane
+ * @returns Container
+ */
+ Container getContentPane();
+
+ /**
+ * setLayeredPane
+ * @param layeredPane TODO
+ */
+ void setLayeredPane(JLayeredPane layeredPane);
+
+ /**
+ * getLayeredPane
+ * @returns JLayeredPane
+ */
+ JLayeredPane getLayeredPane();
+
+ /**
+ * setGlassPane
+ * @param glassPane TODO
+ */
+ void setGlassPane(Component glassPane);
+
+ /**
+ * getGlassPane
+ * @returns Component
+ */
+ Component getGlassPane();
+
+}
diff --git a/libjava/classpath/javax/swing/ScrollPaneLayout.java b/libjava/classpath/javax/swing/ScrollPaneLayout.java
index 75a6f9aa208..edf1f1f4292 100644
--- a/libjava/classpath/javax/swing/ScrollPaneLayout.java
+++ b/libjava/classpath/javax/swing/ScrollPaneLayout.java
@@ -43,12 +43,9 @@ import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
-import java.awt.Point;
import java.awt.Rectangle;
import java.io.Serializable;
-import javax.swing.border.Border;
-
/**
* ScrollPaneLayout
* @author Andrew Selkirk
@@ -60,8 +57,11 @@ public class ScrollPaneLayout
private static final long serialVersionUID = -4480022884523193743L;
public static class UIResource extends ScrollPaneLayout
- implements javax.swing.plaf.UIResource {
- public UIResource() {
+ implements javax.swing.plaf.UIResource
+ {
+ public UIResource()
+ {
+ super();
}
}
@@ -77,8 +77,9 @@ public class ScrollPaneLayout
protected int vsbPolicy;
protected int hsbPolicy;
- public ScrollPaneLayout() {
-
+ public ScrollPaneLayout()
+ {
+ // Nothing to do here.
}
public void syncWithScrollPane(JScrollPane scrollPane) {
@@ -95,11 +96,31 @@ public class ScrollPaneLayout
upperRight = scrollPane.getCorner(UPPER_RIGHT_CORNER);
}
+ /**
+ * Removes an existing component. If oldComponent is not null
+ * and is not equal to newComponent, oldComponent must be removed
+ * from its parent.
+ * @param oldComponent the old Component that may need to be removed.
+ * @param newComponent the Component to add.
+ * @return the newComponent
+ */
protected Component addSingletonComponent(Component oldComponent,
- Component newComponent) {
- return null;
+ Component newComponent)
+ {
+ if (oldComponent != null && oldComponent != newComponent)
+ oldComponent.getParent().remove(oldComponent);
+ return newComponent;
}
+ /**
+ * Add the specified component to the layout.
+ * @param key must be one of VIEWPORT, VERTICAL_SCROLLBAR,
+ * HORIZONTAL_SCROLLBAR, ROW_HEADER, COLUMN_HEADER,
+ * LOWER_RIGHT_CORNER, LOWER_LEFT_CORNER, UPPER_RIGHT_CORNER,
+ * UPPER_LEFT_CORNER.
+ * @param component the Component to add
+ * @throws IllegalArgumentException if key is not as above
+ */
public void addLayoutComponent(String key, Component component)
{
if (key == VIEWPORT)
@@ -120,6 +141,8 @@ public class ScrollPaneLayout
lowerLeft = component;
else if (key == UPPER_LEFT_CORNER)
upperLeft = component;
+ else
+ throw new IllegalArgumentException();
}
public void removeLayoutComponent(Component component) {
@@ -147,9 +170,20 @@ public class ScrollPaneLayout
{
return vsbPolicy;
}
-
+
+ /**
+ * Sets the vertical scrollbar policy.
+ * @param policy must be one of VERTICAL_SCROLLBAR_AS_NEEDED,
+ * VERTICAL_SCROLLBAR_NEVER, VERTICAL_SCROLLBAR_ALWAYS.
+ * @throws IllegalArgumentException if policy is not one of the valid
+ * JScrollBar policies.
+ */
public void setVerticalScrollBarPolicy(int policy)
{
+ if (policy != VERTICAL_SCROLLBAR_AS_NEEDED &&
+ policy != VERTICAL_SCROLLBAR_NEVER &&
+ policy != VERTICAL_SCROLLBAR_ALWAYS)
+ throw new IllegalArgumentException("Illegal Scrollbar Policy");
vsbPolicy = policy;
}
@@ -158,8 +192,19 @@ public class ScrollPaneLayout
return hsbPolicy;
}
+ /**
+ * Sets the horizontal scrollbar policy.
+ * @param policy must be one of HORIZONTAL_SCROLLBAR_AS_NEEDED,
+ * HORIZONTAL_SCROLLBAR_NEVER, HORIZONTAL_SCROLLBAR_ALWAYS.
+ * @throws IllegalArgumentException if policy is not one of the valid
+ * JScrollbar policies.
+ */
public void setHorizontalScrollBarPolicy(int policy)
{
+ if (policy != HORIZONTAL_SCROLLBAR_AS_NEEDED &&
+ policy != HORIZONTAL_SCROLLBAR_NEVER &&
+ policy != HORIZONTAL_SCROLLBAR_ALWAYS)
+ throw new IllegalArgumentException("Illegal Scrollbar Policy");
hsbPolicy = policy;
}
@@ -188,6 +233,12 @@ public class ScrollPaneLayout
return colHead;
}
+ /**
+ * Returns the Component at the specified corner.
+ * @param key the corner.
+ * @return the Component at the specified corner, or null if
+ * key is not one of the four valid corners.
+ */
public Component getCorner(String key)
{
if (key == LOWER_RIGHT_CORNER)
@@ -201,151 +252,53 @@ public class ScrollPaneLayout
return null;
}
- private static void maybeSetPreferredSize(JComponent src, Dimension dim)
- {
- Dimension tmp = null;
- if (src != null)
- tmp = src.getPreferredSize();
- if (tmp != null)
- dim.setSize(tmp);
- }
-
- private static void maybeSetMinimumSize(JComponent src, Dimension dim)
- {
- Dimension tmp = null;
- if (src != null)
- tmp = src.getMinimumSize();
- if (tmp != null)
- dim.setSize(tmp);
- }
-
public Dimension preferredLayoutSize(Container parent)
{
- if (parent != null && parent instanceof JScrollPane)
- {
- JScrollPane sc = (JScrollPane) parent;
- synchronized (sc.getTreeLock ())
- {
- Dimension insetsSize = new Dimension(0,0);
- Dimension viewportSize = new Dimension(0,0);
- Dimension viewportInsetsSize = new Dimension(0,0);
- Dimension columnHeaderSize = new Dimension(0,0);
- Dimension rowHeaderSize = new Dimension(0,0);
- Dimension verticalScrollBarSize = new Dimension(0,0);
- Dimension horizontalScrollBarSize = new Dimension(0,0);
-
- Insets insets = sc.getInsets();
- Border viewportBorder = sc.getViewportBorder();
- Insets viewportInsets = null;
-
- if (viewportBorder != null)
- {
- viewportInsets = viewportBorder.getBorderInsets(parent);
- if (viewportInsets != null)
- viewportInsetsSize.setSize(viewportInsets.left + viewportInsets.right,
- viewportInsets.top + viewportInsets.bottom);
- }
-
- if (insets != null)
- insetsSize.setSize(insets.left + insets.right,
- insets.top + insets.bottom);
-
- if (viewport != null)
- {
- Component view = null;
- Scrollable scr = null;
- Dimension pref = null;
-
- view = viewport.getView();
- if (view != null && view instanceof Scrollable)
- scr = (Scrollable) view;
- if (scr != null)
- pref = scr.getPreferredScrollableViewportSize();
- if (pref == null)
- pref = viewport.getPreferredSize();
- if (pref != null)
- viewportSize.setSize(pref);
- }
-
- maybeSetPreferredSize(colHead, columnHeaderSize);
- maybeSetPreferredSize(rowHead, rowHeaderSize);
- maybeSetPreferredSize(vsb, verticalScrollBarSize);
- maybeSetPreferredSize(hsb, horizontalScrollBarSize);
-
- return new Dimension(insetsSize.width
- + viewportSize.width
- + viewportInsetsSize.width
- + rowHeaderSize.width
- + verticalScrollBarSize.width,
- insetsSize.height
- + viewportSize.height
- + viewportInsetsSize.height
- + columnHeaderSize.height
- + horizontalScrollBarSize.height);
- }
- }
- else
- {
- return new Dimension(0,0);
- }
+ // Sun's implementation simply throws a ClassCastException if
+ // parent is no JScrollPane, so do we.
+ JScrollPane sc = (JScrollPane) parent;
+ Dimension viewportSize = viewport.getPreferredSize();
+ Dimension viewSize = viewport.getViewSize();
+ int width = viewportSize.width;
+ int height = viewportSize.height;
+
+ // horizontal scrollbar needed if the view's preferred width
+ // is larger than the viewport's preferred width
+ if (hsb != null && viewSize.width > viewportSize.width)
+ height += hsb.getPreferredSize().height;
+
+ // vertical scrollbar needed if the view's preferred height
+ // is larger than the viewport's preferred height
+ if (vsb != null && viewSize.height > viewportSize.height)
+ width += vsb.getPreferredSize().width;
+ if (rowHead != null && rowHead.isVisible())
+ width += rowHead.getPreferredSize().width;
+ if (colHead != null && colHead.isVisible())
+ height += colHead.getPreferredSize().height;
+ Insets i = sc.getInsets();
+ return new Dimension(width + i.left + i.right,
+ height + i.left + i.right);
}
public Dimension minimumLayoutSize(Container parent)
{
- if (parent instanceof JScrollPane)
- {
- JScrollPane sc = (JScrollPane) parent;
- synchronized (sc.getTreeLock ())
- {
- Dimension insetsSize = new Dimension(0,0);
- Dimension viewportSize = new Dimension(0,0);
- Dimension viewportInsetsSize = new Dimension(0,0);
- Dimension columnHeaderSize = new Dimension(0,0);
- Dimension rowHeaderSize = new Dimension(0,0);
- Dimension verticalScrollBarSize = new Dimension(0,0);
- Dimension horizontalScrollBarSize = new Dimension(0,0);
-
- Insets insets = sc.getInsets();
- Border viewportBorder = sc.getViewportBorder();
- Insets viewportInsets = null;
-
- if (viewportBorder != null)
- {
- viewportInsets = viewportBorder.getBorderInsets(parent);
- if (viewportInsets != null)
- viewportInsetsSize.setSize(viewportInsets.left + viewportInsets.right,
- viewportInsets.top + viewportInsets.bottom);
- }
-
- if (insets != null)
- insetsSize.setSize(insets.left + insets.right,
- insets.top + insets.bottom);
-
- maybeSetMinimumSize(colHead, columnHeaderSize);
- maybeSetMinimumSize(rowHead, rowHeaderSize);
-
- if (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)
- maybeSetMinimumSize(vsb, verticalScrollBarSize);
-
- if (hsbPolicy != HORIZONTAL_SCROLLBAR_NEVER)
- maybeSetMinimumSize(hsb, horizontalScrollBarSize);
-
- return new Dimension(insetsSize.width
- + viewportSize.width
- + viewportInsetsSize.width
- + rowHeaderSize.width
- + verticalScrollBarSize.width,
- insetsSize.height
- + viewportSize.height
- + viewportInsetsSize.height
- + columnHeaderSize.height
- + horizontalScrollBarSize.height);
- }
- }
- else
- {
- return new Dimension(0,0);
- }
+ // Sun's implementation simply throws a ClassCastException if
+ // parent is no JScrollPane, so do we.
+ JScrollPane sc = (JScrollPane) parent;
+ Dimension viewportSize = viewport.getMinimumSize();
+ int width = viewportSize.width;
+ int height = viewportSize.height;
+ if (hsb != null && hsb.isVisible())
+ height += hsb.getMinimumSize().height;
+ if (vsb != null && vsb.isVisible())
+ width += vsb.getMinimumSize().width;
+ if (rowHead != null && rowHead.isVisible())
+ width += rowHead.getMinimumSize().width;
+ if (colHead != null && colHead.isVisible())
+ height += colHead.getMinimumSize().height;
+ Insets i = sc.getInsets();
+ return new Dimension(width + i.left + i.right,
+ height + i.top + i.bottom);
}
/**
@@ -371,100 +324,91 @@ public class ScrollPaneLayout
*/
public void layoutContainer(Container parent)
{
- if (parent instanceof JScrollPane)
+ // Sun's implementation simply throws a ClassCastException if
+ // parent is no JScrollPane, so do we.
+ JScrollPane sc = (JScrollPane) parent;
+ JViewport viewport = sc.getViewport();
+ Dimension viewSize = viewport.getViewSize();
+
+ int x1 = 0, x2 = 0, x3 = 0, x4 = 0;
+ int y1 = 0, y2 = 0, y3 = 0, y4 = 0;
+ Rectangle scrollPaneBounds = SwingUtilities.calculateInnerArea(sc, null);
+
+ x1 = scrollPaneBounds.x;
+ y1 = scrollPaneBounds.y;
+ x4 = scrollPaneBounds.x + scrollPaneBounds.width;
+ y4 = scrollPaneBounds.y + scrollPaneBounds.height;
+ if (colHead != null)
+ y2 = y1 + colHead.getPreferredSize().height;
+ else
+ y2 = y1;
+
+ if (rowHead != null)
+ x2 = x1 + rowHead.getPreferredSize().width;
+ else
+ x2 = x1;
+
+ int vsbPolicy = sc.getVerticalScrollBarPolicy();
+ int hsbPolicy = sc.getHorizontalScrollBarPolicy();
+
+ boolean showVsb =
+ (vsb != null)
+ && ((vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS)
+ || (vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED
+ && viewSize.height > (y4 - y2)));
+ boolean showHsb =
+ (hsb != null)
+ && ((hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS)
+ || (hsbPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED
+ && viewSize.width > (x4 - x2)));
+
+ if (!showVsb)
+ x3 = x4;
+ else
+ x3 = x4 - vsb.getPreferredSize().width;
+
+ if (!showHsb)
+ y3 = y4;
+ else
+ y3 = y4 - hsb.getPreferredSize().height;
+
+ // now set the layout
+ if (viewport != null)
+ viewport.setBounds(new Rectangle(x2, y2, x3 - x2, y3 - y2));
+
+ if (colHead != null)
+ colHead.setBounds(new Rectangle(x2, y1, x3 - x2, y2 - y1));
+
+ if (rowHead != null)
+ rowHead.setBounds(new Rectangle(x1, y2, x2 - x1, y3 - y2));
+
+ if (showVsb)
+ {
+ vsb.setVisible(true);
+ vsb.setBounds(new Rectangle(x3, y2, x4 - x3, y3 - y2));
+ }
+ else if (vsb != null)
+ vsb.setVisible(false);
+
+ if (showHsb)
{
- JScrollPane sc = (JScrollPane) parent;
- synchronized (sc.getTreeLock ())
- {
- JViewport viewport = sc.getViewport();
- Dimension viewSize = viewport.getViewSize();
- Point viewPos = viewport.getViewPosition();
-
- int x1 = 0, x2 = 0, x3 = 0, x4 = 0;
- int y1 = 0, y2 = 0, y3 = 0, y4 = 0;
-
- Rectangle scrollPaneBounds = SwingUtilities.calculateInnerArea(sc, null);
-
- x1 = scrollPaneBounds.x;
- y1 = scrollPaneBounds.y;
- x4 = scrollPaneBounds.x + scrollPaneBounds.width;
- y4 = scrollPaneBounds.y + scrollPaneBounds.height;
-
- if (colHead != null)
- y2 = y1 + colHead.getPreferredSize().height;
- else
- y2 = y1;
-
- if (rowHead != null)
- x2 = x1 + rowHead.getPreferredSize().width;
- else
- x2 = x1;
-
- int vsbPolicy = sc.getVerticalScrollBarPolicy();
- int hsbPolicy = sc.getHorizontalScrollBarPolicy();
-
- x3 = x4 - vsb.getPreferredSize().width;
- y3 = y4 - hsb.getPreferredSize().height;
-
- boolean showVsb =
- (vsb != null)
- && ((vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS)
- || (vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED
- && viewSize.height > (y3 - y2)));
-
- boolean showHsb =
- (hsb != null)
- && ((hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS)
- || (hsbPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED
- && viewSize.width > (x3 - x2)));
-
- if (!showVsb)
- x3 = x4;
-
- if (!showHsb)
- y3 = y4;
-
- // now set the layout
-
- if (viewport != null)
- viewport.setBounds(new Rectangle(x2, y2, x3-x2, y3-y2));
-
- if (colHead != null)
- colHead.setBounds(new Rectangle(x2, y1, x3-x2, y2-y1));
-
- if (rowHead != null)
- rowHead.setBounds(new Rectangle(x1, y2, x2-x1, y3-y2));
-
- if (showVsb)
- {
- vsb.setVisible(true);
- vsb.setBounds(new Rectangle(x3, y2, x4-x3, y3-y2));
- }
- else if (vsb != null)
- vsb.setVisible(false);
-
- if (showHsb)
- {
- hsb.setVisible(true);
- hsb.setBounds(new Rectangle(x2, y3, x3-x2, y4-y3));
- }
- else if (hsb != null)
- hsb.setVisible(false);
-
- if (upperLeft != null)
- upperLeft.setBounds(new Rectangle(x1, y1, x2-x1, y2-y1));
-
- if (upperRight != null)
- upperRight.setBounds(new Rectangle(x3, y1, x4-x3, y2-y1));
-
- if (lowerLeft != null)
- lowerLeft.setBounds(new Rectangle(x1, y3, x2-x1, y4-y3));
-
- if (lowerRight != null)
- lowerRight.setBounds(new Rectangle(x3, y3, x4-x3, y4-y3));
-
- }
+ hsb.setVisible(true);
+ hsb.setBounds(new Rectangle(x2, y3, x3 - x2, y4 - y3));
}
+ else if (hsb != null)
+ hsb.setVisible(false);
+
+ if (upperLeft != null)
+ upperLeft.setBounds(new Rectangle(x1, y1, x2 - x1, y2 - y1));
+
+ if (upperRight != null)
+ upperRight.setBounds(new Rectangle(x3, y1, x4 - x3, y2 - y1));
+
+ if (lowerLeft != null)
+ lowerLeft.setBounds(new Rectangle(x1, y3, x2 - x1, y4 - y3));
+
+ if (lowerRight != null)
+ lowerRight.setBounds(new Rectangle(x3, y3, x4 - x3, y4 - y3));
}
/**
diff --git a/libjava/classpath/javax/swing/Scrollable.java b/libjava/classpath/javax/swing/Scrollable.java
index 19732192330..9dce665d626 100644
--- a/libjava/classpath/javax/swing/Scrollable.java
+++ b/libjava/classpath/javax/swing/Scrollable.java
@@ -48,9 +48,16 @@ import java.awt.Rectangle;
*/
public interface Scrollable
{
- Dimension getPreferredScrollableViewportSize();
- int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction);
- int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction);
- boolean getScrollableTracksViewportWidth();
- boolean getScrollableTracksViewportHeight();
+ Dimension getPreferredScrollableViewportSize();
+
+ int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
+ int direction);
+
+ int getScrollableBlockIncrement(Rectangle visibleRect, int orientation,
+ int direction);
+
+ boolean getScrollableTracksViewportWidth();
+
+ boolean getScrollableTracksViewportHeight();
+
}
diff --git a/libjava/classpath/javax/swing/SingleSelectionModel.java b/libjava/classpath/javax/swing/SingleSelectionModel.java
index b5380c857a3..d57443b56bb 100644
--- a/libjava/classpath/javax/swing/SingleSelectionModel.java
+++ b/libjava/classpath/javax/swing/SingleSelectionModel.java
@@ -46,46 +46,41 @@ import javax.swing.event.ChangeListener;
*
* @author Andrew Selkirk
*/
-public interface SingleSelectionModel {
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * getSelectedIndex
- * @returns int
- */
- int getSelectedIndex();
-
- /**
- * setSelectedIndex
- * @param index TODO
- */
- void setSelectedIndex(int index);
-
- /**
- * clearSelection
- */
- void clearSelection();
-
- /**
- * isSelected
- * @returns boolean
- */
- boolean isSelected();
-
- /**
- * addChangeListener
- * @param listener TODO
- */
- void addChangeListener(ChangeListener listener);
-
- /**
- * removeChangeListener
- * @param listener TODO
- */
- void removeChangeListener(ChangeListener listener);
-
-
-} // SingleSelectionModel
+public interface SingleSelectionModel
+{
+ /**
+ * getSelectedIndex
+ * @returns int
+ */
+ int getSelectedIndex();
+
+ /**
+ * setSelectedIndex
+ * @param index TODO
+ */
+ void setSelectedIndex(int index);
+
+ /**
+ * clearSelection
+ */
+ void clearSelection();
+
+ /**
+ * isSelected
+ * @returns boolean
+ */
+ boolean isSelected();
+
+ /**
+ * addChangeListener
+ * @param listener TODO
+ */
+ void addChangeListener(ChangeListener listener);
+
+ /**
+ * removeChangeListener
+ * @param listener TODO
+ */
+ void removeChangeListener(ChangeListener listener);
+
+}
diff --git a/libjava/classpath/javax/swing/SizeRequirements.java b/libjava/classpath/javax/swing/SizeRequirements.java
index 77b42db1ce9..b9b5c322379 100644
--- a/libjava/classpath/javax/swing/SizeRequirements.java
+++ b/libjava/classpath/javax/swing/SizeRequirements.java
@@ -116,7 +116,17 @@ public class SizeRequirements implements Serializable
*/
public String toString()
{
- return null; // TODO
+ StringBuilder b = new StringBuilder();
+ b.append("<[");
+ b.append(minimum);
+ b.append(',');
+ b.append(preferred);
+ b.append(',');
+ b.append(maximum);
+ b.append("]@");
+ b.append(alignment);
+ b.append('>');
+ return b.toString();
}
/**
@@ -132,13 +142,26 @@ public class SizeRequirements implements Serializable
public static SizeRequirements
getTiledSizeRequirements(SizeRequirements[] children)
{
- SizeRequirements result = new SizeRequirements();
+ long minimum = 0;
+ long preferred = 0;
+ long maximum = 0;
for (int i = 0; i < children.length; i++)
{
- result.minimum += children[i].minimum;
- result.preferred += children[i].preferred;
- result.maximum += children[i].maximum;
+ minimum += children[i].minimum;
+ preferred += children[i].preferred;
+ maximum += children[i].maximum;
}
+ // Overflow check.
+ if (minimum > Integer.MAX_VALUE)
+ minimum = Integer.MAX_VALUE;
+ if (preferred > Integer.MAX_VALUE)
+ preferred = Integer.MAX_VALUE;
+ if (maximum > Integer.MAX_VALUE)
+ maximum = Integer.MAX_VALUE;
+ SizeRequirements result = new SizeRequirements((int) minimum,
+ (int) preferred,
+ (int) maximum,
+ 0.5F);
return result;
}
@@ -156,7 +179,34 @@ public class SizeRequirements implements Serializable
public static SizeRequirements
getAlignedSizeRequirements(SizeRequirements[] children)
{
- return null; // TODO
+ float minLeft = 0;
+ float minRight = 0;
+ float prefLeft = 0;
+ float prefRight = 0;
+ float maxLeft = 0;
+ float maxRight = 0;
+ for (int i = 0; i < children.length; i++)
+ {
+ float myMinLeft = children[i].minimum * children[i].alignment;
+ float myMinRight = children[i].minimum - myMinLeft;
+ minLeft = Math.max(myMinLeft, minLeft);
+ minRight = Math.max(myMinRight, minRight);
+ float myPrefLeft = children[i].preferred * children[i].alignment;
+ float myPrefRight = children[i].preferred - myPrefLeft;
+ prefLeft = Math.max(myPrefLeft, prefLeft);
+ prefRight = Math.max(myPrefRight, prefRight);
+ float myMaxLeft = children[i].maximum * children[i].alignment;
+ float myMaxRight = children[i].maximum - myMaxLeft;
+ maxLeft = Math.max(myMaxLeft, maxLeft);
+ maxRight = Math.max(myMaxRight, maxRight);
+ }
+ int minSize = (int) (minLeft + minRight);
+ int prefSize = (int) (prefLeft + prefRight);
+ int maxSize = (int) (maxLeft + maxRight);
+ float align = prefLeft / (prefRight + prefLeft);
+ if (Float.isNaN(align))
+ align = 0;
+ return new SizeRequirements(minSize, prefSize, maxSize, align);
}
/**
@@ -222,6 +272,7 @@ public class SizeRequirements implements Serializable
int[] offsets, int[] spans,
boolean forward)
{
+ int span = 0;
if (forward)
{
int offset = 0;
@@ -229,6 +280,7 @@ public class SizeRequirements implements Serializable
{
offsets[i] = offset;
spans[i] = children[i].preferred;
+ span += spans[i];
offset += children[i].preferred;
}
}
@@ -239,9 +291,84 @@ public class SizeRequirements implements Serializable
{
offset -= children[i].preferred;
offsets[i] = offset;
+ span += spans[i];
spans[i] = children[i].preferred;
}
}
+ // Adjust spans so that we exactly fill the allocated region. If
+ if (span > allocated)
+ adjustSmaller(allocated, children, spans, span);
+ else if (span < allocated)
+ adjustGreater(allocated, children, spans, span);
+
+ // Adjust offsets.
+ if (forward)
+ {
+ int offset = 0;
+ for (int i = 0; i < children.length; i++)
+ {
+ offsets[i] = offset;
+ offset += spans[i];
+ }
+ }
+ else
+ {
+ int offset = allocated;
+ for (int i = 0; i < children.length; i++)
+ {
+ offset -= spans[i];
+ offsets[i] = offset;
+ }
+ }
+ }
+
+ private static void adjustSmaller(int allocated, SizeRequirements[] children,
+ int[] spans, int span)
+ {
+ // Sum up (prefSize - minSize) over all children
+ int sumDelta = 0;
+ for (int i = 0; i < children.length; i++)
+ sumDelta += children[i].preferred - children[i].minimum;
+
+ // If we have sumDelta == 0, then all components have prefSize == maxSize
+ // and we can't do anything about it.
+ if (sumDelta == 0)
+ return;
+
+ // Adjust all sizes according to their preferred and minimum sizes.
+ for (int i = 0; i < children.length; i++)
+ {
+ double factor = ((double) (children[i].preferred - children[i].minimum))
+ / ((double) sumDelta);
+ // In case we have a sumDelta of 0, the factor should also be 0.
+ if (Double.isNaN(factor))
+ factor = 0;
+ spans[i] -= factor * (span - allocated);
+ }
+ }
+
+ private static void adjustGreater(int allocated, SizeRequirements[] children,
+ int[] spans, int span)
+ {
+ // Sum up (maxSize - prefSize) over all children
+ long sumDelta = 0;
+ for (int i = 0; i < children.length; i++)
+ {
+ sumDelta += children[i].maximum - children[i].preferred;
+ }
+
+ // If we have sumDelta == 0, then all components have prefSize == maxSize
+ // and we can't do anything about it.
+ if (sumDelta == 0)
+ return;
+
+ // Adjust all sizes according to their preferred and minimum sizes.
+ for (int i = 0; i < children.length; i++)
+ {
+ double factor = ((double) (children[i].maximum - children[i].preferred))
+ / ((double) sumDelta);
+ spans[i] += factor * (allocated - span);
+ }
}
/**
@@ -271,7 +398,8 @@ public class SizeRequirements implements Serializable
SizeRequirements[] children,
int[] offsets, int[] spans)
{
- calculateTiledPositions(allocated, total, children, offsets, spans, true);
+ calculateAlignedPositions(allocated, total, children, offsets, spans,
+ true);
}
/**
@@ -306,7 +434,74 @@ public class SizeRequirements implements Serializable
int[] offset, int[] spans,
boolean forward)
{
- // TODO
+ // First we compute the position of the baseline.
+ float baseline = allocated * total.alignment;
+
+ // Now we can layout the components along the baseline.
+ for (int i = 0; i < children.length; i++)
+ {
+ float align = children[i].alignment;
+ // Try to fit the component into the available space.
+ int[] spanAndOffset = new int[2];
+ if (align < .5F || baseline == 0)
+ adjustFromRight(children[i], baseline, allocated, spanAndOffset);
+ else
+ adjustFromLeft(children[i], baseline, allocated, spanAndOffset);
+ spans[i] = spanAndOffset[0];
+ offset[i] = spanAndOffset[1];
+ }
+ }
+
+ /**
+ * Adjusts the span and offset of a component for the aligned layout.
+ *
+ * @param reqs
+ * @param baseline
+ * @param allocated
+ * @param spanAndOffset
+ */
+ private static void adjustFromRight(SizeRequirements reqs, float baseline,
+ int allocated, int[] spanAndOffset)
+ {
+ float right = allocated - baseline;
+ // If the resulting span exceeds the maximum of the component, then adjust
+ // accordingly.
+ float maxRight = ((float) reqs.maximum) * (1.F - reqs.alignment);
+ if (right / (1.F - reqs.alignment) > reqs.maximum)
+ right = maxRight;
+ // If we have not enough space on the left side, then adjust accordingly.
+ if (right / (1.F - reqs.alignment) * reqs.alignment > allocated - baseline)
+ right = ((float) (allocated - baseline))
+ / reqs.alignment * (1.F - reqs.alignment);
+
+ spanAndOffset[0] = (int) (right / (1.F - reqs.alignment));
+ spanAndOffset[1] = (int) (baseline - spanAndOffset[0] * reqs.alignment);
+ }
+
+ /**
+ * Adjusts the span and offset of a component for the aligned layout.
+ *
+ * @param reqs
+ * @param baseline
+ * @param allocated
+ * @param spanAndOffset
+ */
+ private static void adjustFromLeft(SizeRequirements reqs, float baseline,
+ int allocated, int[] spanAndOffset)
+ {
+ float left = baseline;
+ // If the resulting span exceeds the maximum of the component, then adjust
+ // accordingly.
+ float maxLeft = ((float) reqs.maximum) * reqs.alignment;
+ if (left / reqs.alignment > reqs.maximum)
+ left = maxLeft;
+ // If we have not enough space on the right side, then adjust accordingly.
+ if (left / reqs.alignment * (1.F - reqs.alignment) > allocated - baseline)
+ left = ((float) (allocated - baseline))
+ / (1.F - reqs.alignment) * reqs.alignment;
+
+ spanAndOffset[0] = (int) (left / reqs.alignment);
+ spanAndOffset[1] = (int) (baseline - spanAndOffset[0] * reqs.alignment);
}
/**
diff --git a/libjava/classpath/javax/swing/SizeSequence.java b/libjava/classpath/javax/swing/SizeSequence.java
index cf6e5f042a1..dff966b3e35 100644
--- a/libjava/classpath/javax/swing/SizeSequence.java
+++ b/libjava/classpath/javax/swing/SizeSequence.java
@@ -42,208 +42,197 @@ package javax.swing;
* @author Andrew Selkirk
* @version 1.0
*/
-public class SizeSequence {
-
- //-------------------------------------------------------------
- // Variables --------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * sizes
- */
- private int[] sizes = new int[0];
-
-
- //-------------------------------------------------------------
- // Initialization ---------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * Constructor SizeSequence
- */
- public SizeSequence() {
- sizes = new int[0];
- } // SizeSequence()
-
- /**
- * Constructor SizeSequence
- * @param numEntries TODO
- */
- public SizeSequence(int numEntries) {
- this(numEntries, 0);
- } // SizeSequence()
-
- /**
- * Constructor SizeSequence
- * @param numEntries TODO
- * @param value TODO
- */
- public SizeSequence(int numEntries, int value) {
- insertEntries(0, numEntries, value);
- } // SizeSequence()
-
- /**
- * Constructor SizeSequence
- * @param sizes TODO
- */
- public SizeSequence(int[] sizes) {
- setSizes(sizes);
- } // SizeSequence()
-
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * setSize
- * @param index TODO
- * @param size TODO
- */
- public void setSize(int index, int size) {
- sizes[index] = size;
- } // setSize()
-
- /**
- * getIndex
- * @param position TODO
- * @returns int
- */
- public int getIndex(int position) {
- return 0; // TODO
- } // getIndex()
-
- /**
- * getSize
- * @param index TODO
- * @returns int
- */
- public int getSize(int index) {
- return sizes[index];
- } // getSize()
-
- /**
- * setSizes
- * @param sizes TODO
- */
- public void setSizes(int[] sizes) {
-
- // Variables
- int index;
-
- // Initialize Sizes
- this.sizes = new int[sizes.length];
- for (index = 0; index < sizes.length; index++) {
- this.sizes[index] = sizes[index];
- } // for
-
- } // setSizes()
-
- /**
- * getSizes
- * @returns int[]
- */
- public int[] getSizes() {
-
- // Variables
- int[] array;
- int index;
-
- // Create New Array
- array = new int[sizes.length];
- for (index = 0; index < sizes.length; index++) {
- array[index] = sizes[index];
- } // for
-
- // Return Newly created array
- return array;
-
- } // getSizes()
-
- /**
- * getPosition
- * @param index TODO
- * @returns int
- */
- public int getPosition(int index) {
-
- // Variables
- int position;
- int loop;
-
- // Process Sizes
- position = 0;
- for (loop = 0; loop < index; loop++) {
- position += sizes[loop];
- } // for
-
- // Return Position
- return position;
-
- } // getPosition()
-
- /**
- * insertEntries
- * @param start TODO
- * @param length TODO
- * @param value TODO
- */
- public void insertEntries(int start, int length, int value) {
-
- // Variables
- int[] array;
- int index;
- int arrayIndex;
- int loop;
-
- // Create New Array
- array = new int[sizes.length + length];
- arrayIndex = 0;
- for (index = 0; index < sizes.length; index++) {
- if (index == start) {
- for (loop = 0; loop < length; loop++) {
- array[arrayIndex] = value;
- arrayIndex++;
- } // for
- } else {
- array[arrayIndex] = sizes[index];
- arrayIndex++;
- } // if
- } // for
-
- } // insertEntries()
-
- /**
- * removeEntries
- * @param start TODO
- * @param length TODO
- */
- public void removeEntries(int start, int length) {
-
- // Variables
- int[] array;
- int index;
- int arrayIndex;
-
- // Sanity Check
- if ((start + length) > sizes.length) {
- throw new IllegalArgumentException("Specified start/length that " +
- "is greater than available sizes");
- } // if
-
- // Create New Array
- array = new int[sizes.length - length];
- arrayIndex = 0;
- for (index = 0; index < sizes.length; index++) {
- if (index == start) {
- index += length - 1;
- } else {
- array[arrayIndex] = sizes[index];
- arrayIndex++;
- } // if
- } // for
-
- } // removeEntries()
-
-
-} // SizeSequence
+public class SizeSequence
+{
+
+ /**
+ * sizes
+ */
+ private int[] sizes = new int[0];
+
+ /**
+ * Constructor SizeSequence
+ */
+ public SizeSequence()
+ {
+ sizes = new int[0];
+ }
+
+ /**
+ * Constructor SizeSequence
+ * @param numEntries TODO
+ */
+ public SizeSequence(int numEntries)
+ {
+ this(numEntries, 0);
+ }
+
+ /**
+ * Constructor SizeSequence
+ * @param numEntries TODO
+ * @param value TODO
+ */
+ public SizeSequence(int numEntries, int value)
+ {
+ insertEntries(0, numEntries, value);
+ }
+
+ /**
+ * Constructor SizeSequence
+ * @param sizes TODO
+ */
+ public SizeSequence(int[] sizes)
+ {
+ setSizes(sizes);
+ }
+
+ /**
+ * setSize
+ * @param index TODO
+ * @param size TODO
+ */
+ public void setSize(int index, int size)
+ {
+ sizes[index] = size;
+ }
+
+ /**
+ * getIndex
+ * @param position TODO
+ * @returns int
+ */
+ public int getIndex(int position)
+ {
+ return 0; // TODO
+ }
+
+ /**
+ * getSize
+ * @param index TODO
+ * @returns int
+ */
+ public int getSize(int index)
+ {
+ return sizes[index];
+ }
+
+ /**
+ * setSizes
+ * @param sizes TODO
+ */
+ public void setSizes(int[] sizes)
+ {
+ int index;
+ // Initialize sizes.
+ this.sizes = new int[sizes.length];
+ for (index = 0; index < sizes.length; index++)
+ this.sizes[index] = sizes[index];
+
+ }
+
+ /**
+ * getSizes
+ * @returns int[]
+ */
+ public int[] getSizes()
+ {
+ int[] array;
+ int index;
+
+ // Create new array.
+ array = new int[sizes.length];
+ for (index = 0; index < sizes.length; index++)
+ array[index] = sizes[index];
+
+ // Return newly created array.
+ return array;
+
+ }
+
+ /**
+ * getPosition
+ * @param index TODO
+ * @returns int
+ */
+ public int getPosition(int index)
+ {
+ int position;
+ int loop;
+
+ // Process sizes.
+ position = 0;
+ for (loop = 0; loop < index; loop++)
+ position += sizes[loop];
+
+ // Return position.
+ return position;
+
+ }
+
+ /**
+ * insertEntries
+ * @param start TODO
+ * @param length TODO
+ * @param value TODO
+ */
+ public void insertEntries(int start, int length, int value)
+ {
+ int[] array;
+ int index;
+ int arrayIndex;
+ int loop;
+
+ // Create new array.
+ array = new int[sizes.length + length];
+ arrayIndex = 0;
+ for (index = 0; index < sizes.length; index++)
+ {
+ if (index == start)
+ {
+ for (loop = 0; loop < length; loop++)
+ {
+ array[arrayIndex] = value;
+ arrayIndex++;
+ }
+ }
+ else
+ {
+ array[arrayIndex] = sizes[index];
+ arrayIndex++;
+ }
+ }
+
+ }
+
+ /**
+ * removeEntries
+ * @param start TODO
+ * @param length TODO
+ */
+ public void removeEntries(int start, int length)
+ {
+ int[] array;
+ int index;
+ int arrayIndex;
+
+ // Sanity check.
+ if ((start + length) > sizes.length)
+ throw new IllegalArgumentException("Specified start/length that "
+ + "is greater than available sizes");
+
+ // Create new array.
+ array = new int[sizes.length - length];
+ arrayIndex = 0;
+ for (index = 0; index < sizes.length; index++)
+ {
+ if (index == start)
+ index += length - 1;
+ else
+ {
+ array[arrayIndex] = sizes[index];
+ arrayIndex++;
+ }
+ }
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/SortingFocusTraversalPolicy.java b/libjava/classpath/javax/swing/SortingFocusTraversalPolicy.java
index fada17c6339..96ef3832955 100644
--- a/libjava/classpath/javax/swing/SortingFocusTraversalPolicy.java
+++ b/libjava/classpath/javax/swing/SortingFocusTraversalPolicy.java
@@ -72,7 +72,7 @@ public class SortingFocusTraversalPolicy
* simply advance within the containing focus cycle, subject to the
* {@link #comparator} order and the {@link #accept} judgment.</p>
*
- * @see #getNextFocusableComponent
+ * @see #getImplicitDownCycleTraversal()
*/
boolean implicitDownCycleTraversal = true;
diff --git a/libjava/classpath/javax/swing/SpinnerListModel.java b/libjava/classpath/javax/swing/SpinnerListModel.java
index 85dc4efa6f1..d8e2f22d585 100644
--- a/libjava/classpath/javax/swing/SpinnerListModel.java
+++ b/libjava/classpath/javax/swing/SpinnerListModel.java
@@ -68,231 +68,228 @@ import javax.swing.event.ChangeEvent;
* @since 1.4
*/
-public class SpinnerListModel
- extends AbstractSpinnerModel
- implements Serializable
+public class SpinnerListModel extends AbstractSpinnerModel
+ implements Serializable
{
- /**
- * For compatability with Sun's JDK
- */
- private static final long serialVersionUID = 3358804052191994516L;
+ /**
+ * For compatability with Sun's JDK
+ */
+ private static final long serialVersionUID = 3358804052191994516L;
- /**
- * The backing list for this model.
- */
- private List list;
+ /**
+ * The backing list for this model.
+ */
+ private List list;
- /**
- * The current index in the list.
- */
- private transient int index;
+ /**
+ * The current index in the list.
+ */
+ private transient int index;
- /**
- * Constructs a default <code>SpinnerListModel</code>. This
- * is a model backed by a list containing only the single
- * <code>String</code> element, "empty".
- */
- public SpinnerListModel()
- {
- List defaultList;
+ /**
+ * Constructs a default <code>SpinnerListModel</code>. This
+ * is a model backed by a list containing only the single
+ * <code>String</code> element, "empty".
+ */
+ public SpinnerListModel()
+ {
+ List defaultList;
- /* Create an empty list */
- defaultList = new ArrayList();
- /* Add the string "empty" */
- defaultList.add("empty");
- /* Set the list */
- setList(defaultList);
- }
+ // Create an empty list.
+ defaultList = new ArrayList();
+ // Add the string "empty".
+ defaultList.add("empty");
+ // Set the list.
+ setList(defaultList);
+ }
- /**
- * Constructs a <code>SpinnerListModel</code> using the supplied list.
- * The model maintains a reference to this list, and returns
- * consecutive elements in response to calls to <code>getNextValue()</code>.
- * The initial value is that at position 0, so an initial call
- * to <code>getValue()</code> returns the same as <code>list.get(0)</code>.
- *
- * @param list The list to use for this model.
- * @throws IllegalArgumentException if the list is null or contains no
- * elements.
- * @see SpinnerListModel#getNextValue()
- * @see SpinnerListModel#getValue()
- */
- public SpinnerListModel(List list)
- {
- /* Retain a reference to the valid list */
- setList(list);
- }
+ /**
+ * Constructs a <code>SpinnerListModel</code> using the supplied list.
+ * The model maintains a reference to this list, and returns
+ * consecutive elements in response to calls to <code>getNextValue()</code>.
+ * The initial value is that at position 0, so an initial call
+ * to <code>getValue()</code> returns the same as <code>list.get(0)</code>.
+ *
+ * @param list The list to use for this model.
+ *
+ * @throws IllegalArgumentException if the list is null or contains no
+ * elements.
+ *
+ * @see SpinnerListModel#getNextValue()
+ * @see SpinnerListModel#getValue()
+ */
+ public SpinnerListModel(List list)
+ {
+ // Retain a reference to the valid list.
+ setList(list);
+ }
- /**
- * Constructs a <code>SpinnerListModel</code> using the supplied array.
- * The model stores a reference to the wrapper list returned by
- * <code>Arrays.asList()</code>. The wrapper list reflects modifications
- * in the underlying array, so these changes will also be reflected
- * by the model. The model produces consecutive elements from the array
- * in response to calls to <code>getNextValue()</code>. The initial
- * value returned by <code>getValue()</code> is the same as
- * <code>array[0]</code>.
- *
- * @param array The array to use for this model.
- * @throws IllegalArgumentException if the array is null or contains
- * no elements.
- * @see Arrays#asList(Object[])
- * @see SpinnerListModel#getNextValue()
- * @see SpinnerListModel#getValue()
- */
- public SpinnerListModel(Object[] array)
- {
- /* Check for a null or zero-sized array */
- if (array == null || array.length == 0)
- {
- throw new IllegalArgumentException("The supplied array was invalid.");
- }
- /*
- Retain a reference to a wrapper around the valid array
- The array, in list form, will be tested again here, but we can't really
- avoid this -- a null value to Arrays.asList will throw a NullPointerException
- */
- setList(Arrays.asList(array));
- }
+ /**
+ * Constructs a <code>SpinnerListModel</code> using the supplied array.
+ * The model stores a reference to the wrapper list returned by
+ * <code>Arrays.asList()</code>. The wrapper list reflects modifications
+ * in the underlying array, so these changes will also be reflected
+ * by the model. The model produces consecutive elements from the array
+ * in response to calls to <code>getNextValue()</code>. The initial
+ * value returned by <code>getValue()</code> is the same as
+ * <code>array[0]</code>.
+ *
+ * @param array The array to use for this model.
+ *
+ * @throws IllegalArgumentException if the array is null or contains
+ * no elements.
+ *
+ * @see Arrays#asList(Object[])
+ * @see SpinnerListModel#getNextValue()
+ * @see SpinnerListModel#getValue()
+ */
+ public SpinnerListModel(Object[] array)
+ {
+ // Check for a null or zero-sized array.
+ if (array == null || array.length == 0)
+ {
+ throw new IllegalArgumentException("The supplied array was invalid.");
+ }
- /**
- * Returns the backing list for this model.
- *
- * @return The backing list.
- */
- public List getList()
- {
- return list;
- }
+ // Retain a reference to a wrapper around the valid array.
+ // The array, in list form, will be tested again here, but we can't really
+ // avoid this -- a null value to Arrays.asList will throw a
+ // NullPointerException.
+ setList(Arrays.asList(array));
+ }
+
+ /**
+ * Returns the backing list for this model.
+ *
+ * @return The backing list.
+ */
+ public List getList()
+ {
+ return list;
+ }
- /**
- * Returns the next value from the list, which is the same as the element
- * stored at the current index + 1. Null is returned if there are no more
- * values to be returned (the end of the list has been reached). An
- * ambiguity can occur here, as null may also be returned as a valid list
- * element. This operation does not change the current value.
- *
- * @return The next value from the list or null.
- */
- public Object getNextValue()
- {
- /* Check for a next value */
- if (index < (list.size() - 1))
- {
- /* Return the element at the next index */
- return list.get(index + 1);
- }
- else
- {
- /* Return null as this is the end of the list */
- return null;
- }
+ /**
+ * Returns the next value from the list, which is the same as the element
+ * stored at the current index + 1. Null is returned if there are no more
+ * values to be returned (the end of the list has been reached). An
+ * ambiguity can occur here, as null may also be returned as a valid list
+ * element. This operation does not change the current value.
+ *
+ * @return The next value from the list or null.
+ */
+ public Object getNextValue()
+ {
+ // Check for a next value.
+ if (index < (list.size() - 1))
+ // Return the element at the next index.
+ return list.get(index + 1);
+ else
+ // Return null as this is the end of the list.
+ return null;
}
- /**
- * Returns the previous value from the list, which is the same as the element
- * stored at the current index - 1. Null is returned if there are no more
- * values to be returned (the start of the list has been reached). An
- * ambiguity can occur here, as null may also be returned as a valid list
- * element. This operation does not change the current value.
- *
- * @return The previous value from the list or null.
- */
- public Object getPreviousValue()
- {
- /* Check for a previous value. */
- if (index > 0)
- {
- /* Return the element at the previous position */
- return list.get(index - 1);
- }
+ /**
+ * Returns the previous value from the list, which is the same as the element
+ * stored at the current index - 1. Null is returned if there are no more
+ * values to be returned (the start of the list has been reached). An
+ * ambiguity can occur here, as null may also be returned as a valid list
+ * element. This operation does not change the current value.
+ *
+ * @return The previous value from the list or null.
+ */
+ public Object getPreviousValue()
+ {
+ // Check for a previous value.
+ if (index > 0)
+ // Return the element at the previous position.
+ return list.get(index - 1);
else
- {
- /* Return null as this is the start of the list */
- return null;
- }
+ // Return null as this is the start of the list.
+ return null;
}
- /**
- * Returns the current value of the model. Initially, this will
- * be the element at position 0. On later invocations, this will
- * be the last element returned by <code>getNextValue()</code>
- * or <code>getPreviousValue()</code>.
- *
- * @return The current value.
- * @see SpinnerListModel#getPreviousValue()
- * @see SpinnerListModel#getNextValue()
- */
- public Object getValue()
- {
- return list.get(index);
- }
+ /**
+ * Returns the current value of the model. Initially, this will
+ * be the element at position 0. On later invocations, this will
+ * be the last element returned by <code>getNextValue()</code>
+ * or <code>getPreviousValue()</code>.
+ *
+ * @return The current value.
+ *
+ * @see SpinnerListModel#getPreviousValue()
+ * @see SpinnerListModel#getNextValue()
+ */
+ public Object getValue()
+ {
+ return list.get(index);
+ }
- /**
- * Changes the backing list for this model. The model only stores
- * a reference to the list, so any changes made to the list elsewhere
- * will be reflected in the values returned by the model. A
- * <code>ChangeEvent</code> is fired if the list being used actually
- * changes (i.e. the new list is not referentially equal (!=) to the
- * old one).
- *
- * @param list The new list to use.
- * @throws IllegalArgumentException if the list is null or contains
- * no elements.
- * @see ChangeEvent
- */
- public void setList(List list)
- {
- /* Check for null or zero size list */
- if (list == null || list.size() == 0)
- {
- throw new IllegalArgumentException("The supplied list was invalid.");
- }
- /* Check for a change of referenced list */
- if (this.list != list)
- {
- /* Store the new list */
- this.list = list;
- /* Notify listeners of a change */
- fireStateChanged();
- }
- /* We reset the other values in either case */
- /* Set the index to 0 */
- index = 0;
- }
+ /**
+ * Changes the backing list for this model. The model only stores
+ * a reference to the list, so any changes made to the list elsewhere
+ * will be reflected in the values returned by the model. A
+ * <code>ChangeEvent</code> is fired if the list being used actually
+ * changes (i.e. the new list is not referentially equal (!=) to the
+ * old one).
+ *
+ * @param list The new list to use.
+ *
+ * @throws IllegalArgumentException if the list is null or contains
+ * no elements.
+ *
+ * @see ChangeEvent
+ */
+ public void setList(List list)
+ {
+ // Check for null or zero size list.
+ if (list == null || list.size() == 0)
+ throw new IllegalArgumentException("The supplied list was invalid.");
- /**
- * Sets the current value of the model to be the one supplied.
- * The value must exist within the backing list in order for
- * the change to take place. Otherwise, an exception is thrown.
- * The value used is the first occurrence of the value within
- * the backing list. Listeners are notified of this change.
- * Following the change, <code>getNextValue()</code> and
- * <code>getPreviousValue()</code> return the objects following
- * and prior to the supplied value, respectively.
- *
- * @param value The requested new value of the list.
- * @throws IllegalArgumentException if the supplied value does
- * not exist in the backing list.
- * @see SpinnerListModel#getPreviousValue()
- * @see SpinnerListModel#getNextValue()
- */
- public void setValue(Object value)
- {
- int valueIndex;
+ // Check for a change of referenced list.
+ if (this.list != list)
+ {
+ // Store the new list.
+ this.list = list;
+ // Notify listeners of a change.
+ fireStateChanged();
+ }
+ // We reset the other values in either case.
+ // Set the index to 0.
+ index = 0;
+ }
- /* Search for the value in the list */
- valueIndex = list.indexOf(value);
- /* Check for the value being found */
- if (valueIndex == -1)
- {
- throw new IllegalArgumentException("The supplied value does not "
- + "exist in this list");
- }
- /* Make the indices match */
- index = valueIndex;
- /* Notify the listeners */
- fireStateChanged();
- }
+ /**
+ * Sets the current value of the model to be the one supplied.
+ * The value must exist within the backing list in order for
+ * the change to take place. Otherwise, an exception is thrown.
+ * The value used is the first occurrence of the value within
+ * the backing list. Listeners are notified of this change.
+ * Following the change, <code>getNextValue()</code> and
+ * <code>getPreviousValue()</code> return the objects following
+ * and prior to the supplied value, respectively.
+ *
+ * @param value The requested new value of the list.
+ *
+ * @throws IllegalArgumentException if the supplied value does
+ * not exist in the backing list.
+ *
+ * @see SpinnerListModel#getPreviousValue()
+ * @see SpinnerListModel#getNextValue()
+ */
+ public void setValue(Object value)
+ {
+ int valueIndex;
+
+ // Search for the value in the list.
+ valueIndex = list.indexOf(value);
+ // Check for the value being found.
+ if (valueIndex == -1)
+ throw new IllegalArgumentException("The supplied value does not "
+ + "exist in this list");
+ // Make the indices match.
+ index = valueIndex;
+ // Notify the listeners.
+ fireStateChanged();
+ }
}
diff --git a/libjava/classpath/javax/swing/Spring.java b/libjava/classpath/javax/swing/Spring.java
index 69c88c77d96..8f7105d496d 100644
--- a/libjava/classpath/javax/swing/Spring.java
+++ b/libjava/classpath/javax/swing/Spring.java
@@ -65,6 +65,7 @@ public abstract class Spring
*/
protected Spring()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/SpringLayout.java b/libjava/classpath/javax/swing/SpringLayout.java
index df9ddffb654..592cc0e02a9 100644
--- a/libjava/classpath/javax/swing/SpringLayout.java
+++ b/libjava/classpath/javax/swing/SpringLayout.java
@@ -395,46 +395,40 @@ public class SpringLayout implements LayoutManager2
public SpringLayout.Constraints getConstraints(Component c)
{
Constraints constraints = (Constraints) constraintsMap.get(c);
+
if (constraints == null)
{
Container parent = c.getParent();
constraints = new Constraints();
+
if (parent != null)
{
- constraints.setX
- (Spring.constant(parent.getInsets().left));
- constraints.setY
- (Spring.constant(parent.getInsets().top));
+ constraints.setX(Spring.constant(parent.getInsets().left));
+ constraints.setY(Spring.constant(parent.getInsets().top));
}
else
{
- constraints.setX
- (Spring.constant(0));
- constraints.setY
- (Spring.constant(0));
-
+ constraints.setX(Spring.constant(0));
+ constraints.setY(Spring.constant(0));
}
- constraints.setWidth
- (Spring.constant(c.getMinimumSize().width,
- c.getPreferredSize().width,
- c.getMaximumSize().width));
- constraints.setHeight
- (Spring.constant(c.getMinimumSize().height,
- c.getPreferredSize().height,
- c.getMaximumSize().height));
-
- constraintsMap.put(c, constraints);
-
}
+ constraints.setWidth(Spring.constant(c.getMinimumSize().width,
+ c.getPreferredSize().width,
+ c.getMaximumSize().width));
+ constraints.setHeight(Spring.constant(c.getMinimumSize().height,
+ c.getPreferredSize().height,
+ c.getMaximumSize().height));
+ constraintsMap.put(c, constraints);
return constraints;
}
/**
* Returns the X alignment of the Container <code>p</code>.
- *
- * @param p the {@link java.awt.Container} for which to determine the X
- * alignment.
+ *
+ * @param p
+ * the {@link java.awt.Container} for which to determine the X
+ * alignment.
* @return always 0.0
*/
public float getLayoutAlignmentX(Container p)
@@ -480,6 +474,7 @@ public class SpringLayout implements LayoutManager2
for (int index = 0; index < components.length; index++)
{
Component c = components[index];
+
Constraints constraints = getConstraints(c);
int x = constraints.getX().getValue();
int y = constraints.getY().getValue();
@@ -597,7 +592,6 @@ public class SpringLayout implements LayoutManager2
if (bottomEdge > maxY)
maxY = bottomEdge;
}
-
return new Dimension(maxX, maxY);
}
@@ -621,7 +615,6 @@ public class SpringLayout implements LayoutManager2
Spring strut = Spring.constant(pad);
Spring otherEdge = constraints2.getConstraint(e2);
constraints1.setConstraint(e1, Spring.sum(strut, otherEdge));
-
}
/**
diff --git a/libjava/classpath/javax/swing/SwingUtilities.java b/libjava/classpath/javax/swing/SwingUtilities.java
index ee5fa74d47a..58b3a78d7aa 100644
--- a/libjava/classpath/javax/swing/SwingUtilities.java
+++ b/libjava/classpath/javax/swing/SwingUtilities.java
@@ -840,7 +840,7 @@ public class SwingUtilities
iconR.width = icon.getIconWidth();
iconR.height = icon.getIconHeight();
}
- if (text == null)
+ if (text == null || text.equals(""))
{
textIconGap = 0;
textR.width = 0;
@@ -890,7 +890,7 @@ public class SwingUtilities
iconR.y = 0;
textR.y = (horizontalTextPosition == CENTER
? iconR.height + textIconGap
- : iconR.height - textR.height);
+ : Math.max(iconR.height - textR.height, 0));
break;
case CENTER:
int centerLine = Math.max(textR.height, iconR.height) / 2;
@@ -1116,7 +1116,7 @@ public class SwingUtilities
* <pre>
* [{@link javax.swing.JComponent#getActionMap()}]
* --&gt; [{@link javax.swing.ActionMap}]
- * parent --&gt; [{@link javax.swing.text.KeymapActionMap}]
+ * parent --&gt; [{@link javax.swing.text.JTextComponent.KeymapActionMap}]
* parent --&gt; [{@link javax.swing.plaf.ActionMapUIResource}]
* </pre>
*
@@ -1138,14 +1138,12 @@ public class SwingUtilities
else
{
ActionMap parent = child.getParent();
- while(parent != null)
+ while (parent != null && !(parent instanceof ActionMapUIResource))
{
child = parent;
parent = child.getParent();
}
-
- if (child != null)
- child.setParent(uiActionMap);
+ child.setParent(uiActionMap);
}
}
@@ -1159,7 +1157,7 @@ public class SwingUtilities
* <pre>
* [{@link javax.swing.JComponent#getInputMap()}]
* --&gt; [{@link javax.swing.InputMap}]
- * parent --&gt; [{@link javax.swing.text.KeymapWrapper}]
+ * parent --&gt; [{@link javax.swing.text.JTextComponent.KeymapWrapper}]
* parent --&gt; [{@link javax.swing.plaf.InputMapUIResource}]
* </pre>
*
@@ -1181,11 +1179,13 @@ public class SwingUtilities
component.setInputMap(condition, uiInputMap);
else
{
- while(child.getParent() != null
- && !(child.getParent() instanceof InputMapUIResource))
- child = child.getParent();
- if (child != null)
- child.setParent(uiInputMap);
+ InputMap parent = child.getParent();
+ while (parent != null && !(parent instanceof InputMapUIResource))
+ {
+ child = parent;
+ parent = parent.getParent();
+ }
+ child.setParent(uiInputMap);
}
}
diff --git a/libjava/classpath/javax/swing/Timer.java b/libjava/classpath/javax/swing/Timer.java
index 87f420a4367..cf91c23e8ec 100644
--- a/libjava/classpath/javax/swing/Timer.java
+++ b/libjava/classpath/javax/swing/Timer.java
@@ -46,7 +46,12 @@ import java.util.EventListener;
import javax.swing.event.EventListenerList;
/**
- * Fires one or more action events after the specified delay.
+ * Fires one or more action events after the specified delay. This is
+ * a specialised version of <code>java.util.Timer</code> just for
+ * firing <code>ActionEvent</code>s. All Timers share one (daemon)
+ * Thread (or java.util.Timer). All events are fired from the event
+ * queue.
+ *
* @author Ronald Veldema
* @author Audrius Meskauskas (audriusa@Bionformatics.org) - bug fixes
* and documentation comments
@@ -55,48 +60,19 @@ public class Timer
implements Serializable
{
/**
- * The timer thread
+ * Given to the shared java.util.Timer to (possibly repeatedly) call
+ * queueEvent().
*/
- private class Waker
- extends Thread
+ private class Task extends java.util.TimerTask
{
- /**
- * Fires events, pausing for required intervals.
- */
public void run()
{
- running = true;
- try
- {
- sleep(initialDelay);
-
- queueEvent();
-
- while (running)
- {
- try
- {
- sleep(delay);
- }
- catch (InterruptedException e)
- {
- return;
- }
- queueEvent();
-
- if (logTimers)
- System.out.println("javax.swing.Timer -> clocktick");
-
- if ( ! repeats)
- break;
- }
- running = false;
- }
- catch (Exception e)
- {
- // The timer is no longer running.
- running = false;
- }
+ if (logTimers)
+ System.out.println("javax.swing.Timer -> queueEvent()");
+ queueEvent();
+
+ if (!repeats)
+ task = null;
}
}
@@ -118,6 +94,14 @@ public class Timer
};
/**
+ * The static java.util.Timer daemon which will be used to schedule
+ * all javax.swing.Timer.Task objects. The daemon will always be
+ * running, even if there's no task scheduled in it.
+ */
+ private static java.util.Timer timer = new java.util.Timer("swing.Timer",
+ true);
+
+ /**
* If <code>true</code>, the timer prints a message to
* {@link System#out} when firing each event.
*/
@@ -139,12 +123,6 @@ public class Timer
boolean repeats = true;
/**
- * <code>true</code> if the timer is currently active, firing events
- * as scheduled.
- */
- boolean running;
-
- /**
* The delay between subsequent repetetive events.
*/
int delay;
@@ -162,10 +140,9 @@ public class Timer
int ticks;
/**
- * Stores the thread that posts events to the queue at required time
- * intervals.
+ * The task that calls queueEvent(). When null this Timer is stopped.
*/
- private Waker waker;
+ private Task task;
/**
* This object manages a "queue" of virtual actionEvents, maintained as a
@@ -360,7 +337,7 @@ public class Timer
*/
public boolean isRunning()
{
- return running;
+ return task != null;
}
/**
@@ -398,10 +375,16 @@ public class Timer
*/
public void start()
{
- if (isRunning())
- return;
- waker = new Waker();
- waker.start();
+ Task t = task;
+ if (t == null)
+ {
+ t = new Task();
+ if (isRepeats())
+ timer.schedule(t, getInitialDelay(), getDelay());
+ else
+ timer.schedule(t, getInitialDelay());
+ task = t;
+ }
}
/**
@@ -409,12 +392,11 @@ public class Timer
*/
public void stop()
{
- running = false;
- if (waker != null)
- waker.interrupt();
- synchronized (queueLock)
+ Task t = task;
+ if (t != null)
{
- queue = 0;
+ t.cancel();
+ task = null;
}
}
@@ -475,11 +457,11 @@ public class Timer
*/
void queueEvent()
{
- synchronized (queueLock)
+ synchronized(queueLock)
{
- queue++;
- if (queue == 1)
- SwingUtilities.invokeLater(drainer);
+ queue++;
+ if (queue == 1)
+ SwingUtilities.invokeLater(drainer);
}
}
}
diff --git a/libjava/classpath/javax/swing/ToolTipManager.java b/libjava/classpath/javax/swing/ToolTipManager.java
index 61693763898..03835794b68 100644
--- a/libjava/classpath/javax/swing/ToolTipManager.java
+++ b/libjava/classpath/javax/swing/ToolTipManager.java
@@ -44,7 +44,6 @@ import java.awt.FlowLayout;
import java.awt.LayoutManager;
import java.awt.Panel;
import java.awt.Point;
-import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
@@ -68,6 +67,7 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
*/
protected stillInsideTimerAction()
{
+ // Nothing to do here.
}
/**
@@ -93,6 +93,7 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
*/
protected outsideTimerAction()
{
+ // Nothing to do here.
}
/**
@@ -103,6 +104,7 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
*/
public void actionPerformed(ActionEvent event)
{
+ // TODO: What should be done here, if anything?
}
}
@@ -118,6 +120,7 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
*/
protected insideTimerAction()
{
+ // Nothing to do here.
}
/**
@@ -129,8 +132,6 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
public void actionPerformed(ActionEvent event)
{
showTip();
- if (insideTimer != null)
- insideTimer.start();
}
}
@@ -183,7 +184,7 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
* The window used when the tooltip doesn't fit inside the current
* container.
*/
- private static JWindow tooltipWindow;
+ private static JDialog tooltipWindow;
/**
* Creates a new ToolTipManager and sets up the timers.
@@ -373,7 +374,6 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
if (exitTimer.isRunning())
{
exitTimer.stop();
- showTip();
insideTimer.start();
return;
}
@@ -424,13 +424,6 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
insideTimer.stop();
hideTip();
}
-
- if (currentComponent == null)
- currentComponent = (Component) event.getSource();
-
- currentComponent.invalidate();
- currentComponent.validate();
- currentComponent.repaint();
}
/**
@@ -455,16 +448,8 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
public void mouseMoved(MouseEvent event)
{
currentPoint = event.getPoint();
- if (currentTip != null)
- {
- if (currentComponent == null)
- currentComponent = (Component) event.getSource();
-
- String text = ((JComponent) currentComponent).getToolTipText(event);
- currentTip.setTipText(text);
- }
if (enterTimer.isRunning())
- enterTimer.restart();
+ enterTimer.restart();
}
/**
@@ -474,70 +459,103 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
*/
void showTip()
{
- if (! enabled || currentComponent == null)
+ if (!enabled || currentComponent == null || !currentComponent.isEnabled()
+ || (currentTip != null && currentTip.isVisible()))
return;
- if (currentTip == null
- || currentTip.getComponent() != currentComponent
+ if (currentTip == null || currentTip.getComponent() != currentComponent
&& currentComponent instanceof JComponent)
currentTip = ((JComponent) currentComponent).createToolTip();
+
+ currentTip.setVisible(true);
+ Container parent = currentComponent.getParent();
Point p = currentPoint;
Dimension dims = currentTip.getPreferredSize();
- if (canToolTipFit(currentTip))
- {
- JLayeredPane pane = ((JRootPane) SwingUtilities.getAncestorOfClass(JRootPane.class,
- currentComponent))
- .getLayeredPane();
-
- // This should never happen, but just in case.
- if (pane == null)
- return;
-
- if (containerPanel != null)
- hideTip();
- if (isLightWeightPopupEnabled())
- {
- containerPanel = new Panel();
- JRootPane root = new JRootPane();
- root.getContentPane().add(currentTip);
- containerPanel.add(root);
- }
- else
- {
- containerPanel = new JPanel();
- containerPanel.add(currentTip);
- }
- LayoutManager lm = containerPanel.getLayout();
- if (lm instanceof FlowLayout)
- {
- FlowLayout fm = (FlowLayout) lm;
- fm.setVgap(0);
- fm.setHgap(0);
- }
-
- p = getGoodPoint(p, pane, currentTip, dims);
-
- pane.add(containerPanel);
- containerPanel.setBounds(p.x, p.y, dims.width, dims.height);
- currentTip.setBounds(0, 0, dims.width, dims.height);
-
- pane.revalidate();
- pane.repaint();
- }
+
+ if (parent instanceof JPopupMenu)
+ setLightWeightPopupEnabled(((JPopupMenu) parent).isLightWeightPopupEnabled());
else
+ setLightWeightPopupEnabled(true);
+
+ if (isLightWeightPopupEnabled())
{
- SwingUtilities.convertPointToScreen(p, currentComponent);
- tooltipWindow = new JWindow();
- tooltipWindow.getContentPane().add(currentTip);
- tooltipWindow.setFocusable(false);
- tooltipWindow.pack();
- tooltipWindow.setBounds(p.x, p.y, dims.width, dims.height);
- tooltipWindow.show();
+ JLayeredPane pane = null;
+ JRootPane r = ((JRootPane) SwingUtilities.
+ getAncestorOfClass(JRootPane.class, currentComponent));
+ if (r != null)
+ pane = r.getLayeredPane();
+ if (pane == null)
+ return;
+
+ if (containerPanel != null)
+ hideTip();
+
+ containerPanel = new Panel();
+ JRootPane root = new JRootPane();
+ root.getContentPane().add(currentTip);
+ containerPanel.add(root);
+
+ LayoutManager lm = containerPanel.getLayout();
+ if (lm instanceof FlowLayout)
+ {
+ FlowLayout fm = (FlowLayout) lm;
+ fm.setVgap(0);
+ fm.setHgap(0);
+ }
+
+ p = SwingUtilities.convertPoint(currentComponent, p, pane);
+ p = adjustLocation(p, pane, dims);
+
+ pane.add(containerPanel);
+ containerPanel.setBounds(p.x, p.y, dims.width, dims.height);
+ currentTip.setBounds(0, 0, dims.width, dims.height);
+ containerPanel.validate();
+ containerPanel.repaint();
+ }
+ else if (currentComponent.isShowing())
+ {
+ SwingUtilities.convertPointToScreen(p, currentComponent);
+ p = adjustLocation(p, SwingUtilities.getWindowAncestor(currentComponent),
+ dims);
+
+ tooltipWindow = new JDialog();
+ tooltipWindow.setContentPane(currentTip);
+ tooltipWindow.setUndecorated(true);
+ tooltipWindow.getRootPane().
+ setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);
+ tooltipWindow.pack();
+ tooltipWindow.setBounds(p.x, p.y, dims.width, dims.height);
+ tooltipWindow.show();
+ tooltipWindow.validate();
+ tooltipWindow.repaint();
+ currentTip.revalidate();
+ currentTip.repaint();
}
- currentTip.setVisible(true);
}
/**
+ * Adjusts the point to a new location on the component,
+ * using the currentTip's dimensions.
+ *
+ * @param p - the point to convert.
+ * @param c - the component the point is on.
+ * @param d - the dimensions of the currentTip.
+ */
+ private Point adjustLocation(Point p, Component c, Dimension d)
+ {
+ if (p.x + d.width > c.getWidth())
+ p.x -= d.width;
+ if (p.x < 0)
+ p.x = 0;
+ if (p.y + d.height < c.getHeight())
+ p.y += d.height;
+ if (p.y + d.height > c.getHeight())
+ p.y -= d.height*2;
+
+ return p;
+ }
+
+ /**
* This method hides the ToolTip.
* This is package-private to avoid an accessor method.
*/
@@ -552,15 +570,11 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
if (parent == null)
return;
parent.remove(containerPanel);
- parent.invalidate();
- parent.validate();
- parent.repaint();
parent = currentTip.getParent();
if (parent == null)
return;
parent.remove(currentTip);
-
containerPanel = null;
}
if (tooltipWindow != null)
@@ -569,35 +583,7 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
tooltipWindow.dispose();
tooltipWindow = null;
}
- }
-
- /**
- * This method returns a point in the LayeredPane where the ToolTip can be
- * shown. The point returned (if the ToolTip is to be displayed at the
- * preferred dimensions) will always place the ToolTip inside the
- * currentComponent if possible.
- *
- * @param p The last known good point for the mouse.
- * @param c The JLayeredPane in the first RootPaneContainer up from the
- * currentComponent.
- * @param tip The ToolTip to display.
- * @param dims The ToolTip preferred dimensions (can be null).
- *
- * @return A good point to place the ToolTip.
- */
- private Point getGoodPoint(Point p, JLayeredPane c, JToolTip tip,
- Dimension dims)
- {
- if (dims == null)
- dims = tip.getPreferredSize();
- Rectangle bounds = currentComponent.getBounds();
- if (p.x + dims.width > bounds.width)
- p.x = bounds.width - dims.width;
- if (p.y + dims.height > bounds.height)
- p.y = bounds.height - dims.height;
-
- p = SwingUtilities.convertPoint(currentComponent, p, c);
- return p;
+ currentTip = null;
}
/**
@@ -622,25 +608,4 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
Component target = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y);
return target;
}
-
- /**
- * This method returns whether the ToolTip can fit in the first
- * RootPaneContainer up from the currentComponent.
- *
- * @param tip The ToolTip.
- *
- * @return Whether the ToolTip can fit.
- */
- private boolean canToolTipFit(JToolTip tip)
- {
- JRootPane root = (JRootPane) SwingUtilities.getAncestorOfClass(JRootPane.class,
- currentComponent);
- if (root == null)
- return false;
- Dimension pref = tip.getPreferredSize();
- Dimension rootSize = root.getSize();
- if (rootSize.width > pref.width && rootSize.height > pref.height)
- return true;
- return false;
- }
}
diff --git a/libjava/classpath/javax/swing/TransferHandler.java b/libjava/classpath/javax/swing/TransferHandler.java
index 96cb9d42abf..4828fdbfa98 100644
--- a/libjava/classpath/javax/swing/TransferHandler.java
+++ b/libjava/classpath/javax/swing/TransferHandler.java
@@ -75,30 +75,38 @@ public class TransferHandler implements Serializable
}
}
+ /**
+ * Get the system cliboard. If not available, create and return the VM-local
+ * clipboard.
+ *
+ * @param component a component, used to get the toolkit.
+ * @return the clipboard
+ */
private static Clipboard getClipboard(JComponent component)
{
- SecurityManager sm = System.getSecurityManager();
-
- if (sm != null)
- {
- try
- {
- sm.checkSystemClipboardAccess();
-
- // We may access system clipboard.
- return component.getToolkit().getSystemClipboard();
- }
- catch (SecurityException e)
- {
- // We may not access system clipboard.
- }
- }
-
- // Create VM-local clipboard if non exists yet.
- if (clipboard == null)
- clipboard = new Clipboard("Clipboard");
-
- return clipboard;
+ // Avoid throwing exception if the system clipboard access failed
+ // in the past.
+ if (clipboard != null)
+ return clipboard;
+ else
+ {
+ try
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSystemClipboardAccess();
+
+ // We may access system clipboard.
+ return component.getToolkit().getSystemClipboard();
+ }
+ catch (Exception e)
+ {
+ // We may not access system clipboard.
+ // Create VM-local clipboard if none exists yet.
+ clipboard = new Clipboard("Clipboard");
+ return clipboard;
+ }
+ }
}
}
@@ -162,15 +170,18 @@ public class TransferHandler implements Serializable
}
public void exportAsDrag (JComponent c, InputEvent e, int action)
- {
+ {
+ // TODO: Implement this properly
}
protected void exportDone (JComponent c, Transferable data, int action)
{
+ // TODO: Implement this properly
}
public void exportToClipboard(JComponent c, Clipboard clip, int action)
{
+ // TODO: Implement this properly
}
public int getSourceActions (JComponent c)
diff --git a/libjava/classpath/javax/swing/UIDefaults.java b/libjava/classpath/javax/swing/UIDefaults.java
index ab78ca6442f..f6aee1b944c 100644
--- a/libjava/classpath/javax/swing/UIDefaults.java
+++ b/libjava/classpath/javax/swing/UIDefaults.java
@@ -577,8 +577,8 @@ public class UIDefaults extends Hashtable
*
* @param key the key to the requested entry
*
- * @return the boolean entry for <code>key</code> or null if no such entry
- * exists
+ * @return The boolean entry for <code>key</code> or <code>false</code> if no
+ * such entry exists.
*/
public boolean getBoolean(Object key)
{
@@ -674,9 +674,9 @@ public class UIDefaults extends Hashtable
return null;
try
{
- if (loader != null)
- return loader.loadClass (className);
- return Class.forName (className);
+ if (loader == null)
+ loader = ClassLoader.getSystemClassLoader();
+ return loader.loadClass (className);
}
catch (Exception e)
{
diff --git a/libjava/classpath/javax/swing/UIManager.java b/libjava/classpath/javax/swing/UIManager.java
index f4648f1e219..15a78190303 100644
--- a/libjava/classpath/javax/swing/UIManager.java
+++ b/libjava/classpath/javax/swing/UIManager.java
@@ -146,19 +146,29 @@ public class UIManager implements Serializable
LookAndFeel laf = (LookAndFeel) lafClass.newInstance();
setLookAndFeel(laf);
}
+ else
+ {
+ setLookAndFeel(new MetalLookAndFeel());
+ }
}
catch (Exception ex)
{
System.err.println("cannot initialize Look and Feel: " + defaultlaf);
- System.err.println("error: " + ex.getMessage());
+ System.err.println("error: " + ex.toString());
System.err.println("falling back to Metal Look and Feel");
+ try
+ {
+ setLookAndFeel(new MetalLookAndFeel());
+ }
+ catch (Exception ex2)
+ {
+ throw (Error) new AssertionError("There must be no problem installing"
+ + " the MetalLookAndFeel.")
+ .initCause(ex2);
+ }
}
- currentLookAndFeel = new MetalLookAndFeel();
- currentLookAndFeel.initialize();
- currentUIDefaults = currentLookAndFeel.getDefaults();
-
}
-
+
/**
* Creates a new instance of the <code>UIManager</code>. There is no need
* to construct an instance of this class, since all methods are static.
diff --git a/libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java b/libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java
index 5abe45fe117..f99c0ac19f7 100644
--- a/libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java
+++ b/libjava/classpath/javax/swing/UnsupportedLookAndFeelException.java
@@ -40,8 +40,8 @@ package javax.swing;
public class UnsupportedLookAndFeelException extends Exception
{
- public UnsupportedLookAndFeelException(String a)
- {
- super(a);
- }
+ public UnsupportedLookAndFeelException(String a)
+ {
+ super(a);
+ }
}
diff --git a/libjava/classpath/javax/swing/ViewportLayout.java b/libjava/classpath/javax/swing/ViewportLayout.java
index 19735839387..884f7cb27a8 100644
--- a/libjava/classpath/javax/swing/ViewportLayout.java
+++ b/libjava/classpath/javax/swing/ViewportLayout.java
@@ -56,12 +56,17 @@ public class ViewportLayout implements LayoutManager, Serializable
public ViewportLayout()
{
+ // Nothing to do here.
}
+
public void addLayoutComponent(String name, Component c)
{
+ // Nothing to do here.
}
+
public void removeLayoutComponent(Component c)
{
+ // Nothing to do here.
}
public Dimension preferredLayoutSize(Container parent)
diff --git a/libjava/classpath/javax/swing/WindowConstants.java b/libjava/classpath/javax/swing/WindowConstants.java
index 5e364434484..aaa0cb9a3ab 100644
--- a/libjava/classpath/javax/swing/WindowConstants.java
+++ b/libjava/classpath/javax/swing/WindowConstants.java
@@ -43,31 +43,26 @@ package javax.swing;
*
* @author Andrew Selkirk
*/
-public interface WindowConstants {
+public interface WindowConstants
+{
+ /**
+ * DO_NOTHING_ON_CLOSE
+ */
+ int DO_NOTHING_ON_CLOSE = 0;
- //-------------------------------------------------------------
- // Variables --------------------------------------------------
- //-------------------------------------------------------------
+ /**
+ * HIDE_ON_CLOSE
+ */
+ int HIDE_ON_CLOSE = 1;
- /**
- * DO_NOTHING_ON_CLOSE
- */
- int DO_NOTHING_ON_CLOSE = 0;
+ /**
+ * DISPOSE_ON_CLOSE
+ */
+ int DISPOSE_ON_CLOSE = 2;
- /**
- * HIDE_ON_CLOSE
- */
- int HIDE_ON_CLOSE = 1;
+ /**
+ * EXIT_ON_CLOSE
+ */
+ int EXIT_ON_CLOSE =3;
- /**
- * DISPOSE_ON_CLOSE
- */
- int DISPOSE_ON_CLOSE = 2;
-
- /**
- * EXIT_ON_CLOSE
- */
- int EXIT_ON_CLOSE =3;
-
-
-} // WindowConstants
+}
diff --git a/libjava/classpath/javax/swing/border/AbstractBorder.java b/libjava/classpath/javax/swing/border/AbstractBorder.java
index 951debd5207..7cbbcdaa83b 100644
--- a/libjava/classpath/javax/swing/border/AbstractBorder.java
+++ b/libjava/classpath/javax/swing/border/AbstractBorder.java
@@ -52,20 +52,18 @@ import java.io.Serializable;
* @author Sascha Brawer (brawer@dandelis.ch)
* @author Ronald Veldema (rveldema@cs.vu.nl)
*/
-public abstract class AbstractBorder
- implements Border, Serializable
+public abstract class AbstractBorder implements Border, Serializable
{
static final long serialVersionUID = -545885975315191844L;
-
/**
* Constructs a new AbstractBorder.
*/
- public AbstractBorder ()
+ public AbstractBorder()
{
+ // Nothing to do here.
}
-
/**
* Performs nothing, because the default implementation provided by
* this class is an invisible, zero-width border. Subclasses will
@@ -79,17 +77,15 @@ public abstract class AbstractBorder
* @param width the width of the available area for painting the border.
* @param height the height of the available area for painting the border.
*/
- public void paintBorder (Component c, Graphics g,
- int x, int y, int width, int height)
+ public void paintBorder(Component c, Graphics g, int x, int y, int width,
+ int height)
{
- /* A previous version of Classpath had emitted a warning when
- * this method was called. The warning was removed because it is
- * perfectly legal for a subclass to not override the paintBorder
- * method. An example would be EmptyBorder.
- */
+ // A previous version of Classpath had emitted a warning when
+ // this method was called. The warning was removed because it is
+ // perfectly legal for a subclass to not override the paintBorder
+ // method. An example would be EmptyBorder.
}
-
/**
* Measures the width of this border.
*
@@ -102,31 +98,29 @@ public abstract class AbstractBorder
*
* @see #getBorderInsets(java.awt.Component, java.awt.Insets)
*/
- public Insets getBorderInsets (Component c)
+ public Insets getBorderInsets(Component c)
{
- return new Insets (0, 0, 0, 0);
+ return new Insets(0, 0, 0, 0);
}
-
/**
* Determines the insets of this border. The implementation provided
* by AbstractButton sets the <code>left</code>, <code>right</code>,
* <code>top</code> and <code>bottom</code> fields of the passed
* <code>insets</code> parameter to zero.
*
- * @param c the component whose border is to be measured.
+ * @param c the component whose border is to be measured
*
- * @return the same object that was passed for <code>insets</code>.
+ * @return the same object that was passed for <code>insets</code>
*
* @see #getBorderInsets(Component)
*/
- public Insets getBorderInsets (Component c, Insets insets)
+ public Insets getBorderInsets(Component c, Insets insets)
{
insets.left = insets.right = insets.top = insets.bottom = 0;
return insets;
}
-
/**
* Determines whether or not this border is opaque. An opaque border
* fills every pixel in its area when painting. Partially
@@ -136,12 +130,11 @@ public abstract class AbstractBorder
*
* @return <code>false</code>.
*/
- public boolean isBorderOpaque ()
+ public boolean isBorderOpaque()
{
return false;
}
-
/**
* Returns a rectangle that covers the specified area minus this
* border. Components that wish to determine an area into which
@@ -154,12 +147,11 @@ public abstract class AbstractBorder
* @param width the width of the available area for the border.
* @param height the height of the available area for the border.
*/
- public Rectangle getInteriorRectangle (Component c,
- int x, int y, int width, int height)
+ public Rectangle getInteriorRectangle(Component c, int x, int y, int width,
+ int height)
{
return getInteriorRectangle (c, this, x, y, width, height);
}
-
/**
* Returns a rectangle that covers the specified area minus a
@@ -173,8 +165,8 @@ public abstract class AbstractBorder
* @param width the width of the available area for the border.
* @param height the height of the available area for the border.
*/
- public static Rectangle getInteriorRectangle (Component c, Border b,
- int x, int y, int width, int height)
+ public static Rectangle getInteriorRectangle(Component c, Border b, int x,
+ int y, int width, int height)
{
Insets borderInsets;
diff --git a/libjava/classpath/javax/swing/border/BevelBorder.java b/libjava/classpath/javax/swing/border/BevelBorder.java
index fcdc1c64675..45b758cae41 100644
--- a/libjava/classpath/javax/swing/border/BevelBorder.java
+++ b/libjava/classpath/javax/swing/border/BevelBorder.java
@@ -55,8 +55,7 @@ import java.awt.Insets;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class BevelBorder
- extends AbstractBorder
+public class BevelBorder extends AbstractBorder
{
/**
* Determined using the <code>serialver</code> tool
@@ -508,11 +507,11 @@ public class BevelBorder
* Paints a two-pixel bevel in four colors.
*
* <pre>
- * @@@@@@@@@@@@
- * @..........# @ = color a
- * @. X# . = color b
- * @. X# X = color c
- * @.XXXXXXXXX# # = color d
+ * ++++++++++++
+ * +..........# + = color a
+ * +. X# . = color b
+ * +. X# X = color c
+ * +.XXXXXXXXX# # = color d
* ############</pre>
*
* @param g the graphics for painting.
diff --git a/libjava/classpath/javax/swing/border/Border.java b/libjava/classpath/javax/swing/border/Border.java
index 11bddfe78b3..f4af3fb38bb 100644
--- a/libjava/classpath/javax/swing/border/Border.java
+++ b/libjava/classpath/javax/swing/border/Border.java
@@ -77,9 +77,8 @@ public interface Border
* @param width the width of the available area for painting the border.
* @param height the height of the available area for painting the border.
*/
- void paintBorder(Component c, Graphics g,
- int x, int y, int width, int height);
-
+ void paintBorder(Component c, Graphics g, int x, int y, int width,
+ int height);
/**
* Measures the width of this border.
@@ -92,7 +91,6 @@ public interface Border
*/
Insets getBorderInsets(Component c);
-
/**
* Determines whether this border fills every pixel in its area
* when painting.
diff --git a/libjava/classpath/javax/swing/border/CompoundBorder.java b/libjava/classpath/javax/swing/border/CompoundBorder.java
index 2130a0e3447..998a9bab3bd 100644
--- a/libjava/classpath/javax/swing/border/CompoundBorder.java
+++ b/libjava/classpath/javax/swing/border/CompoundBorder.java
@@ -48,8 +48,7 @@ import java.awt.Insets;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class CompoundBorder
- extends AbstractBorder
+public class CompoundBorder extends AbstractBorder
{
/**
* Determined using the <code>serialver</code> tool
@@ -57,7 +56,6 @@ public class CompoundBorder
*/
static final long serialVersionUID = 9054540377030555103L;
-
/**
* The inside border, which is painted between the bordered
* Component and the outside border. It is valid for
@@ -65,7 +63,6 @@ public class CompoundBorder
*/
protected Border insideBorder;
-
/**
* The outside border, which is painted outside both the
* bordered Component and the inside border. It is valid for
@@ -73,7 +70,6 @@ public class CompoundBorder
*/
protected Border outsideBorder;
-
/**
* Constructs a CompoundBorder whose inside and outside borders
* are both <code>null</code>. While this does not really make
@@ -83,12 +79,11 @@ public class CompoundBorder
*
* @see EmptyBorder
*/
- public CompoundBorder ()
+ public CompoundBorder()
{
this (null, null);
}
-
/**
* Constructs a CompoundBorder with the specified inside and
* outside borders.
@@ -103,13 +98,12 @@ public class CompoundBorder
* component. It is acceptable to pass <code>null</code>, in
* which case no inside border is painted.
*/
- public CompoundBorder (Border outsideBorder, Border insideBorder)
+ public CompoundBorder(Border outsideBorder, Border insideBorder)
{
this.outsideBorder = outsideBorder;
this.insideBorder = insideBorder;
}
-
/**
* Determines whether or not this border is opaque. An opaque
* border fills every pixel in its area when painting. Partially
@@ -119,20 +113,18 @@ public class CompoundBorder
* @return <code>true</code> if both the inside and outside borders
* are opaque, or <code>false</code> otherwise.
*/
- public boolean isBorderOpaque ()
+ public boolean isBorderOpaque()
{
- /* While it would be safe to assume true for the opacity of
- * a null border, this behavior would not be according to
- * the API specification. Also, it is pathological to have
- * null borders anyway.
- */
+ // While it would be safe to assume true for the opacity of
+ // a null border, this behavior would not be according to
+ // the API specification. Also, it is pathological to have
+ // null borders anyway.
if ((insideBorder == null) || (outsideBorder == null))
return false;
return insideBorder.isBorderOpaque()
&& outsideBorder.isBorderOpaque();
}
-
/**
* Paints the compound border by first painting the outside border,
@@ -148,9 +140,9 @@ public class CompoundBorder
public void paintBorder(Component c, Graphics g,
int x, int y, int width, int height)
{
- /* If there is an outside border, paint it and reduce the
- * bounding box by its insets.
- */
+ // If there is an outside border, paint it and reduce the
+ // bounding box by its insets.
+ //
if (outsideBorder != null)
{
Insets outsideInsets;
@@ -161,9 +153,8 @@ public class CompoundBorder
x += outsideInsets.left;
y += outsideInsets.top;
- /* Reduce width and height by the respective extent of the
- * outside border.
- */
+ // Reduce width and height by the respective extent of the
+ // outside border.
width -= outsideInsets.left + outsideInsets.right;
height -= outsideInsets.top + outsideInsets.bottom;
}
@@ -172,7 +163,6 @@ public class CompoundBorder
insideBorder.paintBorder(c, g, x, y, width, height);
}
-
/**
* Changes the specified insets to the insets of this border,
* which is the sum of the insets of the inside and the outside
@@ -192,7 +182,7 @@ public class CompoundBorder
else
insets.left = insets.right = insets.top = insets.bottom = 0;
- /* If there is an outside border, add it to insets. */
+ // If there is an outside border, add it to insets.
if (outsideBorder != null)
{
borderInsets = outsideBorder.getBorderInsets(c);
@@ -202,7 +192,7 @@ public class CompoundBorder
insets.bottom += borderInsets.bottom;
}
- /* If there is an inside border, add it to insets. */
+ // If there is an inside border, add it to insets.
if (insideBorder != null)
{
borderInsets = insideBorder.getBorderInsets(c);
@@ -215,35 +205,31 @@ public class CompoundBorder
return insets;
}
-
/**
* Determines the insets of this border, which is the sum of the
* insets of the inside and the outside border.
*
* @param c the component in the center of this border.
*/
- public Insets getBorderInsets (Component c)
+ public Insets getBorderInsets(Component c)
{
- /* It is not clear why CompoundBorder does not simply inherit
- * the implementation from AbstractBorder. However, we want
- * to be compatible with the API specification, which overrides
- * the getBorderInsets(Component) method.
- */
+ // It is not clear why CompoundBorder does not simply inherit
+ // the implementation from AbstractBorder. However, we want
+ // to be compatible with the API specification, which overrides
+ // the getBorderInsets(Component) method.
return getBorderInsets (c, null);
}
-
/**
* Returns the outside border, which is painted outside both the
* bordered Component and the inside border. It is valid for the
* result to be <code>null</code>.
*/
- public Border getOutsideBorder ()
+ public Border getOutsideBorder()
{
return outsideBorder;
}
-
/**
* Returns the inside border, which is painted between the bordered
* Component and the outside border. It is valid for the result to
@@ -254,4 +240,3 @@ public class CompoundBorder
return insideBorder;
}
}
-
diff --git a/libjava/classpath/javax/swing/border/EmptyBorder.java b/libjava/classpath/javax/swing/border/EmptyBorder.java
index 0f3b7b6931c..c8e9c604469 100644
--- a/libjava/classpath/javax/swing/border/EmptyBorder.java
+++ b/libjava/classpath/javax/swing/border/EmptyBorder.java
@@ -53,8 +53,7 @@ import java.awt.Insets;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class EmptyBorder
- extends AbstractBorder
+public class EmptyBorder extends AbstractBorder
{
/**
* Determined using the <code>serialver</code> tool
@@ -142,6 +141,7 @@ public class EmptyBorder
public void paintBorder(Component c, Graphics g,
int x, int y, int width, int height)
{
+ // Nothing to do here.
}
diff --git a/libjava/classpath/javax/swing/border/EtchedBorder.java b/libjava/classpath/javax/swing/border/EtchedBorder.java
index 0bd76ff0fb6..22882b78cb1 100644
--- a/libjava/classpath/javax/swing/border/EtchedBorder.java
+++ b/libjava/classpath/javax/swing/border/EtchedBorder.java
@@ -56,8 +56,7 @@ import java.awt.Insets;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class EtchedBorder
- extends AbstractBorder
+public class EtchedBorder extends AbstractBorder
{
/**
* Determined using the <code>serialver</code> tool
@@ -199,8 +198,8 @@ public class EtchedBorder
* @param width the width of the available area for painting the border.
* @param height the height of the available area for painting the border.
*/
- public void paintBorder(Component c, Graphics g,
- int x, int y, int width, int height)
+ public void paintBorder(Component c, Graphics g, int x, int y, int width,
+ int height)
{
switch (etchType)
{
@@ -270,16 +269,14 @@ public class EtchedBorder
*/
public boolean isBorderOpaque()
{
- /* If the colors are to be drived from the enclosed Component's
- * background color, the border is guaranteed to be fully opaque
- * because Color.brighten() and Color.darken() always return an
- * opaque color.
- */
+ // If the colors are to be derived from the enclosed Component's
+ // background color, the border is guaranteed to be fully opaque
+ // because Color.brighten() and Color.darken() always return an
+ // opaque color.
return
((highlight == null) || (highlight.getAlpha() == 255))
&& ((shadow == null) || (shadow.getAlpha() == 255));
}
-
/**
* Returns the appearance of this EtchedBorder, which is either
@@ -310,8 +307,7 @@ public class EtchedBorder
else
return c.getBackground().brighter();
}
-
-
+
/**
* Returns the color that will be used for highlighted parts when
* painting the border, or <code>null</code> if that color will be
@@ -359,11 +355,11 @@ public class EtchedBorder
* Paints a two-pixel etching in two colors.
*
* <pre>
- * @@@@@@@@@@@.
- * @.........@. @ = color a
- * @. @. . = color b
- * @. @.
- * @@@@@@@@@@@.
+ * +++++++++++.
+ * +.........+. + = color a
+ * +. +. . = color b
+ * +. +.
+ * +++++++++++.
* ............</pre>
*
* @param g the graphics for painting.
@@ -374,9 +370,8 @@ public class EtchedBorder
* @param a one of the two colors.
* @param b the second of the two colors.
*/
- private static void paintEtchedBorder(Graphics g,
- int x, int y, int width, int height,
- Color a, Color b)
+ private static void paintEtchedBorder(Graphics g, int x, int y, int width,
+ int height, Color a, Color b)
{
Color oldColor;
@@ -387,11 +382,10 @@ public class EtchedBorder
try
{
- /* To understand this code, it might be helpful to look at the
- * images that are included with the JavaDoc. They are located
- * in the "doc-files" subdirectory. EtchedBorder-2.png might
- * be especially informative.
- */
+ // To understand this code, it might be helpful to look at the
+ // images that are included with the JavaDoc. They are located
+ // in the "doc-files" subdirectory. EtchedBorder-2.png might
+ // be especially informative.
g.setColor(a);
g.drawRect(0, 0, width - 1, height - 1);
@@ -408,4 +402,3 @@ public class EtchedBorder
}
}
}
-
diff --git a/libjava/classpath/javax/swing/border/LineBorder.java b/libjava/classpath/javax/swing/border/LineBorder.java
index c34e38c5789..36abddd915d 100644
--- a/libjava/classpath/javax/swing/border/LineBorder.java
+++ b/libjava/classpath/javax/swing/border/LineBorder.java
@@ -50,8 +50,7 @@ import java.awt.Insets;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class LineBorder
- extends AbstractBorder
+public class LineBorder extends AbstractBorder
{
/**
* Determined using the <code>serialver</code> tool
@@ -71,7 +70,7 @@ public class LineBorder
/**
* A shared instance of a gray, one pixel thick, plain LineBorder.
* The singleton object is lazily created by {@link
- * #createBlackGrayBorder()} upon its first invocation.
+ * #createGrayLineBorder()} upon its first invocation.
*/
private static LineBorder grayLineBorder;
@@ -213,29 +212,27 @@ public class LineBorder
{
g.setColor(lineColor);
- /* If width and height were not adjusted, the border would
- * appear one pixel too large in both directions.
- */
+ // If width and height were not adjusted, the border would
+ // appear one pixel too large in both directions.
width -= 1;
height -= 1;
- /* Blurred, too large appearance
- * -----------------------------
- * While Java 2D has introduced line strokes of arbitrary width,
- * it seems desirable to keep this code independent of Java 2D.
- * Therefore, multiple nested rectangles (or rounded rectangles)
- * are drawn in order to simulate a line whose thickness is
- * greater than one pixel.
- *
- * This hack causes a blurred appearance when anti-aliasing is
- * on. Interestingly enough, though, the Sun JDK 1.3.1 (at least
- * on MacOS X 10.1.5) shows exactly the same appearance under
- * this condition. It thus seems likely that Sun does the same
- * hack for simulating thick lines. For this reason, the
- * blurred appearance seems acceptable -- especially since GNU
- * Classpath tries to be compatible with the Sun reference
- * implementation.
- */
+ // Blurred, too large appearance
+ // -----------------------------
+ // While Java 2D has introduced line strokes of arbitrary width,
+ // it seems desirable to keep this code independent of Java 2D.
+ // Therefore, multiple nested rectangles (or rounded rectangles)
+ // are drawn in order to simulate a line whose thickness is
+ // greater than one pixel.
+ //
+ // This hack causes a blurred appearance when anti-aliasing is
+ // on. Interestingly enough, though, the Sun JDK 1.3.1 (at least
+ // on MacOS X 10.1.5) shows exactly the same appearance under
+ // this condition. It thus seems likely that Sun does the same
+ // hack for simulating thick lines. For this reason, the
+ // blurred appearance seems acceptable -- especially since GNU
+ // Classpath tries to be compatible with the Sun reference
+ // implementation.
for (int i = 0; i < thickness; i++)
{
if (roundedCorners)
@@ -340,4 +337,3 @@ public class LineBorder
return (!roundedCorners) && (lineColor.getAlpha() == 255);
}
}
-
diff --git a/libjava/classpath/javax/swing/border/MatteBorder.java b/libjava/classpath/javax/swing/border/MatteBorder.java
index f7ff1ca01c3..4d5b8c25360 100644
--- a/libjava/classpath/javax/swing/border/MatteBorder.java
+++ b/libjava/classpath/javax/swing/border/MatteBorder.java
@@ -54,8 +54,7 @@ import javax.swing.Icon;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class MatteBorder
- extends EmptyBorder
+public class MatteBorder extends EmptyBorder
{
/**
* Determined using the <code>serialver</code> tool
@@ -401,4 +400,3 @@ public class MatteBorder
}
}
}
-
diff --git a/libjava/classpath/javax/swing/border/SoftBevelBorder.java b/libjava/classpath/javax/swing/border/SoftBevelBorder.java
index 379ecb65a35..028fd00e021 100644
--- a/libjava/classpath/javax/swing/border/SoftBevelBorder.java
+++ b/libjava/classpath/javax/swing/border/SoftBevelBorder.java
@@ -55,8 +55,7 @@ import java.awt.Insets;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class SoftBevelBorder
- extends BevelBorder
+public class SoftBevelBorder extends BevelBorder
{
/**
* Determined using the <code>serialver</code> tool
@@ -264,10 +263,10 @@ public class SoftBevelBorder
* Paints a soft bevel in four colors.
*
* <pre>
- * @@@@@@@@@@@.
- * @@.........# @ = color a
- * @.. # . = color b
- * @. # X = color c
+ * +++++++++++.
+ * ++.........# + = color a
+ * +.. # . = color b
+ * +. # X = color c
* .. X# # = color d
* . ##########</pre>
*
@@ -326,4 +325,3 @@ public class SoftBevelBorder
}
}
}
-
diff --git a/libjava/classpath/javax/swing/border/TitledBorder.java b/libjava/classpath/javax/swing/border/TitledBorder.java
index ceae2b1c9e3..8d3ee13d4bb 100644
--- a/libjava/classpath/javax/swing/border/TitledBorder.java
+++ b/libjava/classpath/javax/swing/border/TitledBorder.java
@@ -1,5 +1,5 @@
/* TitledBorder.java --
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -46,6 +46,9 @@ import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Shape;
+import java.awt.font.FontRenderContext;
+import java.awt.font.LineMetrics;
+import java.awt.geom.AffineTransform;
import javax.swing.UIManager;
@@ -55,8 +58,7 @@ import javax.swing.UIManager;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class TitledBorder
- extends AbstractBorder
+public class TitledBorder extends AbstractBorder
{
/**
* A value for the <code>titlePosition</code> property that vertically
@@ -301,7 +303,7 @@ public class TitledBorder
public TitledBorder(String title)
{
this(/* border */ null,
- title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION,
+ title, LEADING, TOP,
/* titleFont */ null, /* titleColor */ null);
}
@@ -314,7 +316,7 @@ public class TitledBorder
*/
public TitledBorder(Border border)
{
- this(border, /* title */ "", DEFAULT_JUSTIFICATION, DEFAULT_POSITION,
+ this(border, /* title */ "", LEADING, TOP,
/* titleFont */ null, /* titleColor */ null);
}
@@ -330,7 +332,7 @@ public class TitledBorder
*/
public TitledBorder(Border border, String title)
{
- this(border, title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION,
+ this(border, title, LEADING, TOP,
/* titleFont */ null, /* titleColor */ null);
}
@@ -504,7 +506,7 @@ public class TitledBorder
public void paint(Graphics g)
{
if (b != null)
- b.paintBorder(c, g, x, y, width - 1, height - 1);
+ b.paintBorder(c, g, x, y, width, height);
}
@@ -562,7 +564,7 @@ public class TitledBorder
if (stripeHeight > 0)
{
paint(g, x, holeY, holeX - x, stripeHeight); // patches #2 and #3
- paint(g, holeX + holeWidth, holeY, width - (holeX + holeWidth), stripeHeight);
+ paint(g, holeX + holeWidth, holeY, x + width - (holeX + holeWidth), stripeHeight);
}
stripeHeight = height - (holeY - y + holeHeight);
@@ -574,16 +576,16 @@ public class TitledBorder
BorderPainter bp;
int textX, textY, borderWidth, borderHeight;
- borderWidth = width - (mes.borderSpacing.left + mes.borderSpacing.right);
- borderHeight = height - (mes.borderSpacing.top + mes.borderSpacing.bottom);
+ borderWidth = width - (mes.outerSpacing.left + mes.outerSpacing.right);
+ borderHeight = height - (mes.outerSpacing.top + mes.outerSpacing.bottom);
bp = new BorderPainter(c, getBorder(),
- x + mes.borderSpacing.left, y + mes.borderSpacing.top,
+ x + mes.outerSpacing.left, y + mes.outerSpacing.top,
borderWidth, borderHeight);
switch (getRealTitleJustification(c))
{
case LEFT:
- textX = x + TEXT_INSET_H;
+ textX = x + EDGE_SPACING + TEXT_INSET_H;
break;
case CENTER:
@@ -601,21 +603,22 @@ public class TitledBorder
switch (titlePosition)
{
case ABOVE_TOP:
- textY = y;
+ textY = y + EDGE_SPACING;
break;
case TOP:
case DEFAULT_POSITION:
default:
- textY = y + mes.borderSpacing.top + mes.borderInsets.top - mes.textAscent;
+ textY = y + mes.outerSpacing.top + mes.borderInsets.top - mes.textAscent
+ + mes.lineHeight;
break;
case BELOW_TOP:
- textY = y + mes.borderSpacing.top + mes.borderInsets.top + TEXT_SPACING;
+ textY = y + mes.outerSpacing.top + mes.borderInsets.top + TEXT_SPACING;
break;
case ABOVE_BOTTOM:
- textY = y + height - mes.borderSpacing.bottom - mes.borderInsets.bottom
+ textY = y + height - mes.outerSpacing.bottom - mes.borderInsets.bottom
- TEXT_SPACING - (mes.textAscent + mes.textDescent);
break;
@@ -640,8 +643,8 @@ public class TitledBorder
g.setFont(oldFont);
g.setColor(oldColor);
}
- bp.paintExcept(g, textX - 2, textY,
- mes.textWidth + 2, mes.textAscent + mes.textDescent);
+ bp.paintExcept(g, textX, textY,
+ mes.textWidth, mes.textAscent + mes.textDescent);
}
}
@@ -998,39 +1001,63 @@ public class TitledBorder
m.trimmedText = null;
}
- m.textAscent = fmet.getAscent();
- m.textDescent = fmet.getDescent();
if (m.trimmedText != null)
- m.textWidth = fmet.stringWidth(m.trimmedText) + 3;
+ {
+ m.textAscent = fmet.getAscent();
+ m.textDescent = fmet.getDescent() + fmet.getLeading();
+
+ FontRenderContext frc = new FontRenderContext(new AffineTransform(),
+ false, false);
+ LineMetrics lmet = m.font.getLineMetrics(m.trimmedText, 0,
+ m.trimmedText.length(), frc);
+ m.lineHeight = (int) lmet.getStrikethroughOffset();
+
+ // Fallback in case that LineMetrics is not available/working.
+ if (m.lineHeight == 0)
+ m.lineHeight = (int) (0.3333 * (double) m.textAscent);
+ m.textWidth = fmet.stringWidth(m.trimmedText) + 3;
+ }
+ else
+ {
+ m.textAscent = 0;
+ m.textDescent = 0;
+ }
- m.edgeSpacing = new Insets(EDGE_SPACING, EDGE_SPACING, EDGE_SPACING, EDGE_SPACING);
- m.borderSpacing = new Insets(0, 0, 0, 0);
+ m.innerSpacing = new Insets(EDGE_SPACING, EDGE_SPACING, EDGE_SPACING,
+ EDGE_SPACING);
+ m.outerSpacing = new Insets(EDGE_SPACING, EDGE_SPACING, EDGE_SPACING,
+ EDGE_SPACING);
switch (titlePosition)
{
case ABOVE_TOP:
- m.borderSpacing.top += m.textAscent + m.textDescent + TEXT_SPACING;
+ m.outerSpacing.top += m.textAscent + m.textDescent + TEXT_SPACING;
break;
+ case TOP:
+ m.outerSpacing.top += m.textDescent + m.lineHeight;
+ m.innerSpacing.top += m.textAscent - m.lineHeight;
+ break;
+
case BELOW_TOP:
- m.edgeSpacing.top += m.textAscent + m.textDescent + TEXT_SPACING;
+ m.innerSpacing.top += m.textAscent + m.textDescent + TEXT_SPACING;
break;
case ABOVE_BOTTOM:
- m.edgeSpacing.bottom += m.textAscent + m.textDescent + TEXT_SPACING;
+ m.innerSpacing.bottom += m.textAscent + m.textDescent + TEXT_SPACING;
break;
case BOTTOM:
- m.edgeSpacing.bottom += Math.max(m.textAscent - m.borderInsets.bottom, 0);
- m.borderSpacing.bottom += m.textDescent;
+ m.innerSpacing.bottom += Math.max(m.textAscent - m.lineHeight, 0);
+ m.outerSpacing.bottom += m.textDescent + m.lineHeight;
break;
case BELOW_BOTTOM:
- m.borderSpacing.bottom += m.textAscent + m.textDescent + TEXT_SPACING;
+ m.outerSpacing.bottom += m.textAscent + m.textDescent;
break;
default:
- m.borderSpacing.top += m.textAscent;
+ m.outerSpacing.top += m.textAscent;
}
return m;
@@ -1053,7 +1080,7 @@ public class TitledBorder
* which means that the font is to be retrieved from the current
* LookAndFeel. In this case, this <code>font</code> field will
* contain the result of the retrieval. Therefore, it is safe
- * to assume that his <code>font</code> field will never have
+ * to assume that this <code>font</code> field will never have
* a <code>null</code> value.
*/
Font font;
@@ -1072,6 +1099,11 @@ public class TitledBorder
*/
int textDescent;
+ /**
+ * The number of pixels between the base line and the height where
+ * a strike-through would be drawn.
+ */
+ int lineHeight;
/**
* The title text after removing leading and trailing white space
@@ -1088,7 +1120,7 @@ public class TitledBorder
/**
- * The border that constitues the interior border
+ * The border that constitutes the interior border
* underneath the title text.
*/
Border border;
@@ -1097,8 +1129,7 @@ public class TitledBorder
/**
* The distance between the TitledBorder and the interior border.
*/
- Insets borderSpacing;
-
+ Insets outerSpacing;
/**
* The width of the interior border, as returned by
@@ -1111,7 +1142,7 @@ public class TitledBorder
* The distance between the interior border and the nested
* Component for which this TitledBorder is a border.
*/
- Insets edgeSpacing;
+ Insets innerSpacing;
/**
@@ -1130,10 +1161,10 @@ public class TitledBorder
{
if (i == null)
i = new Insets(0, 0, 0, 0);
- i.left = borderSpacing.left + borderInsets.left + edgeSpacing.left;
- i.right = borderSpacing.right + borderInsets.right + edgeSpacing.right;
- i.top = borderSpacing.top + borderInsets.top + edgeSpacing.top;
- i.bottom = borderSpacing.bottom + borderInsets.bottom + edgeSpacing.bottom;
+ i.left = outerSpacing.left + borderInsets.left + innerSpacing.left;
+ i.right = outerSpacing.right + borderInsets.right + innerSpacing.right;
+ i.top = outerSpacing.top + borderInsets.top + innerSpacing.top;
+ i.bottom = outerSpacing.bottom + borderInsets.bottom + innerSpacing.bottom;
return i;
}
@@ -1148,7 +1179,8 @@ public class TitledBorder
Insets insets;
insets = getContentInsets(null);
- width = Math.max(insets.left + insets.right, textWidth + 2 * TEXT_INSET_H);
+ width = Math.max(insets.left + insets.right, textWidth + 2
+ * TEXT_INSET_H);
return new Dimension(width, insets.top + insets.bottom);
}
}
diff --git a/libjava/classpath/javax/swing/colorchooser/AbstractColorChooserPanel.java b/libjava/classpath/javax/swing/colorchooser/AbstractColorChooserPanel.java
index d55346aaf2c..efb527725fa 100644
--- a/libjava/classpath/javax/swing/colorchooser/AbstractColorChooserPanel.java
+++ b/libjava/classpath/javax/swing/colorchooser/AbstractColorChooserPanel.java
@@ -1,5 +1,5 @@
/* AbstractColorChooserPanel.java --
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -64,7 +64,8 @@ public abstract class AbstractColorChooserPanel extends JPanel
*/
public AbstractColorChooserPanel()
{
- } // AbstractColorChooserPanel()
+ // Nothing to do here.
+ }
/**
* This method returns the name displayed in the tab for this chooser panel.
@@ -74,6 +75,36 @@ public abstract class AbstractColorChooserPanel extends JPanel
public abstract String getDisplayName();
/**
+ * Returns the key code for the mnemonic for this panel. This method returns
+ * zero to indicate no mnemonic, subclasses can override this.
+ *
+ * @return <code>0</code>, to indicate no mnemonic key code.
+ *
+ * @see #getDisplayedMnemonicIndex()
+ * @since 1.4
+ */
+ public int getMnemonic()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the index of the character in the display name that is the
+ * mnemonic. This method returns <code>-1</code> to indicate no mnemonic,
+ * subclasses can override.
+ *
+ * @return <code>-1</code>, to indicate no mnemonic.
+ *
+ * @see #getDisplayName()
+ * @see #getMnemonic()
+ * @since 1.4
+ */
+ public int getDisplayedMnemonicIndex()
+ {
+ return -1;
+ }
+
+ /**
* This method updates the chooser panel when the JColorChooser's color has
* changed.
*/
diff --git a/libjava/classpath/javax/swing/colorchooser/ColorChooserComponentFactory.java b/libjava/classpath/javax/swing/colorchooser/ColorChooserComponentFactory.java
index 77e319c70e4..923ea531ffb 100644
--- a/libjava/classpath/javax/swing/colorchooser/ColorChooserComponentFactory.java
+++ b/libjava/classpath/javax/swing/colorchooser/ColorChooserComponentFactory.java
@@ -53,7 +53,8 @@ public class ColorChooserComponentFactory
*/
private ColorChooserComponentFactory()
{
- } // ColorChooserComponentFactory()
+ // Nothing to do here.
+ }
/**
* This method returns the three default chooser panels to be used in
diff --git a/libjava/classpath/javax/swing/colorchooser/DefaultSwatchChooserPanel.java b/libjava/classpath/javax/swing/colorchooser/DefaultSwatchChooserPanel.java
index f28af4cac7c..ff3436808ec 100644
--- a/libjava/classpath/javax/swing/colorchooser/DefaultSwatchChooserPanel.java
+++ b/libjava/classpath/javax/swing/colorchooser/DefaultSwatchChooserPanel.java
@@ -587,6 +587,7 @@ class DefaultSwatchChooserPanel extends AbstractColorChooserPanel
*/
public void addLayoutComponent(String name, Component comp)
{
+ // Nothing to do here.
}
/**
@@ -634,6 +635,7 @@ class DefaultSwatchChooserPanel extends AbstractColorChooserPanel
*/
public void removeLayoutComponent(Component comp)
{
+ // Nothing to do here.
}
/**
@@ -786,6 +788,7 @@ class DefaultSwatchChooserPanel extends AbstractColorChooserPanel
*/
public void updateChooser()
{
+ // Nothing to do here yet.
}
/**
diff --git a/libjava/classpath/javax/swing/event/EventListenerList.java b/libjava/classpath/javax/swing/event/EventListenerList.java
index 3b9f4c807de..ee3f220f4d5 100644
--- a/libjava/classpath/javax/swing/event/EventListenerList.java
+++ b/libjava/classpath/javax/swing/event/EventListenerList.java
@@ -119,6 +119,7 @@ public class EventListenerList
*/
public EventListenerList()
{
+ // Nothing to do here.
}
diff --git a/libjava/classpath/javax/swing/event/InternalFrameAdapter.java b/libjava/classpath/javax/swing/event/InternalFrameAdapter.java
index a2878e76e79..dfa88c3d4fd 100644
--- a/libjava/classpath/javax/swing/event/InternalFrameAdapter.java
+++ b/libjava/classpath/javax/swing/event/InternalFrameAdapter.java
@@ -39,75 +39,88 @@ exception statement from your version. */
package javax.swing.event;
/**
- * InternalFrameAdapter
+ * InternalFrameAdapter.
+ *
* @author Andrew Selkirk
*/
public abstract class InternalFrameAdapter implements InternalFrameListener
{
-
- //-------------------------------------------------------------
- // Initialization ---------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * InternalFrameAdapter constructor
- */
- public InternalFrameAdapter() {
- } // InternalFrameAdapter()
-
-
- //-------------------------------------------------------------
- // Interface: InternalFrameListener ---------------------------
- //-------------------------------------------------------------
+ /**
+ * InternalFrameAdapter constructor.
+ */
+ public InternalFrameAdapter()
+ {
+ // Nothing to do here.
+ }
- /**
- * Internal frame activated
- * @param event Internal frame event
- */
- public void internalFrameActivated(InternalFrameEvent event) {
- } // internalFrameActivated()
-
- /**
- * Internal frame closed
- * @param event Internal frame event
- */
- public void internalFrameClosed(InternalFrameEvent event) {
- } // internalFrameClosed()
-
- /**
- * Internal frame closing
- * @param event Internal frame event
- */
- public void internalFrameClosing(InternalFrameEvent event) {
- } // internalFrameClosing()
-
- /**
- * Internal frame deactivated
- * @param event Internal frame event
- */
- public void internalFrameDeactivated(InternalFrameEvent event) {
- } // internalFrameDeactivated()
-
- /**
- * Internal frame deiconified
- * @param event Internal frame event
- */
- public void internalFrameDeiconified(InternalFrameEvent event) {
- } // internalFrameDeiconified()
-
- /**
- * Internal frame iconified
- * @param event Internal frame event
- */
- public void internalFrameIconified(InternalFrameEvent event) {
- } // internalFrameIconified()
-
- /**
- * Internal frame opened
- * @param event Internal frame event
- */
- public void internalFrameOpened(InternalFrameEvent event) {
- } // internalFrameOpened()
-
-
-} // InternalFrameAdapter
+ /**
+ * Internal frame activated.
+ *
+ * @param event internal frame event
+ */
+ public void internalFrameActivated(InternalFrameEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Internal frame closed.
+ *
+ * @param event internal frame event
+ */
+ public void internalFrameClosed(InternalFrameEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Internal frame closing.
+ *
+ * @param event internal frame event
+ */
+ public void internalFrameClosing(InternalFrameEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Internal frame deactivated.
+ *
+ * @param event internal frame event
+ */
+ public void internalFrameDeactivated(InternalFrameEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Internal frame deiconified.
+ *
+ * @param event internal frame event
+ */
+ public void internalFrameDeiconified(InternalFrameEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Internal frame iconified.
+ *
+ * @param event internal frame event
+ */
+ public void internalFrameIconified(InternalFrameEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Internal frame opened.
+ *
+ * @param event internal frame event
+ */
+ public void internalFrameOpened(InternalFrameEvent event)
+ {
+ // Nothing to do here.
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/event/ListDataListener.java b/libjava/classpath/javax/swing/event/ListDataListener.java
index 7ce17d86fa6..f42777d09d6 100644
--- a/libjava/classpath/javax/swing/event/ListDataListener.java
+++ b/libjava/classpath/javax/swing/event/ListDataListener.java
@@ -1,5 +1,5 @@
/* ListDataListener.java --
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,33 +37,46 @@ exception statement from your version. */
package javax.swing.event;
-// Imports
import java.util.EventListener;
+import javax.swing.ListModel;
+
/**
- * ListDataListener public interface
+ * A <code>ListDataListener</code> can register with a {@link ListModel} and
+ * receive notification of updates to the model.
+ *
* @author Andrew Selkirk
* @author Ronald Veldema
*/
-public interface ListDataListener extends EventListener {
-
- /**
- * Contents Changed
- * @param event ListDataEvent Event
- */
- void contentsChanged(ListDataEvent event);
+public interface ListDataListener extends EventListener
+{
- /**
- * Interval Added
- * @param event ListDataEvent Event
- */
- void intervalAdded(ListDataEvent event);
+ /**
+ * Notifies the listener that the contents of the list have changed
+ * in some way. This method will be called if the change cannot be
+ * notified via the {@link #intervalAdded(ListDataEvent)} or the
+ * {@link #intervalRemoved(ListDataEvent)} methods.
+ *
+ * @param event the event.
+ */
+ void contentsChanged(ListDataEvent event);
- /**
- * Interval Removed
- * @param event ListDataEvent Event
- */
- void intervalRemoved(ListDataEvent event);
+ /**
+ * Notifies the listener that one or more items have been added to the
+ * list. The <code>event</code> argument can supply the indices for the
+ * range of items added.
+ *
+ * @param event the event.
+ */
+ void intervalAdded(ListDataEvent event);
+ /**
+ * Notifies the listener that one or more items have been removed from
+ * the list. The <code>event</code> argument can supply the indices for
+ * the range of items removed.
+ *
+ * @param event the event.
+ */
+ void intervalRemoved(ListDataEvent event);
-} // ListDataListener
+}
diff --git a/libjava/classpath/javax/swing/event/MouseInputListener.java b/libjava/classpath/javax/swing/event/MouseInputListener.java
index 3c3ca2347fe..3d879b9e746 100644
--- a/libjava/classpath/javax/swing/event/MouseInputListener.java
+++ b/libjava/classpath/javax/swing/event/MouseInputListener.java
@@ -37,16 +37,17 @@ exception statement from your version. */
package javax.swing.event;
-// Imports
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
/**
- * MouseInputListener public interface
+ * MouseInputListener public interface.
+ *
* @author Andrew Selkirk
*/
public interface MouseInputListener extends MouseListener,
- MouseMotionListener {
-
-} // MouseInputListener
-
+ MouseMotionListener
+{
+ // This interface only pulls together MouseListener and MouseMotionListener
+ // without adding any methods on its own.
+}
diff --git a/libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java b/libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java
index 408ca957e95..7e8ff0dc2e9 100644
--- a/libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java
+++ b/libjava/classpath/javax/swing/event/SwingPropertyChangeSupport.java
@@ -289,10 +289,9 @@ public final class SwingPropertyChangeSupport
int index;
PropertyChangeListener listener;
- // Check Values if they are equal
- if (event.getOldValue() == null && event.getNewValue() == null ||
- (event.getOldValue() != null && event.getNewValue() != null &&
- event.getOldValue().equals(event.getNewValue())))
+ // if the old and new values are non-null and equal, don't notify listeners
+ if (event.getOldValue() != null && event.getNewValue() != null &&
+ event.getOldValue().equals(event.getNewValue()))
return;
// Process Main Listener List
diff --git a/libjava/classpath/javax/swing/event/TreeModelEvent.java b/libjava/classpath/javax/swing/event/TreeModelEvent.java
index a217e3b4053..8fa28a7eadb 100644
--- a/libjava/classpath/javax/swing/event/TreeModelEvent.java
+++ b/libjava/classpath/javax/swing/event/TreeModelEvent.java
@@ -55,12 +55,12 @@ public class TreeModelEvent extends EventObject {
/**
* childIndices
*/
- protected int[] childIndices = new int[0];
+ protected int[] childIndices = null;
/**
* children
*/
- protected Object[] children = new Object[0];
+ protected Object[] children = null;
/**
* path
@@ -164,7 +164,9 @@ public class TreeModelEvent extends EventObject {
* @returns String representation
*/
public String toString() {
- return null; // TODO
+ return getClass() + " [Source: " + getSource() + ", TreePath: " + getTreePath() +
+ ", Child Indicies: " + getChildIndices() + ", Children: " + getChildren() +
+ ", Path: " + getPath() +"]";
} // toString()
diff --git a/libjava/classpath/javax/swing/filechooser/FileFilter.java b/libjava/classpath/javax/swing/filechooser/FileFilter.java
index 42770d98186..ecfa54b5814 100644
--- a/libjava/classpath/javax/swing/filechooser/FileFilter.java
+++ b/libjava/classpath/javax/swing/filechooser/FileFilter.java
@@ -1,5 +1,5 @@
/* FileFilter.java --
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -40,41 +40,46 @@ package javax.swing.filechooser;
import java.io.File;
+import javax.swing.JFileChooser;
+
/**
- * FileFilter
+ * The base class for filters that control the visibility of files in the
+ * {@link JFileChooser} component.
+ *
+ * @see JFileChooser#addChoosableFileFilter(FileFilter)
+ *
* @author Andrew Selkirk
- * @version 1.0
*/
-public abstract class FileFilter {
-
- //-------------------------------------------------------------
- // Initialization ---------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * Constructor FileFilter
- */
- public FileFilter() {
- // TODO
- } // FileFilter()
-
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * accept
- * @param file TODO
- * @returns boolean
- */
- public abstract boolean accept(File file);
-
- /**
- * getDescription
- * @returns String
- */
- public abstract String getDescription();
-
-
-} // FileFilter
+public abstract class FileFilter
+{
+
+ /**
+ * Default constructor.
+ */
+ public FileFilter()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns <code>true</code> if the specified file matches the filter, and
+ * <code>false</code> otherwise.
+ *
+ * @param file the file.
+ *
+ * @returns A boolean.
+ */
+ public abstract boolean accept(File file);
+
+ /**
+ * Returns a description of the files that will be selected by the filter
+ * (for example, "Java source files"). This description will usually be
+ * displayed on the {@link JFileChooser} component, often in a combo box that
+ * is used to select the appropriate filter (in cases where more than one
+ * filter is available).
+ *
+ * @returns A description of the filter.
+ */
+ public abstract String getDescription();
+
+}
diff --git a/libjava/classpath/javax/swing/filechooser/FileSystemView.java b/libjava/classpath/javax/swing/filechooser/FileSystemView.java
index ffa41ca07de..f51b745c892 100644
--- a/libjava/classpath/javax/swing/filechooser/FileSystemView.java
+++ b/libjava/classpath/javax/swing/filechooser/FileSystemView.java
@@ -40,21 +40,27 @@ package javax.swing.filechooser;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+
import javax.swing.Icon;
+import javax.swing.JFileChooser;
/**
- * DOCUMENT ME!
+ * The base class providing a view of the file system for use by the
+ * {@link JFileChooser} component.
*/
public abstract class FileSystemView
{
+ /** The instance returned by {@link #getFileSystemView()}. */
+ private static FileSystemView defaultFileSystemView;
+
/**
- * DOCUMENT ME!
+ * Creates a new file object with the given name in the specified directory.
*
- * @param dir DOCUMENT ME!
- * @param filename DOCUMENT ME!
+ * @param dir the directory (<code>null</code> permitted).
+ * @param filename the file name.
*
- * @return DOCUMENT ME!
+ * @return A new file object.
*/
public File createFileObject(File dir, String filename)
{
@@ -62,11 +68,11 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Creates a new file object from the specified path.
*
- * @param path DOCUMENT ME!
+ * @param path the path.
*
- * @return DOCUMENT ME!
+ * @return A new file object.
*/
public File createFileObject(String path)
{
@@ -89,13 +95,16 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Creates a new folder with a unique name in the specified directory and
+ * returns a {@link File} object representing the new directory.
*
- * @param containingDir DOCUMENT ME!
+ * @param containingDir the directory to contain the new folder
+ * (<code>null</code> not permitted).
*
- * @return DOCUMENT ME!
+ * @return A {@link File} object representing the new directory.
*
- * @throws IOException DOCUMENT ME!
+ * @throws IOException if an exception occurs while creating the new
+ * directory.
*/
public abstract File createNewFolder(File containingDir)
throws IOException;
@@ -115,9 +124,9 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns the default directory.
*
- * @return DOCUMENT ME!
+ * @return The default directory.
*/
public File getDefaultDirectory()
{
@@ -125,12 +134,16 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns an array containing the files in the given directory. The
+ * <code>useFileHiding</code> controls whether or not hidden files are
+ * included in the result.
*
- * @param dir DOCUMENT ME!
- * @param useFileHiding DOCUMENT ME!
+ * @param dir the directory (if <code>null</code>
+ * @param useFileHiding a flag that controls whether or not hidden files are
+ * included in the result (pass in <code>true</code> to
+ * exclude hidden files).
*
- * @return DOCUMENT ME!
+ * @return The files in the given directory (possibly <code>null</code>).
*/
public File[] getFiles(File dir, boolean useFileHiding)
{
@@ -143,31 +156,34 @@ public abstract class FileSystemView
for (int i = 0; i < files.length; i++)
if (! files[i].isHidden())
trim.add(files[i]);
- File[] value = (File[]) trim.toArray(new File[0]);
+ File[] value = (File[]) trim.toArray(new File[trim.size()]);
return value;
}
/**
- * DOCUMENT ME!
+ * Returns a default {@link FileSystemView} appropriate for the platform.
*
- * @return DOCUMENT ME!
+ * @return A default {@link FileSystemView} appropriate for the platform.
*/
public static FileSystemView getFileSystemView()
{
- if (File.separator.equals("/"))
- return new UnixFileSystemView();
-
- // else if (File.Separator.equals("\"))
- // return new Win32FileSystemView();
- // else
- // return new GenericFileSystemView();
- return null;
+ if (defaultFileSystemView == null)
+ {
+ if (File.separator.equals("/"))
+ defaultFileSystemView = new UnixFileSystemView();
+ // FIXME: need to implement additional views
+ // else if (File.Separator.equals("\"))
+ // return new Win32FileSystemView();
+ // else
+ // return new GenericFileSystemView();
+ }
+ return defaultFileSystemView;
}
/**
- * DOCUMENT ME!
+ * Returns the home directory for the current user.
*
- * @return DOCUMENT ME!
+ * @return The home directory for the current user.
*/
public File getHomeDirectory()
{
@@ -175,11 +191,12 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns the parent directory for the given file/directory.
*
- * @param f DOCUMENT ME!
+ * @param f the file/directory.
*
- * @return DOCUMENT ME!
+ * @return The parent directory (or <code>null</code> if there is no parent
+ * directory).
*/
public File getParentDirectory(File f)
{
@@ -189,9 +206,14 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
+ * Returns an array containing the file system roots. On Unix-like platforms,
+ * this array will contain just a single item ("/"), while other platforms
+ * may return multiple roots.
+ * <p>
+ * This method is implemented to return <code>null</code>, subclasses must
+ * override this method.
+ *
+ * @return An array containing the file system roots.
*/
public File[] getRoots()
{
@@ -200,11 +222,13 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns the name of a file as it would be displayed by the underlying
+ * system. This implementation returns <code>null</code>, subclasses must
+ * override.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return <code>null</code>.
*/
public String getSystemDisplayName(File f)
{
@@ -212,11 +236,13 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns the icon that would be displayed for the given file by the
+ * underlying system. This implementation returns <code>null</code>,
+ * subclasses must override.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return <code>null</code>.
*/
public Icon getSystemIcon(File f)
{
@@ -224,11 +250,13 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns the type description of a file that would be displayed by the
+ * underlying system. This implementation returns <code>null</code>,
+ * subclasses must override.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return <code>null</code>.
*/
public String getSystemTypeDescription(File f)
{
@@ -248,11 +276,13 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if the given directory represents a disk
+ * drive, and <code>false</code> otherwise. This default implementation
+ * always returns <code>false</code>.
*
- * @param dir DOCUMENT ME!
+ * @param dir the directory.
*
- * @return DOCUMENT ME!
+ * @return <code>false</code>.
*/
public boolean isDrive(File dir)
{
@@ -260,11 +290,13 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if <code>f</code> is a file or directory, and
+ * <code>false</code> otherwise.
*
- * @param f DOCUMENT ME!
+ * @param f the file/directory.
*
- * @return DOCUMENT ME!
+ * @return <code>true</code> if <code>f</code> is a file or directory, and
+ * <code>false</code> otherwise.
*/
public boolean isFileSystem(File f)
{
@@ -272,11 +304,13 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if the given directory is a file system root,
+ * and <code>false</code> otherwise.
*
- * @param dir DOCUMENT ME!
+ * @param dir the directory.
*
- * @return DOCUMENT ME!
+ * @return <code>true</code> if the given directory is a file system root,
+ * and <code>false</code> otherwise.
*/
public boolean isFileSystemRoot(File dir)
{
@@ -291,11 +325,13 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if the given directory represents a floppy
+ * drive, and <code>false</code> otherwise. This default implementation
+ * always returns <code>false</code>.
*
- * @param dir DOCUMENT ME!
+ * @param dir the directory.
*
- * @return DOCUMENT ME!
+ * @return <code>false</code>.
*/
public boolean isFloppyDrive(File dir)
{
@@ -303,11 +339,13 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if the given file is hidden, and
+ * <code>false</code> otherwise.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return <code>true</code> if the given file is hidden, and
+ * <code>false</code> otherwise.
*/
public boolean isHiddenFile(File f)
{
@@ -315,12 +353,14 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if <code>folder</code> is the parent of
+ * <code>file</code>, and <code>false</code> otherwise.
*
- * @param folder DOCUMENT ME!
- * @param file DOCUMENT ME!
+ * @param folder the folder (<code>null</code> not permitted).
+ * @param file the file (<code>null</code> not permitted).
*
- * @return DOCUMENT ME!
+ * @return <code>true</code> if <code>folder</code> is the parent of
+ * <code>file</code>, and <code>false</code> otherwise.
*/
public boolean isParent(File folder, File file)
{
@@ -344,11 +384,14 @@ public abstract class FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if the file is traversable, and
+ * <code>false</code> otherwise. Here, all directories are considered
+ * traversable, and files are considered non-traversable.
*
- * @param f DOCUMENT ME!
+ * @param f the file or directory (<code>null</code> not permitted).
*
- * @return DOCUMENT ME!
+ * @return <code>true</code> if the file is traversable, and
+ * <code>false</code> otherwise.
*/
public Boolean isTraversable(File f)
{
@@ -356,6 +399,6 @@ public abstract class FileSystemView
// traversable. (No files are listed when you traverse the directory)
// My best guess is that as long as it's a directory, the file is
// traversable.
- return new Boolean(f.isDirectory());
+ return Boolean.valueOf(f.isDirectory());
}
}
diff --git a/libjava/classpath/javax/swing/filechooser/FileView.java b/libjava/classpath/javax/swing/filechooser/FileView.java
index c431fd46127..ea1989f9353 100644
--- a/libjava/classpath/javax/swing/filechooser/FileView.java
+++ b/libjava/classpath/javax/swing/filechooser/FileView.java
@@ -1,5 +1,5 @@
/* FileView.java --
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -43,72 +43,86 @@ import java.io.File;
import javax.swing.Icon;
/**
- * FileView
- * @author Andrew Selkirk
- * @version 1.0
+ * An abstract class that provides presentation information about files and
+ * directories. .
+ *
+ * @author Andrew Selkirk
*/
-public abstract class FileView {
-
- //-------------------------------------------------------------
- // Initialization ---------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * Constructor FileView
- */
- public FileView() {
- // TODO
- } // FileView()
-
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * getName
- * @param file TODO
- * @returns String
- */
- public String getName(File file) {
- return null; // TODO
- } // getName()
-
- /**
- * getDescription
- * @param value0 TODO
- * @returns String
- */
- public String getDescription(File value0) {
- return null; // TODO
- } // getDescription()
-
- /**
- * getTypeDescription
- * @param value0 TODO
- * @returns String
- */
- public String getTypeDescription(File value0) {
- return null; // TODO
- } // getTypeDescription()
-
- /**
- * getIcon
- * @param value0 TODO
- * @returns Icon
- */
- public Icon getIcon(File value0) {
- return null; // TODO
- } // getIcon()
-
- /**
- * isTraversable
- * @param value0 TODO
- * @returns Boolean
- */
- public Boolean isTraversable(File value0) {
- return null; // TODO
- } // isTraversable()
-
-
-} // FileView
+public abstract class FileView
+{
+
+ /**
+ * Creates a new <code>FileView</code> instance.
+ */
+ public FileView()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the name for the specified file. This method always returns
+ * <code>null</code> and should be overridden by subclasses.
+ *
+ * @param file the file.
+ *
+ * @return Always <code>null</code>.
+ */
+ public String getName(File file)
+ {
+ return null;
+ }
+
+ /**
+ * Returns a description for the specified file. This method always returns
+ * <code>null</code> and should be overridden by subclasses.
+ *
+ * @param file the file.
+ *
+ * @return Always <code>null</code>.
+ */
+ public String getDescription(File file)
+ {
+ return null;
+ }
+
+ /**
+ * Returns a description for the type of the specified file. This method
+ * always returns <code>null</code> and should be overridden by subclasses.
+ *
+ * @param file the file.
+ *
+ * @return Always <code>null</code>.
+ */
+ public String getTypeDescription(File file)
+ {
+ return null;
+ }
+
+ /**
+ * Returns an {@link Icon} to represent the specified file. This method
+ * always returns <code>null</code> and should be overridden by subclasses.
+ *
+ * @param file the file.
+ *
+ * @return Always <code>null</code>.
+ */
+ public Icon getIcon(File file)
+ {
+ return null;
+ }
+
+ /**
+ * Returns {@link Boolean#TRUE} if the given directory is traversable, and
+ * {@link Boolean#FALSE} if it is not. This method always returns
+ * <code>null</code> and should be overridden by subclasses.
+ *
+ * @param directory the directory.
+ *
+ * @returns Always <code>null</code>.
+ */
+ public Boolean isTraversable(File directory)
+ {
+ return null;
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/filechooser/UnixFileSystemView.java b/libjava/classpath/javax/swing/filechooser/UnixFileSystemView.java
index f2360ec52f8..c2f65965e09 100644
--- a/libjava/classpath/javax/swing/filechooser/UnixFileSystemView.java
+++ b/libjava/classpath/javax/swing/filechooser/UnixFileSystemView.java
@@ -43,21 +43,31 @@ import javax.swing.Icon;
/**
- * DOCUMENT ME!
+ * A concrete implementation of {@link FileSystemView} that is appropriate for
+ * Unix-like systems.
+ *
+ * @see FileSystemView#getFileSystemView()
*/
class UnixFileSystemView extends FileSystemView
{
- /** DOCUMENT ME! */
+ /** The default name for new folders. */
private static final String NEW_FOLDER_NAME = "NewFolder";
/**
- * DOCUMENT ME!
+ * Creates a new folder with a unique name in the specified directory and
+ * returns a {@link File} object representing the new directory. The name
+ * of the new folder is <code>NewFolder</code> or, if a directory or file
+ * with that name already exists, <code>NewFolder.n</code> where
+ * <code>n</code> is the lowest integer greater than zero that results in
+ * a unique directory name.
*
- * @param containingDir DOCUMENT ME!
+ * @param containingDir the directory to contain the new folder
+ * (<code>null</code> not permitted).
*
- * @return DOCUMENT ME!
+ * @return A {@link File} object representing the new directory.
*
- * @throws IOException DOCUMENT ME!
+ * @throws IOException if an exception occurs while creating the new
+ * directory.
*/
public File createNewFolder(File containingDir) throws IOException
{
@@ -82,9 +92,9 @@ class UnixFileSystemView extends FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns an array containing the file system root.
*
- * @return DOCUMENT ME!
+ * @return An array containing the file system root.
*/
public File[] getRoots()
{
@@ -92,11 +102,12 @@ class UnixFileSystemView extends FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns the name of a file as it would be displayed by the underlying
+ * system. This method is NOT YET IMPLEMENTED.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return <code>null</code>.
*/
public String getSystemDisplayName(File f)
{
@@ -105,11 +116,12 @@ class UnixFileSystemView extends FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns the icon that would be displayed for the given file by the
+ * underlying system. This method is NOT YET IMPLEMENTED.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return <code>null</code>.
*/
public Icon getSystemIcon(File f)
{
@@ -118,11 +130,12 @@ class UnixFileSystemView extends FileSystemView
}
/**
- * DOCUMENT ME!
+ * Returns the description of a file that would be displayed by the
+ * underlying system. This method is NOT YET IMPLEMENTED.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return <code>null</code>.
*/
public String getSystemTypeDescription(File f)
{
diff --git a/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java b/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java
index f6af0880ddb..07292fe24a4 100644
--- a/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java
+++ b/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java
@@ -50,9 +50,7 @@ import javax.swing.ActionMap;
* @author Andrew Selkirk
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class ActionMapUIResource
- extends ActionMap
- implements UIResource
+public class ActionMapUIResource extends ActionMap implements UIResource
{
/**
* Constructs a new ActionMapUIResource.
diff --git a/libjava/classpath/javax/swing/plaf/BorderUIResource.java b/libjava/classpath/javax/swing/plaf/BorderUIResource.java
index 4402bbb48b6..317cb09ac57 100644
--- a/libjava/classpath/javax/swing/plaf/BorderUIResource.java
+++ b/libjava/classpath/javax/swing/plaf/BorderUIResource.java
@@ -71,9 +71,7 @@ import javax.swing.border.TitledBorder;
* @author Brian Jones (cbj@gnu.org)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class BorderUIResource
- extends Object
- implements Border, UIResource, Serializable
+public class BorderUIResource implements Border, UIResource, Serializable
{
/**
* Verified using the <code>serialver</code> tool
diff --git a/libjava/classpath/javax/swing/plaf/ButtonUI.java b/libjava/classpath/javax/swing/plaf/ButtonUI.java
index 197299e0c95..6910e42989d 100644
--- a/libjava/classpath/javax/swing/plaf/ButtonUI.java
+++ b/libjava/classpath/javax/swing/plaf/ButtonUI.java
@@ -46,7 +46,7 @@ package javax.swing.plaf;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class ButtonUI
- extends ComponentUI
+public abstract class ButtonUI extends ComponentUI
{
+ // This abstract class does not define any methods of its own.
}
diff --git a/libjava/classpath/javax/swing/plaf/ColorChooserUI.java b/libjava/classpath/javax/swing/plaf/ColorChooserUI.java
index 68ffd916d21..16091416a32 100644
--- a/libjava/classpath/javax/swing/plaf/ColorChooserUI.java
+++ b/libjava/classpath/javax/swing/plaf/ColorChooserUI.java
@@ -46,8 +46,7 @@ package javax.swing.plaf;
* @author Andrew Selkirk
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class ColorChooserUI
- extends ComponentUI
+public abstract class ColorChooserUI extends ComponentUI
{
/**
* Constructs a ColorChooserUI.
diff --git a/libjava/classpath/javax/swing/plaf/ColorUIResource.java b/libjava/classpath/javax/swing/plaf/ColorUIResource.java
index 33b1676e0fd..36e10f2d186 100644
--- a/libjava/classpath/javax/swing/plaf/ColorUIResource.java
+++ b/libjava/classpath/javax/swing/plaf/ColorUIResource.java
@@ -50,9 +50,7 @@ import java.awt.Color;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class ColorUIResource
- extends Color
- implements UIResource
+public class ColorUIResource extends Color implements UIResource
{
/**
* Constructs a <code>ColorUIResource</code> using the specified
diff --git a/libjava/classpath/javax/swing/plaf/ComboBoxUI.java b/libjava/classpath/javax/swing/plaf/ComboBoxUI.java
index 9498a48153a..3e81ed75a6b 100644
--- a/libjava/classpath/javax/swing/plaf/ComboBoxUI.java
+++ b/libjava/classpath/javax/swing/plaf/ComboBoxUI.java
@@ -48,14 +48,14 @@ import javax.swing.JComboBox;
* @author Andrew Selkirk
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class ComboBoxUI
- extends ComponentUI
+public abstract class ComboBoxUI extends ComponentUI
{
/**
* Constructs a new <code>ComboBoxUI</code>.
*/
public ComboBoxUI()
{
+ // Nothing to do here.
}
diff --git a/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java b/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java
index e1418710fb2..cfc43e4fc78 100644
--- a/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java
+++ b/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java
@@ -52,8 +52,7 @@ import javax.swing.JComponent;
* @author Andrew Selkirk
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class ComponentInputMapUIResource
- extends ComponentInputMap
+public class ComponentInputMapUIResource extends ComponentInputMap
implements UIResource
{
/**
diff --git a/libjava/classpath/javax/swing/plaf/ComponentUI.java b/libjava/classpath/javax/swing/plaf/ComponentUI.java
index 0e7680542f7..6a736f258a2 100644
--- a/libjava/classpath/javax/swing/plaf/ComponentUI.java
+++ b/libjava/classpath/javax/swing/plaf/ComponentUI.java
@@ -38,8 +38,10 @@ exception statement from your version. */
package javax.swing.plaf;
+import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
+import java.awt.Rectangle;
import javax.accessibility.Accessible;
import javax.swing.JComponent;
@@ -86,6 +88,7 @@ public abstract class ComponentUI
*/
public ComponentUI()
{
+ // Nothing to do here.
}
@@ -157,6 +160,8 @@ public abstract class ComponentUI
*/
public void paint(Graphics g, JComponent c)
{
+ // Nothing is done here. This method is meant to be overridden by
+ // subclasses.
}
@@ -181,13 +186,14 @@ public abstract class ComponentUI
{
if (c.isOpaque())
{
+ Color oldColor = g.getColor();
g.setColor(c.getBackground());
g.fillRect(0, 0, c.getWidth(), c.getHeight());
+ g.setColor(oldColor);
}
paint(g, c);
}
-
-
+
/**
* Determines the preferred size of a component. The default
* implementation returns <code>null</code>, which means that
diff --git a/libjava/classpath/javax/swing/plaf/DesktopIconUI.java b/libjava/classpath/javax/swing/plaf/DesktopIconUI.java
index 2e44088cadd..676233ec2cf 100644
--- a/libjava/classpath/javax/swing/plaf/DesktopIconUI.java
+++ b/libjava/classpath/javax/swing/plaf/DesktopIconUI.java
@@ -44,13 +44,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class DesktopIconUI
- extends ComponentUI
+public abstract class DesktopIconUI extends ComponentUI
{
/**
* Constructs a new <code>DesktopIconUI</code>.
*/
public DesktopIconUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java b/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java
index de553eaf4de..3d4cfc830f5 100644
--- a/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java
@@ -46,14 +46,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class DesktopPaneUI
- extends ComponentUI
+public abstract class DesktopPaneUI extends ComponentUI
{
/**
* Constructs a new <code>DesktopPaneUI</code>.
*/
public DesktopPaneUI()
{
+ // Nothing to do here.
}
}
-
diff --git a/libjava/classpath/javax/swing/plaf/DimensionUIResource.java b/libjava/classpath/javax/swing/plaf/DimensionUIResource.java
index 63c6838c4d1..618c220369e 100644
--- a/libjava/classpath/javax/swing/plaf/DimensionUIResource.java
+++ b/libjava/classpath/javax/swing/plaf/DimensionUIResource.java
@@ -51,9 +51,7 @@ import java.awt.Dimension;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class DimensionUIResource
- extends Dimension
- implements UIResource
+public class DimensionUIResource extends Dimension implements UIResource
{
/**
* Constructs a new DimensionUIResource, given its width and height.
diff --git a/libjava/classpath/javax/swing/plaf/FileChooserUI.java b/libjava/classpath/javax/swing/plaf/FileChooserUI.java
index 8b661e399a5..e9be8f2ba49 100644
--- a/libjava/classpath/javax/swing/plaf/FileChooserUI.java
+++ b/libjava/classpath/javax/swing/plaf/FileChooserUI.java
@@ -53,14 +53,14 @@ import javax.swing.filechooser.FileView;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class FileChooserUI
- extends ComponentUI
+public abstract class FileChooserUI extends ComponentUI
{
/**
* Constructs a new <code>FileChooserUI</code>.
*/
public FileChooserUI()
{
+ // Nothing to do here.
}
diff --git a/libjava/classpath/javax/swing/plaf/FontUIResource.java b/libjava/classpath/javax/swing/plaf/FontUIResource.java
index 1c1731048e8..c54f987fdb7 100644
--- a/libjava/classpath/javax/swing/plaf/FontUIResource.java
+++ b/libjava/classpath/javax/swing/plaf/FontUIResource.java
@@ -50,9 +50,7 @@ import java.awt.Font;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class FontUIResource
- extends Font
- implements UIResource
+public class FontUIResource extends Font implements UIResource
{
/**
* Constructs a new <code>FontUIResource</code> given
diff --git a/libjava/classpath/javax/swing/plaf/IconUIResource.java b/libjava/classpath/javax/swing/plaf/IconUIResource.java
index 1b09ed31f39..659c8e7bab7 100644
--- a/libjava/classpath/javax/swing/plaf/IconUIResource.java
+++ b/libjava/classpath/javax/swing/plaf/IconUIResource.java
@@ -53,8 +53,7 @@ import javax.swing.Icon;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class IconUIResource
- implements Icon, UIResource, Serializable
+public class IconUIResource implements Icon, UIResource, Serializable
{
/**
* Verified using the <code>serialver</code> tool of Sun JDK 1.4.1_01
diff --git a/libjava/classpath/javax/swing/plaf/InputMapUIResource.java b/libjava/classpath/javax/swing/plaf/InputMapUIResource.java
index ae032e51fa8..0c5f6f9e97e 100644
--- a/libjava/classpath/javax/swing/plaf/InputMapUIResource.java
+++ b/libjava/classpath/javax/swing/plaf/InputMapUIResource.java
@@ -49,15 +49,13 @@ import javax.swing.InputMap;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class InputMapUIResource
- extends InputMap
- implements UIResource
+public class InputMapUIResource extends InputMap implements UIResource
{
/**
* Constructs a new <code>InputMapUIResource</code>.
*/
public InputMapUIResource()
{
+ // Nothing to do here.
}
}
-
diff --git a/libjava/classpath/javax/swing/plaf/InsetsUIResource.java b/libjava/classpath/javax/swing/plaf/InsetsUIResource.java
index 755d8add1b2..d64feb44c1a 100644
--- a/libjava/classpath/javax/swing/plaf/InsetsUIResource.java
+++ b/libjava/classpath/javax/swing/plaf/InsetsUIResource.java
@@ -50,8 +50,7 @@ import java.io.Serializable;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class InsetsUIResource
- extends Insets
+public class InsetsUIResource extends Insets
implements Cloneable, UIResource, Serializable
{
/**
diff --git a/libjava/classpath/javax/swing/plaf/InternalFrameUI.java b/libjava/classpath/javax/swing/plaf/InternalFrameUI.java
index fd1e3374c13..0b2f77caa15 100644
--- a/libjava/classpath/javax/swing/plaf/InternalFrameUI.java
+++ b/libjava/classpath/javax/swing/plaf/InternalFrameUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class InternalFrameUI
- extends ComponentUI
+public abstract class InternalFrameUI extends ComponentUI
{
/**
* Constructs a new <code>InternalFrameUI</code>.
*/
public InternalFrameUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/LabelUI.java b/libjava/classpath/javax/swing/plaf/LabelUI.java
index 8fc1d711b0e..f4b74d59e81 100644
--- a/libjava/classpath/javax/swing/plaf/LabelUI.java
+++ b/libjava/classpath/javax/swing/plaf/LabelUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class LabelUI
- extends ComponentUI
+public abstract class LabelUI extends ComponentUI
{
/**
* Constructs a new <code>LabelUI</code>.
*/
public LabelUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/ListUI.java b/libjava/classpath/javax/swing/plaf/ListUI.java
index 66d5cf588bb..bdfe4b3078f 100644
--- a/libjava/classpath/javax/swing/plaf/ListUI.java
+++ b/libjava/classpath/javax/swing/plaf/ListUI.java
@@ -49,14 +49,14 @@ import javax.swing.JList;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class ListUI
- extends ComponentUI
+public abstract class ListUI extends ComponentUI
{
/**
* Constructs a new <code>ListUI</code>.
*/
public ListUI()
{
+ // Nothing to do here.
}
diff --git a/libjava/classpath/javax/swing/plaf/MenuBarUI.java b/libjava/classpath/javax/swing/plaf/MenuBarUI.java
index 8835571ac75..2c82adfa0a0 100644
--- a/libjava/classpath/javax/swing/plaf/MenuBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/MenuBarUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class MenuBarUI
- extends ComponentUI
+public abstract class MenuBarUI extends ComponentUI
{
/**
* Constructs a new <code>MenuBarUI</code>.
*/
public MenuBarUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/MenuItemUI.java b/libjava/classpath/javax/swing/plaf/MenuItemUI.java
index 31d73194a18..83ad52fb103 100644
--- a/libjava/classpath/javax/swing/plaf/MenuItemUI.java
+++ b/libjava/classpath/javax/swing/plaf/MenuItemUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class MenuItemUI
- extends ButtonUI
+public abstract class MenuItemUI extends ButtonUI
{
/**
* Constructs a new <code>MenuItemUI</code>.
*/
public MenuItemUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/PanelUI.java b/libjava/classpath/javax/swing/plaf/PanelUI.java
index b1171b80d30..12a6f52cfa8 100644
--- a/libjava/classpath/javax/swing/plaf/PanelUI.java
+++ b/libjava/classpath/javax/swing/plaf/PanelUI.java
@@ -46,13 +46,13 @@ package javax.swing.plaf;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class PanelUI
- extends ComponentUI
+public abstract class PanelUI extends ComponentUI
{
/**
* Constructs a new <code>PanelUI</code>.
*/
public PanelUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/PopupMenuUI.java b/libjava/classpath/javax/swing/plaf/PopupMenuUI.java
index c70ad2a4e9b..de351f2ef79 100644
--- a/libjava/classpath/javax/swing/plaf/PopupMenuUI.java
+++ b/libjava/classpath/javax/swing/plaf/PopupMenuUI.java
@@ -53,14 +53,14 @@ import javax.swing.PopupFactory;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class PopupMenuUI
- extends ComponentUI
+public abstract class PopupMenuUI extends ComponentUI
{
/**
* Constructs a new <code>PopupMenuUI</code>.
*/
public PopupMenuUI()
{
+ // Nothing to do here.
}
diff --git a/libjava/classpath/javax/swing/plaf/ProgressBarUI.java b/libjava/classpath/javax/swing/plaf/ProgressBarUI.java
index 79c1b95a34a..013b8c5c2e7 100644
--- a/libjava/classpath/javax/swing/plaf/ProgressBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/ProgressBarUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class ProgressBarUI
- extends ComponentUI
+public abstract class ProgressBarUI extends ComponentUI
{
/**
* Constructs a new <code>ProgressBarUI</code>.
*/
public ProgressBarUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/RootPaneUI.java b/libjava/classpath/javax/swing/plaf/RootPaneUI.java
index ff7d0a6e78a..9637c9cf218 100644
--- a/libjava/classpath/javax/swing/plaf/RootPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/RootPaneUI.java
@@ -46,13 +46,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class RootPaneUI
- extends ComponentUI
+public abstract class RootPaneUI extends ComponentUI
{
/**
* Constructs a new <code>RootPaneUI</code>.
*/
public RootPaneUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/ScrollBarUI.java b/libjava/classpath/javax/swing/plaf/ScrollBarUI.java
index 3cad3932720..51b4bf2d853 100644
--- a/libjava/classpath/javax/swing/plaf/ScrollBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/ScrollBarUI.java
@@ -46,13 +46,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class ScrollBarUI
- extends ComponentUI
+public abstract class ScrollBarUI extends ComponentUI
{
/**
* Constructs a new <code>ScrollBarUI</code>.
*/
public ScrollBarUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java
index 14d2ac61ef2..8b37fed2246 100644
--- a/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class ScrollPaneUI
- extends ComponentUI
+public abstract class ScrollPaneUI extends ComponentUI
{
/**
* Constructs a new <code>ScrollPaneUI</code>.
*/
public ScrollPaneUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/SeparatorUI.java b/libjava/classpath/javax/swing/plaf/SeparatorUI.java
index 6855bd0357e..8a9f8cf4d49 100644
--- a/libjava/classpath/javax/swing/plaf/SeparatorUI.java
+++ b/libjava/classpath/javax/swing/plaf/SeparatorUI.java
@@ -54,5 +54,6 @@ public abstract class SeparatorUI
*/
public SeparatorUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/SliderUI.java b/libjava/classpath/javax/swing/plaf/SliderUI.java
index 775f19620a8..570e962aa3e 100644
--- a/libjava/classpath/javax/swing/plaf/SliderUI.java
+++ b/libjava/classpath/javax/swing/plaf/SliderUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class SliderUI
- extends ComponentUI
+public abstract class SliderUI extends ComponentUI
{
/**
* Constructs a new <code>SliderUI</code>.
*/
public SliderUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/SpinnerUI.java b/libjava/classpath/javax/swing/plaf/SpinnerUI.java
index fb4a3b13a93..ca29ddb8e4f 100644
--- a/libjava/classpath/javax/swing/plaf/SpinnerUI.java
+++ b/libjava/classpath/javax/swing/plaf/SpinnerUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class SpinnerUI
- extends ComponentUI
+public abstract class SpinnerUI extends ComponentUI
{
/**
* Constructs a new <code>SpinnerUI</code>.
*/
public SpinnerUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/SplitPaneUI.java b/libjava/classpath/javax/swing/plaf/SplitPaneUI.java
index ea9af2b1716..59ededf5847 100644
--- a/libjava/classpath/javax/swing/plaf/SplitPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/SplitPaneUI.java
@@ -51,14 +51,14 @@ import javax.swing.JSplitPane;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class SplitPaneUI
- extends ComponentUI
+public abstract class SplitPaneUI extends ComponentUI
{
/**
* Constructs a new <code>SplitPaneUI</code>.
*/
public SplitPaneUI()
{
+ // Nothing to do here.
}
diff --git a/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java
index 6ab823b50a8..01a7720148f 100644
--- a/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java
@@ -51,14 +51,14 @@ import javax.swing.JTabbedPane;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class TabbedPaneUI
- extends ComponentUI
+public abstract class TabbedPaneUI extends ComponentUI
{
/**
* Constructs a new <code>TabbedPaneUI</code>.
*/
public TabbedPaneUI()
{
+ // Nothing to do here.
}
diff --git a/libjava/classpath/javax/swing/plaf/TableHeaderUI.java b/libjava/classpath/javax/swing/plaf/TableHeaderUI.java
index f23ca74d7ed..34ac0e0fc55 100644
--- a/libjava/classpath/javax/swing/plaf/TableHeaderUI.java
+++ b/libjava/classpath/javax/swing/plaf/TableHeaderUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class TableHeaderUI
- extends ComponentUI
+public abstract class TableHeaderUI extends ComponentUI
{
/**
* Constructs a new <code>TableHeaderUI</code>.
*/
public TableHeaderUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/TableUI.java b/libjava/classpath/javax/swing/plaf/TableUI.java
index e56bcd13160..a8c6bf909d9 100644
--- a/libjava/classpath/javax/swing/plaf/TableUI.java
+++ b/libjava/classpath/javax/swing/plaf/TableUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class TableUI
- extends ComponentUI
+public abstract class TableUI extends ComponentUI
{
/**
* Constructs a new <code>TableUI</code>.
*/
public TableUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/TextUI.java b/libjava/classpath/javax/swing/plaf/TextUI.java
index dcabdfcdbf3..9f2737cc26f 100644
--- a/libjava/classpath/javax/swing/plaf/TextUI.java
+++ b/libjava/classpath/javax/swing/plaf/TextUI.java
@@ -57,14 +57,14 @@ import javax.swing.text.View;
* @author Ronald Veldema (rveldema@cs.vu.nl)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class TextUI
- extends ComponentUI
+public abstract class TextUI extends ComponentUI
{
/**
* Constructs a new <code>TextUI</code>.
*/
public TextUI()
{
+ // Nothing to do here.
}
diff --git a/libjava/classpath/javax/swing/plaf/ToolBarUI.java b/libjava/classpath/javax/swing/plaf/ToolBarUI.java
index 730cf4887db..9a26e7b59d5 100644
--- a/libjava/classpath/javax/swing/plaf/ToolBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/ToolBarUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class ToolBarUI
- extends ComponentUI
+public abstract class ToolBarUI extends ComponentUI
{
/**
* Constructs a new <code>ToolBarUI</code>.
*/
public ToolBarUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/ToolTipUI.java b/libjava/classpath/javax/swing/plaf/ToolTipUI.java
index 4383d0edd11..ae2d465e51c 100644
--- a/libjava/classpath/javax/swing/plaf/ToolTipUI.java
+++ b/libjava/classpath/javax/swing/plaf/ToolTipUI.java
@@ -47,13 +47,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class ToolTipUI
- extends ComponentUI
+public abstract class ToolTipUI extends ComponentUI
{
/**
* Constructs a new <code>ToolTipUI</code>.
*/
public ToolTipUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/TreeUI.java b/libjava/classpath/javax/swing/plaf/TreeUI.java
index e32952de70f..308ec63e2a8 100644
--- a/libjava/classpath/javax/swing/plaf/TreeUI.java
+++ b/libjava/classpath/javax/swing/plaf/TreeUI.java
@@ -51,14 +51,14 @@ import javax.swing.tree.TreePath;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class TreeUI
- extends ComponentUI
+public abstract class TreeUI extends ComponentUI
{
/**
* Constructs a new <code>TreeUI</code>.
*/
public TreeUI()
{
+ // Nothing to do here.
}
diff --git a/libjava/classpath/javax/swing/plaf/UIResource.java b/libjava/classpath/javax/swing/plaf/UIResource.java
index 59edf566605..fe398fe5474 100644
--- a/libjava/classpath/javax/swing/plaf/UIResource.java
+++ b/libjava/classpath/javax/swing/plaf/UIResource.java
@@ -50,6 +50,10 @@ package javax.swing.plaf;
* they are initialized or set to <code>null</code>.
*
* @author Brian Jones
+ *
* @see ComponentUI
*/
-public interface UIResource { }
+public interface UIResource
+{
+ // This is a marker interface and declares no methods.
+}
diff --git a/libjava/classpath/javax/swing/plaf/ViewportUI.java b/libjava/classpath/javax/swing/plaf/ViewportUI.java
index 087938f1ed2..db514de1a4e 100644
--- a/libjava/classpath/javax/swing/plaf/ViewportUI.java
+++ b/libjava/classpath/javax/swing/plaf/ViewportUI.java
@@ -48,13 +48,13 @@ package javax.swing.plaf;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public abstract class ViewportUI
- extends ComponentUI
+public abstract class ViewportUI extends ComponentUI
{
/**
* Constructs a new <code>ViewportUI</code>.
*/
public ViewportUI()
{
+ // Nothing to do here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java b/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java
index 836ef223494..69d4415371f 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java
@@ -39,42 +39,30 @@ 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.Graphics;
-import java.awt.Insets;
import java.awt.Polygon;
import java.awt.Rectangle;
+import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.SwingConstants;
-import javax.swing.border.Border;
/**
- * This class draws simple arrow buttons for the Basic Look and Feel.
+ * A button that displays an arrow (triangle) that points {@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} or {@link #WEST}. This button is used by
+ * the {@link BasicComboBoxUI} class.
+ *
+ * @see BasicComboBoxUI#createArrowButton
*/
public class BasicArrowButton extends JButton implements SwingConstants
{
- /** The default size of the Arrow buttons. */
- private static int defaultSize = 12;
- /** The Polygon that points up. */
- private static Polygon upIcon = new Polygon(new int[] { 0, 5, 9 },
- new int[] { 7, 2, 7 }, 3);
-
- /** The Polygon that points down. */
- private static Polygon downIcon = new Polygon(new int[] { 1, 5, 9 },
- new int[] { 3, 7, 3 }, 3);
-
- /** The Polygon that points left. */
- private static Polygon leftIcon = new Polygon(new int[] { 7, 3, 7 },
- new int[] { 1, 5, 9 }, 3);
-
- /** The Polygon that points right. */
- private static Polygon rightIcon = new Polygon(new int[] { 3, 7, 3 },
- new int[] { 1, 5, 9 }, 3);
-
- /** The direction to point in. */
+ /**
+ * The direction that the arrow points.
+ *
+ * @see #getDirection()
+ */
protected int direction;
/**
@@ -89,7 +77,7 @@ public class BasicArrowButton extends JButton implements SwingConstants
* edges of the button.
* This is package-private to avoid an accessor method.
*/
- transient Color darkShadow = Color.DARK_GRAY;
+ transient Color darkShadow = new Color(102, 102, 102);
/**
* The top and left edges of the button.
@@ -97,51 +85,15 @@ public class BasicArrowButton extends JButton implements SwingConstants
*/
transient Color highlight = Color.WHITE;
- /** The border around the ArrowButton. */
- private transient Border buttonBorder = new Border()
- {
- public Insets getBorderInsets(Component c)
- {
- return new Insets(2, 2, 2, 2);
- }
-
- public boolean isBorderOpaque()
- {
- return true;
- }
-
- public void paintBorder(Component c, Graphics g, int x, int y, int w,
- int h)
- {
- Color saved = g.getColor();
- g.setColor(highlight);
-
- g.drawLine(x + 1, y + 1, x + w - 1, y + 1);
- g.drawLine(x + 1, y + 1, x + 1, y + h - 1);
-
- g.setColor(shadow);
-
- g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
- g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
-
- g.setColor(darkShadow);
-
- g.drawLine(x, y + h, x + w, y + h);
- g.drawLine(x + w, y, x + w, y + h);
-
- g.setColor(saved);
- }
- };
-
/**
- * Creates a new BasicArrowButton object.
+ * Creates a new <code>BasicArrowButton</code> object.
*
- * @param direction The direction the arrow points in.
+ * @param direction The direction the arrow points in (one of:
+ * {@link #NORTH}, {@link #SOUTH}, {@link #EAST} and {@link #WEST}).
*/
public BasicArrowButton(int direction)
{
super();
- setBorder(buttonBorder);
setDirection(direction);
}
@@ -149,7 +101,8 @@ public class BasicArrowButton extends JButton implements SwingConstants
* Creates a new BasicArrowButton object with the given colors and
* direction.
*
- * @param direction The direction to point in.
+ * @param direction The direction to point in (one of:
+ * {@link #NORTH}, {@link #SOUTH}, {@link #EAST} and {@link #WEST}).
* @param background The background color.
* @param shadow The shadow color.
* @param darkShadow The dark shadow color.
@@ -166,9 +119,10 @@ public class BasicArrowButton extends JButton implements SwingConstants
}
/**
- * This method returns whether the focus can traverse to this component.
+ * Returns whether the focus can traverse to this component. This method
+ * always returns <code>false</code>.
*
- * @return Whether the focus can traverse to this component.
+ * @return <code>false</code>.
*/
public boolean isFocusTraversable()
{
@@ -176,7 +130,8 @@ public class BasicArrowButton extends JButton implements SwingConstants
}
/**
- * This method returns the direction of the arrow.
+ * Returns the direction of the arrow (one of: {@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} and {@link #WEST}).
*
* @return The direction of the arrow.
*/
@@ -186,9 +141,10 @@ public class BasicArrowButton extends JButton implements SwingConstants
}
/**
- * This method changes the direction of the arrow.
+ * Sets the direction of the arrow.
*
- * @param dir The new direction of the arrow.
+ * @param dir The new direction of the arrow (one of: {@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} and {@link #WEST}).
*/
public void setDirection(int dir)
{
@@ -196,7 +152,7 @@ public class BasicArrowButton extends JButton implements SwingConstants
}
/**
- * This method paints the arrow button. The painting is delegated to the
+ * Paints the arrow button. The painting is delegated to the
* paintTriangle method.
*
* @param g The Graphics object to paint with.
@@ -204,147 +160,257 @@ public class BasicArrowButton extends JButton implements SwingConstants
public void paint(Graphics g)
{
super.paint(g);
- Insets insets = getInsets();
Rectangle bounds = getBounds();
- int x = insets.left
- + (bounds.width - insets.left - insets.right - defaultSize) / 2;
- int y = insets.top
- + (bounds.height - insets.left - insets.right - defaultSize) / 2;
- paintTriangle(g, x, y, defaultSize, direction, isEnabled());
+ int size = bounds.height / 4;
+ int x = (bounds.width - size) / 2;
+ int y = (bounds.height - size) / 2;
+ ButtonModel m = getModel();
+ if (m.isArmed())
+ {
+ x++;
+ y++;
+ }
+ paintTriangle(g, x, y, size, direction, isEnabled());
}
+ /** The preferred size for the button. */
+ private static final Dimension PREFERRED_SIZE = new Dimension(16, 16);
+
+ /** The minimum size for the button. */
+ private static final Dimension MINIMUM_SIZE = new Dimension(5, 5);
+
+ /** The maximum size for the button. */
+ private static final Dimension MAXIMUM_SIZE
+ = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+
/**
- * This method returns the preferred size of the arrow button.
+ * Returns the preferred size of the arrow button.
*
- * @return The preferred size.
+ * @return The preferred size (always 16 x 16).
*/
public Dimension getPreferredSize()
{
- Insets insets = getInsets();
- int w = defaultSize + insets.left + insets.right;
- int h = defaultSize + insets.top + insets.bottom;
-
- return new Dimension(w, h);
+ return PREFERRED_SIZE;
}
/**
- * This method returns the minimum size of the arrow button.
+ * Returns the minimum size of the arrow button.
*
- * @return The minimum size.
+ * @return The minimum size (always 5 x 5).
*/
public Dimension getMinimumSize()
{
- return getPreferredSize();
+ return MINIMUM_SIZE;
}
/**
- * This method returns the maximum size of the arrow button.
+ * Returns the maximum size of the arrow button.
*
* @return The maximum size.
*/
public Dimension getMaximumSize()
{
- return getPreferredSize();
+ return MAXIMUM_SIZE;
}
/**
- * The method paints a triangle with the given size and direction at the
- * given x and y coordinates.
+ * Paints a triangle with the given size, location and direction. It is
+ * difficult to explain the rationale behind the positioning of the triangle
+ * relative to the given (x, y) position - by trial and error we seem to
+ * match the behaviour of the reference implementation (which is missing a
+ * specification for this method).
*
- * @param g The Graphics object to paint with.
- * @param x The x coordinate to paint at.
- * @param y The y coordinate to paint at.
- * @param size The size of the icon.
- * @param direction The direction of the icon.
- * @param isEnabled Whether it is enabled.
+ * @param g the graphics device.
+ * @param x the x-coordinate for the triangle's location.
+ * @param y the y-coordinate for the triangle's location.
+ * @param size the arrow size (depth).
+ * @param direction the direction of the arrow (one of: {@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} and {@link #WEST}).
+ * @param isEnabled if <code>true</code> the arrow is drawn in the enabled
+ * state, otherwise it is drawn in the disabled state.
*/
public void paintTriangle(Graphics g, int x, int y, int size, int direction,
boolean isEnabled)
{
- Polygon arrow = null;
- switch (direction)
- {
- case NORTH:
- arrow = upIcon;
- break;
- case SOUTH:
- arrow = downIcon;
- break;
- case EAST:
- case RIGHT:
- arrow = rightIcon;
- break;
- case WEST:
- case LEFT:
- arrow = leftIcon;
- break;
- }
-
- int[] xPoints = arrow.xpoints;
- int[] yPoints = arrow.ypoints;
- int x1;
- int y1;
- int x2;
- int y2;
- x1 = y1 = x2 = y2 = 0;
-
- if (size != defaultSize)
- {
- float scale = size * 1f / defaultSize;
- for (int i = 0; i < 3; i++)
- {
- xPoints[i] *= scale;
- yPoints[i] *= scale;
- }
- }
- g.translate(x, y);
-
+ Color savedColor = g.getColor();
switch (direction)
{
case NORTH:
- x1 = xPoints[0] + 2;
- y1 = yPoints[0];
- y2 = y1;
- x2 = xPoints[2] - 1;
- break;
+ paintTriangleNorth(g, x, y, size, isEnabled);
+ break;
case SOUTH:
- x1 = xPoints[1];
- y1 = yPoints[1] + 1;
- x2 = xPoints[2] - 1;
- y2 = yPoints[2];
- break;
+ paintTriangleSouth(g, x, y, size, isEnabled);
+ break;
case LEFT:
case WEST:
- x1 = xPoints[0] + 1;
- y1 = yPoints[0] + 1;
- x2 = x1;
- y2 = yPoints[2] + 1;
- break;
+ paintTriangleWest(g, x, y, size, isEnabled);
+ break;
case RIGHT:
case EAST:
- x1 = xPoints[2];
- y1 = yPoints[2] + 1;
- x2 = xPoints[1] - 1;
- y2 = yPoints[1] + 1;
- break;
+ paintTriangleEast(g, x, y, size, isEnabled);
+ break;
}
- Color saved = g.getColor();
-
+ g.setColor(savedColor);
+ }
+
+ /**
+ * Paints an upward-pointing triangle. This method is called by the
+ * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method.
+ *
+ * @param g the graphics device.
+ * @param x the x-coordinate for the anchor point.
+ * @param y the y-coordinate for the anchor point.
+ * @param size the arrow size (depth).
+ * @param isEnabled if <code>true</code> the arrow is drawn in the enabled
+ * state, otherwise it is drawn in the disabled state.
+ */
+ private void paintTriangleNorth(Graphics g, int x, int y, int size,
+ boolean isEnabled)
+ {
+ int tipX = x + (size - 2) / 2;
+ int tipY = y;
+ int baseX1 = tipX - (size - 1);
+ int baseX2 = tipX + (size - 1);
+ int baseY = y + (size - 1);
+ Polygon triangle = new Polygon();
+ triangle.addPoint(tipX, tipY);
+ triangle.addPoint(baseX1, baseY);
+ triangle.addPoint(baseX2, baseY);
if (isEnabled)
- {
- g.setColor(Color.DARK_GRAY);
-
- if (arrow != null)
- g.fillPolygon(xPoints, yPoints, 3);
- }
+ {
+ g.setColor(Color.DARK_GRAY);
+ g.fillPolygon(triangle);
+ g.drawPolygon(triangle);
+ }
else
- {
- g.setColor(Color.GRAY);
- g.fillPolygon(xPoints, yPoints, 3);
- g.setColor(Color.WHITE);
- g.drawLine(x1, y1, x2, y2);
- }
- g.setColor(saved);
- g.translate(-x, -y);
+ {
+ g.setColor(Color.GRAY);
+ g.fillPolygon(triangle);
+ g.drawPolygon(triangle);
+ g.setColor(Color.WHITE);
+ g.drawLine(baseX1 + 1, baseY + 1, baseX2 + 1, baseY + 1);
+ }
+ }
+
+ /**
+ * Paints an downward-pointing triangle. This method is called by the
+ * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method.
+ *
+ * @param g the graphics device.
+ * @param x the x-coordinate for the anchor point.
+ * @param y the y-coordinate for the anchor point.
+ * @param size the arrow size (depth).
+ * @param isEnabled if <code>true</code> the arrow is drawn in the enabled
+ * state, otherwise it is drawn in the disabled state.
+ */
+ private void paintTriangleSouth(Graphics g, int x, int y, int size,
+ boolean isEnabled)
+ {
+ int tipX = x + (size - 2) / 2;
+ int tipY = y + (size - 1);
+ int baseX1 = tipX - (size - 1);
+ int baseX2 = tipX + (size - 1);
+ int baseY = y;
+ Polygon triangle = new Polygon();
+ triangle.addPoint(tipX, tipY);
+ triangle.addPoint(baseX1, baseY);
+ triangle.addPoint(baseX2, baseY);
+ if (isEnabled)
+ {
+ g.setColor(Color.DARK_GRAY);
+ g.fillPolygon(triangle);
+ g.drawPolygon(triangle);
+ }
+ else
+ {
+ g.setColor(Color.GRAY);
+ g.fillPolygon(triangle);
+ g.drawPolygon(triangle);
+ g.setColor(Color.WHITE);
+ g.drawLine(tipX + 1, tipY, baseX2, baseY + 1);
+ g.drawLine(tipX + 1, tipY + 1, baseX2 + 1, baseY + 1);
+ }
+ }
+
+ /**
+ * Paints a right-pointing triangle. This method is called by the
+ * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method.
+ *
+ * @param g the graphics device.
+ * @param x the x-coordinate for the anchor point.
+ * @param y the y-coordinate for the anchor point.
+ * @param size the arrow size (depth).
+ * @param isEnabled if <code>true</code> the arrow is drawn in the enabled
+ * state, otherwise it is drawn in the disabled state.
+ */
+ private void paintTriangleEast(Graphics g, int x, int y, int size,
+ boolean isEnabled)
+ {
+ int tipX = x + (size - 1);
+ int tipY = y + (size - 2) / 2;
+ int baseX = x;
+ int baseY1 = tipY - (size - 1);
+ int baseY2 = tipY + (size - 1);
+
+ Polygon triangle = new Polygon();
+ triangle.addPoint(tipX, tipY);
+ triangle.addPoint(baseX, baseY1);
+ triangle.addPoint(baseX, baseY2);
+ if (isEnabled)
+ {
+ g.setColor(Color.DARK_GRAY);
+ g.fillPolygon(triangle);
+ g.drawPolygon(triangle);
+ }
+ else
+ {
+ g.setColor(Color.GRAY);
+ g.fillPolygon(triangle);
+ g.drawPolygon(triangle);
+ g.setColor(Color.WHITE);
+ g.drawLine(baseX + 1, baseY2, tipX, tipY + 1);
+ g.drawLine(baseX + 1, baseY2 + 1, tipX + 1, tipY + 1);
+ }
+ }
+
+ /**
+ * Paints a left-pointing triangle. This method is called by the
+ * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method.
+ *
+ * @param g the graphics device.
+ * @param x the x-coordinate for the anchor point.
+ * @param y the y-coordinate for the anchor point.
+ * @param size the arrow size (depth).
+ * @param isEnabled if <code>true</code> the arrow is drawn in the enabled
+ * state, otherwise it is drawn in the disabled state.
+ */
+ private void paintTriangleWest(Graphics g, int x, int y, int size,
+ boolean isEnabled)
+ {
+ int tipX = x;
+ int tipY = y + (size - 2) / 2;
+ int baseX = x + (size - 1);
+ int baseY1 = tipY - (size - 1);
+ int baseY2 = tipY + (size - 1);
+
+ Polygon triangle = new Polygon();
+ triangle.addPoint(tipX, tipY);
+ triangle.addPoint(baseX, baseY1);
+ triangle.addPoint(baseX, baseY2);
+ if (isEnabled)
+ {
+ g.setColor(Color.DARK_GRAY);
+ g.fillPolygon(triangle);
+ g.drawPolygon(triangle);
+ }
+ else
+ {
+ g.setColor(Color.GRAY);
+ g.fillPolygon(triangle);
+ g.drawPolygon(triangle);
+ g.setColor(Color.WHITE);
+ g.drawLine(baseX + 1, baseY1 + 1, baseX + 1, baseY2 + 1);
+ }
}
+
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java
index e7d6e433877..cec7bec8501 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java
@@ -806,9 +806,9 @@ public class BasicBorders
*/
public MarginBorder()
{
+ // Nothing to do here.
}
-
/**
* Measures the width of this border.
*
@@ -1313,33 +1313,32 @@ public class BasicBorders
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
- public static class SplitPaneBorder
- implements Border, UIResource
+ public static class SplitPaneBorder implements Border, UIResource
{
/**
* Indicates that the top edge shall be not be painted
- * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}.
+ * by {@link #paintRect}.
*/
private static final int SUPPRESS_TOP = 1;
/**
* Indicates that the left edge shall be not be painted
- * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}.
+ * by {@link #paintRect}.
*/
private static final int SUPPRESS_LEFT = 2;
/**
* Indicates that the bottom edge shall be not be painted
- * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}.
+ * by {@link #paintRect}.
*/
private static final int SUPPRESS_BOTTOM = 4;
/**
* Indicates that the right edge shall be not be painted
- * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}.
+ * by {@link #paintRect}.
*/
private static final int SUPPRESS_RIGHT = 8;
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java b/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java
index 5349f524049..1fca694519f 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java
@@ -55,9 +55,8 @@ import javax.swing.JComponent;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
-public class BasicButtonListener
- implements MouseListener, MouseMotionListener, FocusListener,
- ChangeListener, PropertyChangeListener
+public class BasicButtonListener implements MouseListener, MouseMotionListener,
+ FocusListener, ChangeListener, PropertyChangeListener
{
public BasicButtonListener(AbstractButton b)
{
@@ -66,10 +65,12 @@ public class BasicButtonListener
public void propertyChange(PropertyChangeEvent e)
{
+ // TODO: What should be done here, if anything?
}
protected void checkOpacity(AbstractButton b)
{
+ // TODO: What should be done here?
}
public void focusGained(FocusEvent e)
@@ -129,18 +130,22 @@ public class BasicButtonListener
public void stateChanged(ChangeEvent e)
{
+ // TODO: What should be done here, if anything?
}
public void mouseMoved(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
public void mouseDragged(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
public void mouseClicked(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java
index 6c80f14b6fc..2d3dbd350e0 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java
@@ -38,7 +38,6 @@ exception statement from your version. */
package javax.swing.plaf.basic;
-import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
@@ -49,13 +48,19 @@ import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.InputMap;
+import javax.swing.JButton;
import javax.swing.JComponent;
+import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.ButtonUI;
import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.UIResource;
+/**
+ * A UI delegate for the {@link JButton} component.
+ */
public class BasicButtonUI extends ButtonUI
{
/**
@@ -72,13 +77,11 @@ public class BasicButtonUI extends ButtonUI
private int textShiftOffset;
- private Color focusColor;
-
/**
* Factory method to create an instance of BasicButtonUI for a given
* {@link JComponent}, which should be an {@link AbstractButton}.
*
- * @param c The component to create a UI got
+ * @param c The component.
*
* @return A new UI capable of drawing the component
*/
@@ -87,21 +90,46 @@ public class BasicButtonUI extends ButtonUI
return new BasicButtonUI();
}
+ /**
+ * Returns the default gap between the button's text and icon (in pixels).
+ *
+ * @param b the button (ignored).
+ *
+ * @return The gap.
+ */
public int getDefaultTextIconGap(AbstractButton b)
{
return defaultTextIconGap;
}
+ /**
+ * Sets the text shift offset to zero.
+ *
+ * @see #setTextShiftOffset()
+ */
protected void clearTextShiftOffset()
{
textShiftOffset = 0;
}
+ /**
+ * Returns the text shift offset.
+ *
+ * @return The text shift offset.
+ *
+ * @see #clearTextShiftOffset()
+ * @see #setTextShiftOffset()
+ */
protected int getTextShiftOffset()
{
return textShiftOffset;
}
+ /**
+ * Sets the text shift offset to the value in {@link #defaultTextShiftOffset}.
+ *
+ * @see #clearTextShiftOffset()
+ */
protected void setTextShiftOffset()
{
textShiftOffset = defaultTextShiftOffset;
@@ -118,23 +146,33 @@ public class BasicButtonUI extends ButtonUI
return "Button.";
}
+ /**
+ * Installs the default settings.
+ *
+ * @param b the button (<code>null</code> not permitted).
+ */
protected void installDefaults(AbstractButton b)
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
String prefix = getPropertyPrefix();
- focusColor = defaults.getColor(prefix + "focus");
- b.setForeground(defaults.getColor(prefix + "foreground"));
- b.setBackground(defaults.getColor(prefix + "background"));
- b.setMargin(defaults.getInsets(prefix + "margin"));
- b.setBorder(defaults.getBorder(prefix + "border"));
- b.setIconTextGap(defaults.getInt(prefix + "textIconGap"));
+ LookAndFeel.installColorsAndFont(b, prefix + "background",
+ prefix + "foreground", prefix + "font");
+ LookAndFeel.installBorder(b, prefix + "border");
+ b.setMargin(UIManager.getInsets(prefix + "margin"));
+ b.setIconTextGap(UIManager.getInt(prefix + "textIconGap"));
b.setInputMap(JComponent.WHEN_FOCUSED,
- (InputMap) defaults.get(prefix + "focusInputMap"));
- b.setOpaque(true);
+ (InputMap) UIManager.get(prefix + "focusInputMap"));
+ b.setRolloverEnabled(UIManager.getBoolean(prefix + "rollover"));
}
+ /**
+ * Removes the defaults added by {@link #installDefaults(AbstractButton)}.
+ *
+ * @param b the button (<code>null</code> not permitted).
+ */
protected void uninstallDefaults(AbstractButton b)
{
+ if (b.getFont() instanceof UIResource)
+ b.setFont(null);
b.setForeground(null);
b.setBackground(null);
b.setBorder(null);
@@ -144,11 +182,25 @@ public class BasicButtonUI extends ButtonUI
protected BasicButtonListener listener;
+ /**
+ * Creates and returns a new instance of {@link BasicButtonListener}. This
+ * method provides a hook to make it easy for subclasses to install a
+ * different listener.
+ *
+ * @param b the button.
+ *
+ * @return A new listener.
+ */
protected BasicButtonListener createButtonListener(AbstractButton b)
{
return new BasicButtonListener(b);
}
+ /**
+ * Installs listeners for the button.
+ *
+ * @param b the button (<code>null</code> not permitted).
+ */
protected void installListeners(AbstractButton b)
{
listener = createButtonListener(b);
@@ -159,6 +211,11 @@ public class BasicButtonUI extends ButtonUI
b.addMouseMotionListener(listener);
}
+ /**
+ * Uninstalls listeners for the button.
+ *
+ * @param b the button (<code>null</code> not permitted).
+ */
protected void uninstallListeners(AbstractButton b)
{
b.removeChangeListener(listener);
@@ -215,12 +272,12 @@ public class BasicButtonUI extends ButtonUI
return d;
}
- private static Icon currentIcon(AbstractButton b)
+ static Icon currentIcon(AbstractButton b)
{
Icon i = b.getIcon();
ButtonModel model = b.getModel();
- if (model.isPressed() && b.getPressedIcon() != null)
+ if (model.isPressed() && b.getPressedIcon() != null && b.isEnabled())
i = b.getPressedIcon();
else if (model.isRollover())
@@ -231,7 +288,7 @@ public class BasicButtonUI extends ButtonUI
i = b.getRolloverIcon();
}
- else if (b.isSelected())
+ else if (b.isSelected() && b.isEnabled())
{
if (b.isEnabled() && b.getSelectedIcon() != null)
i = b.getSelectedIcon();
@@ -264,7 +321,10 @@ public class BasicButtonUI extends ButtonUI
g.setFont(f);
- SwingUtilities.calculateInnerArea(b, vr);
+ if (b.isBorderPainted())
+ SwingUtilities.calculateInnerArea(b, vr);
+ else
+ vr = SwingUtilities.getLocalBounds(b);
String text = SwingUtilities.layoutCompoundLabel(c, g.getFontMetrics(f),
b.getText(),
currentIcon(b),
@@ -279,13 +339,11 @@ public class BasicButtonUI extends ButtonUI
if ((b.getModel().isArmed() && b.getModel().isPressed())
|| b.isSelected())
paintButtonPressed(g, b);
- else
- paintButtonNormal(g, vr, c);
paintIcon(g, c, ir);
if (text != null)
paintText(g, b, tr, text);
- if (b.isFocusOwner())
+ if (b.isFocusOwner() && b.isFocusPainted())
paintFocus(g, b, vr, tr, ir);
}
@@ -331,44 +389,25 @@ public class BasicButtonUI extends ButtonUI
/**
* Paints the background area of an {@link AbstractButton} in the pressed
- * state. This means filling the supplied area with the {@link
- * pressedBackgroundColor}.
+ * state. This means filling the supplied area with a darker than normal
+ * background.
*
* @param g The graphics context to paint with
* @param b The button to paint the state of
*/
protected void paintButtonPressed(Graphics g, AbstractButton b)
{
- if (b.isContentAreaFilled())
- {
- Rectangle area = new Rectangle();
- SwingUtilities.calculateInnerArea(b, area);
- g.setColor(b.getBackground().darker());
- g.fillRect(area.x, area.y, area.width, area.height);
- }
- }
-
- /**
- * Paints the background area of an {@link AbstractButton} in the normal,
- * non-pressed state. This means filling the supplied area with the
- * {@link normalBackgroundColor}.
- *
- * @param g The graphics context to paint with
- * @param area The area in which to paint
- * @param b The component to paint the state of
- */
- private void paintButtonNormal(Graphics g, Rectangle area, JComponent b)
- {
- if (((AbstractButton)b).isContentAreaFilled() && b.isOpaque())
+ if (b.isContentAreaFilled() && b.isOpaque())
{
- g.setColor(b.getBackground());
+ Rectangle area = new Rectangle();
+ SwingUtilities.calculateInnerArea(b, area);
+ g.setColor(UIManager.getColor(getPropertyPrefix() + "shadow"));
g.fillRect(area.x, area.y, area.width, area.height);
}
}
/**
- * Paints the "text" property of an {@link AbstractButton}, using the
- * {@link textColor} color.
+ * Paints the "text" property of an {@link AbstractButton}.
*
* @param g The graphics context to paint with
* @param c The component to paint the state of
@@ -382,8 +421,7 @@ public class BasicButtonUI extends ButtonUI
}
/**
- * Paints the "text" property of an {@link AbstractButton}, using the
- * {@link textColor} color.
+ * Paints the "text" property of an {@link AbstractButton}.
*
* @param g The graphics context to paint with
* @param b The button to paint the state of
@@ -401,15 +439,15 @@ public class BasicButtonUI extends ButtonUI
if (b.isEnabled())
{
- g.setColor(b.getForeground());
- g.drawString(text, textRect.x, textRect.y + fm.getAscent());
+ g.setColor(b.getForeground());
+ g.drawString(text, textRect.x, textRect.y + fm.getAscent());
}
else
{
- g.setColor(b.getBackground().brighter());
- g.drawString(text, textRect.x, textRect.y + fm.getAscent());
- g.setColor(b.getBackground().darker());
- g.drawString(text, textRect.x + 1, textRect.y + fm.getAscent() + 1);
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ String prefix = getPropertyPrefix();
+ g.setColor(defaults.getColor(prefix + "disabledText"));
+ g.drawString(text, textRect.x, textRect.y + fm.getAscent());
}
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java
index 945aea53dc3..95e0dc98257 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java
@@ -53,6 +53,15 @@ import javax.swing.plaf.ComponentUI;
*/
public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI
{
+
+ /**
+ * Creates a new BasicCheckBoxMenuItemUI object.
+ */
+ public BasicCheckBoxMenuItemUI()
+ {
+ super();
+ }
+
/**
* Factory method to create a BasicCheckBoxMenuItemUI for the given {@link
* JComponent}, which should be a JCheckBoxMenuItem
@@ -77,18 +86,6 @@ public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI
}
/**
- * This method installs the defaults that are defined in the Basic look and
- * feel for this JRadioButtonMenuItem
- */
- protected void installDefaults()
- {
- super.installDefaults();
-
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- checkIcon = defaults.getIcon("CheckBoxMenuItem.checkIcon");
- }
-
- /**
* DOCUMENT ME!
*
* @param item DOCUMENT ME!
@@ -100,5 +97,7 @@ public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI
MenuElement[] path,
MenuSelectionManager manager)
{
+ // TODO: May not be implemented properly.
+ item.processMouseEvent(e, path, manager);
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java
index 4e6d3815453..5a872ae6368 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java
@@ -47,8 +47,7 @@ import javax.swing.JColorChooser;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
-import javax.swing.UIDefaults;
-import javax.swing.UIManager;
+import javax.swing.LookAndFeel;
import javax.swing.colorchooser.AbstractColorChooserPanel;
import javax.swing.colorchooser.ColorChooserComponentFactory;
import javax.swing.event.ChangeEvent;
@@ -243,12 +242,21 @@ public class BasicColorChooserUI extends ColorChooserUI
{
uninstallListeners();
uninstallDefaults();
+ uninstallDefaultChoosers();
pane = null;
chooser = null;
}
/**
+ * Uninstalls the default color choosers that have been installed by this UI.
+ */
+ protected void uninstallDefaultChoosers()
+ {
+ defaultChoosers = null;
+ }
+
+ /**
* This method installs the preview panel for the JColorChooser.
*/
protected void installPreviewPanel()
@@ -281,11 +289,9 @@ public class BasicColorChooserUI extends ColorChooserUI
*/
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- chooser.setFont(defaults.getFont("ColorChooser.font"));
- chooser.setForeground(defaults.getColor("ColorChooser.foreground"));
- chooser.setBackground(defaults.getColor("ColorChooser.background"));
+ LookAndFeel.installColorsAndFont(chooser, "ColorChooser.background",
+ "ColorChooser.foreground",
+ "ColorChooser.font");
}
/**
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java
index dd867f0dc55..831dde8c336 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java
@@ -45,35 +45,34 @@ import java.awt.event.FocusListener;
import javax.swing.ComboBoxEditor;
import javax.swing.JTextField;
-import javax.swing.border.EmptyBorder;
/**
- * This is a component that is responsible for displaying/editting selected
- * item in comboBox. By default, the JTextField is returned as
- * BasicComboBoxEditor.
+ * An editor used by the {@link BasicComboBoxUI} class. This editor uses a
+ * {@link JTextField} as the editor component.
*
* @author Olga Rodimina
*/
public class BasicComboBoxEditor extends Object implements ComboBoxEditor,
FocusListener
{
+ /** The editor component. */
protected JTextField editor;
/**
- * Creates a new BasicComboBoxEditor object.
+ * Creates a new <code>BasicComboBoxEditor</code> instance.
*/
public BasicComboBoxEditor()
{
editor = new JTextField();
- editor.setBorder(new EmptyBorder(1, 1, 1, 1));
+ editor.setBorder(null);
+ editor.setColumns(9);
}
/**
- * This method returns textfield that will be used by the combo box to
- * display/edit currently selected item in the combo box.
+ * Returns the component that will be used by the combo box to display and
+ * edit the currently selected item in the combo box.
*
- * @return textfield that will be used by the combo box to display/edit
- * currently selected item
+ * @return The editor component, which is a {@link JTextField} in this case.
*/
public Component getEditorComponent()
{
@@ -98,15 +97,18 @@ public class BasicComboBoxEditor extends Object implements ComboBoxEditor,
}
/**
- * This method returns item that is currently editable.
+ * Returns the text from the editor component.
*
- * @return item in the combo box that is currently editable
+ * @return The text from the editor component.
*/
public Object getItem()
{
return editor.getText();
}
+ /**
+ * Selects all the text in the editor component.
+ */
public void selectAll()
{
editor.selectAll();
@@ -136,8 +138,8 @@ public class BasicComboBoxEditor extends Object implements ComboBoxEditor,
}
/**
- * This method adds actionListener to the editor. If the user will edit
- * currently selected item in the textfield and pressEnter, then action
+ * Adds an {@link ActionListener} to the editor component. If the user will
+ * edit currently selected item in the textfield and pressEnter, then action
* will be performed. The actionPerformed of this ActionListener should
* change the selected item of the comboBox to the newly editted selected
* item.
@@ -147,27 +149,32 @@ public class BasicComboBoxEditor extends Object implements ComboBoxEditor,
*/
public void addActionListener(ActionListener l)
{
- // FIXME: Need to implement
+ editor.addActionListener(l);
}
/**
- * This method removes actionListener from the textfield.
+ * Removes the {@link ActionListener} from the editor component.
*
- * @param l the ActionListener to remove from the textfield.
+ * @param l the listener to remove.
*/
public void removeActionListener(ActionListener l)
{
- // FIXME: Need to implement
+ editor.removeActionListener(l);
}
+ /**
+ * A subclass of {@link BasicComboBoxEditor} that implements the
+ * {@link UIResource} interface.
+ */
public static class UIResource extends BasicComboBoxEditor
implements javax.swing.plaf.UIResource
{
/**
- * Creates a new UIResource object.
+ * Creates a new <code>BasicComboBoxEditor.UIResource</code> instance.
*/
public UIResource()
{
+ // Nothing to do here.
}
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java
index e4fbb8352a9..8115605b77a 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java
@@ -1,5 +1,5 @@
/* BasicComboBoxRenderer.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -40,36 +40,39 @@ package javax.swing.plaf.basic;
import java.awt.Component;
import java.awt.Dimension;
+import java.awt.FontMetrics;
import java.io.Serializable;
+import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;
-import javax.swing.UIDefaults;
-import javax.swing.UIManager;
+import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
/**
- * This class is renderer for the combo box.
+ * A renderer for a {@link JComboBox}.
*
* @author Olga Rodimina
*/
-public class BasicComboBoxRenderer extends JLabel implements ListCellRenderer,
- Serializable
+public class BasicComboBoxRenderer
+ extends JLabel
+ implements ListCellRenderer, Serializable
{
/**
- * This border is used whenever renderer doesn't have a focus.
+ * A shared border instance for all renderers.
*/
protected static Border noFocusBorder = new EmptyBorder(0, 0, 0, 0);
/**
- * Creates a new BasicComboBoxRenderer object.
+ * Creates a new <code>BasicComboBoxRenderer</code> object.
*/
public BasicComboBoxRenderer()
{
setHorizontalAlignment(SwingConstants.LEFT);
+ setBorder(noFocusBorder);
}
/**
@@ -83,7 +86,8 @@ public class BasicComboBoxRenderer extends JLabel implements ListCellRenderer,
}
/**
- * getListCellRendererComponent
+ * Returns a component that has been configured to display the given
+ * <code>value</code>.
*
* @param list List of items for which to the background and foreground
* colors
@@ -100,43 +104,59 @@ public class BasicComboBoxRenderer extends JLabel implements ListCellRenderer,
boolean cellHasFocus)
{
String s = value.toString();
- setText(s);
+
+ // String maybe larger than comboBox.
+ FontMetrics fm = getToolkit().getFontMetrics(list.getFont());
+ int strWidth = SwingUtilities.computeStringWidth(fm, s);
+ int cbWidth = getSize().width;
+ if (cbWidth != 0 && strWidth > cbWidth)
+ {
+ char[] str = s.toCharArray();
+ int currWidth = 0;
+ int i = 0;
+ String postStr = "... ";
+ cbWidth -= SwingUtilities.computeStringWidth(fm, postStr);
+ while (i < str.length && currWidth < cbWidth)
+ {
+ ++i;
+ currWidth = SwingUtilities.computeStringWidth(fm, new String(str, 0, i));
+ }
+ setText(new String(str, 0, i) + postStr);
+ }
+ else
+ setText(s);
+
setOpaque(true);
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- if (isSelected)
+ if (isSelected || cellHasFocus)
{
- setBackground(list.getSelectionBackground());
- setForeground(list.getSelectionForeground());
+ setBackground(list.getSelectionBackground());
+ setForeground(list.getSelectionForeground());
}
else
{
- setBackground(list.getBackground());
- setForeground(list.getForeground());
+ setBackground(list.getBackground());
+ setForeground(list.getForeground());
}
setEnabled(list.isEnabled());
setFont(list.getFont());
-
- // Use focusCellHighlightBorder when renderer has focus and
- // noFocusBorder otherwise
- if (cellHasFocus)
- setBorder(UIManager.getBorder("List.focusCellHighlightBorder"));
- else
- setBorder(noFocusBorder);
-
return this;
}
+ /**
+ * A subclass of {@link BasicComboBoxRenderer} that implements the
+ * {@link javax.swing.plaf.UIResource} interface.
+ */
public static class UIResource extends BasicComboBoxRenderer
implements javax.swing.plaf.UIResource
{
/**
- * Creates a new UIResource object.
+ * Creates a new <code>UIResource</code> object.
*/
public UIResource()
{
+ // Nothing to do here.
}
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java
index 68e18a6ab01..464c8dd9f63 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java
@@ -42,6 +42,8 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
@@ -69,15 +71,17 @@ import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
-import javax.swing.UIDefaults;
+import javax.swing.LookAndFeel;
+import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.UIResource;
/**
- * UI Delegate for JComboBox
+ * A UI delegate for the {@link JComboBox} component.
*
* @author Olga Rodimina
* @author Robert Schuster
@@ -85,52 +89,54 @@ import javax.swing.plaf.ComponentUI;
public class BasicComboBoxUI extends ComboBoxUI
{
/**
- * This arrow button that is displayed in the rigth side of JComboBox. This
- * button is used to hide and show combo box's list of items
+ * The arrow button that is displayed in the right side of JComboBox. This
+ * button is used to hide and show combo box's list of items.
*/
protected JButton arrowButton;
/**
- * The combo box for which this UI delegate is for
+ * The combo box represented by this UI delegate.
*/
protected JComboBox comboBox;
/**
- * Component that is responsible for displaying/editting selected item of
- * the combo box. By default JTextField is used as an editor for the
- * JComboBox
+ * The component that is responsible for displaying/editing the selected
+ * item of the combo box.
+ *
+ * @see BasicComboBoxEditor#getEditorComponent()
*/
protected Component editor;
/**
- * Listener listening to focus events occuring in the JComboBox
+ * A listener listening to focus events occurring in the {@link JComboBox}.
*/
protected FocusListener focusListener;
/**
- * tells whether JComboBox currently has focus
+ * A flag indicating whether JComboBox currently has the focus.
*/
protected boolean hasFocus;
/**
- * Listener listening to item events fired by the JComboBox
+ * A listener listening to item events fired by the {@link JComboBox}.
*/
protected ItemListener itemListener;
/**
- * KeyListener listening to key events that occur while JComboBox has focus
+ * A listener listening to key events that occur while {@link JComboBox} has
+ * the focus.
*/
protected KeyListener keyListener;
/**
- * MouseListener listening to mouse events occuring in the combo box
+ * A listener listening to mouse events occuring in the {@link JComboBox}.
*/
private MouseListener mouseListener;
/**
* List used when rendering selected item of the combo box. The selection
- * and foreground colors for combo box renderer are configured from this
- * list
+ * and foreground colors for combo box renderer are configured from this
+ * list.
*/
protected JList listBox;
@@ -140,11 +146,14 @@ public class BasicComboBoxUI extends ComboBoxUI
protected ListDataListener listDataListener;
/**
- * Popup list containing combo box's menu items
+ * Popup list containing the combo box's menu items.
*/
protected ComboPopup popup;
+
protected KeyListener popupKeyListener;
+
protected MouseListener popupMouseListener;
+
protected MouseMotionListener popupMouseMotionListener;
/**
@@ -152,30 +161,34 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
protected PropertyChangeListener propertyChangeListener;
+ /**
+ * The button background.
+ * @see #installDefaults()
+ */
+ private Color buttonBackground;
+
+ /**
+ * The button shadow.
+ * @see #installDefaults()
+ */
+ private Color buttonShadow;
+
/**
- * Colors that are used to render selected item in the combo box.
+ * The button dark shadow.
+ * @see #installDefaults()
*/
- private Color shadow;
- private Color darkShadow;
- private Color highlight;
- private Color lightHighlight;
+ private Color buttonDarkShadow;
+
+ /**
+ * The button highlight.
+ * @see #installDefaults()
+ */
+ private Color buttonHighlight;
/* Size of the largest item in the comboBox
* This is package-private to avoid an accessor method.
*/
- Dimension largestItemSize;
-
- // It seems that JComboBox doesn't have a border set explicitely. So we just
- // paint the border everytime combo box is displayed.
-
- /* border insets for this JComboBox
- * This is package-private to avoid an accessor method. */
- static final Insets borderInsets = new Insets(2, 2, 2, 2);
-
- // Width of the arrow button
- // This is package-private to avoid an accessor method.
- // FIXME: has wrong name for a constant.
- static final int arrowButtonWidth = 15;
+ Dimension displaySize;
// FIXME: This fields aren't used anywhere at this moment.
protected Dimension cachedMinimumSize;
@@ -183,19 +196,20 @@ public class BasicComboBoxUI extends ComboBoxUI
protected boolean isMinimumSizeDirty;
/**
- * Creates a new BasicComboBoxUI object.
+ * Creates a new <code>BasicComboBoxUI</code> object.
*/
public BasicComboBoxUI()
{
+ // Nothing to do here.
}
/**
- * Factory method to create a BasicComboBoxUI for the given {@link
- * JComponent}, which should be a {@link JComboBox}.
+ * A factory method to create a UI delegate for the given
+ * {@link JComponent}, which should be a {@link JComboBox}.
*
* @param c The {@link JComponent} a UI is being created for.
*
- * @return A BasicComboBoxUI for the {@link JComponent}.
+ * @return A UI delegate for the {@link JComponent}.
*/
public static ComponentUI createUI(JComponent c)
{
@@ -203,9 +217,11 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method installs the UI for the given JComponent.
+ * Installs the UI for the given {@link JComponent}.
*
- * @param c The JComponent to install a UI for.
+ * @param c the JComponent to install a UI for.
+ *
+ * @see #uninstallUI(JComponent)
*/
public void installUI(JComponent c)
{
@@ -213,20 +229,22 @@ public class BasicComboBoxUI extends ComboBoxUI
if (c instanceof JComboBox)
{
- comboBox = (JComboBox) c;
- comboBox.setOpaque(true);
- comboBox.setLayout(createLayoutManager());
- installDefaults();
- installComponents();
- installListeners();
- installKeyboardActions();
+ comboBox = (JComboBox) c;
+ comboBox.setOpaque(true);
+ comboBox.setLayout(createLayoutManager());
+ installDefaults();
+ installComponents();
+ installListeners();
+ installKeyboardActions();
}
}
/**
- * This method uninstalls the UI.
+ * Uninstalls the UI for the given {@link JComponent}.
*
* @param c The JComponent that is having this UI removed.
+ *
+ * @see #installUI(JComponent)
*/
public void uninstallUI(JComponent c)
{
@@ -238,27 +256,27 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method installs the defaults that are defined in the Basic look and
- * feel for this {@link JComboBox}.
+ * Installs the defaults that are defined in the {@link BasicLookAndFeel}
+ * for this {@link JComboBox}.
+ *
+ * @see #uninstallDefaults()
*/
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- comboBox.setBackground(defaults.getColor("ComboBox.background"));
- comboBox.setFont(defaults.getFont("ComboBox.font"));
- comboBox.setForeground(defaults.getColor("ComboBox.foreground"));
-
- // Set default color that should be used to to render selected item
- // of the combo box.
- shadow = defaults.getColor("Button.shadow");
- darkShadow = defaults.getColor("Button.darkShadow");
- lightHighlight = defaults.getColor("Button.light");
- highlight = defaults.getColor("Button.highlight");
+ LookAndFeel.installColorsAndFont(comboBox, "ComboBox.background",
+ "ComboBox.foreground", "ComboBox.font");
+
+ // fetch the button color scheme
+ buttonBackground = UIManager.getColor("ComboBox.buttonBackground");
+ buttonShadow = UIManager.getColor("ComboBox.buttonShadow");
+ buttonDarkShadow = UIManager.getColor("ComboBox.buttonDarkShadow");
+ buttonHighlight = UIManager.getColor("ComboBox.buttonHighlight");
}
/**
- * This method creates and installs the listeners for this UI.
+ * Creates and installs the listeners for this UI.
+ *
+ * @see #uninstallListeners()
*/
protected void installListeners()
{
@@ -268,6 +286,7 @@ public class BasicComboBoxUI extends ComboBoxUI
focusListener = createFocusListener();
comboBox.addFocusListener(focusListener);
+ listBox.addFocusListener(focusListener);
itemListener = createItemListener();
comboBox.addItemListener(itemListener);
@@ -276,35 +295,40 @@ public class BasicComboBoxUI extends ComboBoxUI
comboBox.addKeyListener(keyListener);
mouseListener = createMouseListener();
- comboBox.addMouseListener(mouseListener);
+ arrowButton.addMouseListener(mouseListener);
// install listeners that listen to combo box model
listDataListener = createListDataListener();
comboBox.getModel().addListDataListener(listDataListener);
-
- configureArrowButton();
}
/**
- * This method uninstalls the defaults and sets any objects created during
- * install to null
+ * Uninstalls the defaults and sets any objects created during
+ * install to <code>null</code>.
+ *
+ * @see #installDefaults()
*/
protected void uninstallDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- comboBox.setBackground(null);
- comboBox.setFont(null);
- comboBox.setForeground(null);
-
- shadow = null;
- darkShadow = null;
- lightHighlight = null;
- highlight = null;
+ if (comboBox.getFont() instanceof UIResource)
+ comboBox.setFont(null);
+
+ if (comboBox.getForeground() instanceof UIResource)
+ comboBox.setForeground(null);
+
+ if (comboBox.getBackground() instanceof UIResource)
+ comboBox.setBackground(null);
+
+ buttonBackground = null;
+ buttonShadow = null;
+ buttonDarkShadow = null;
+ buttonHighlight = null;
}
/**
* Detaches all the listeners we attached in {@link #installListeners}.
+ *
+ * @see #installListeners()
*/
protected void uninstallListeners()
{
@@ -312,6 +336,7 @@ public class BasicComboBoxUI extends ComboBoxUI
propertyChangeListener = null;
comboBox.removeFocusListener(focusListener);
+ listBox.removeFocusListener(focusListener);
focusListener = null;
comboBox.removeItemListener(itemListener);
@@ -320,17 +345,15 @@ public class BasicComboBoxUI extends ComboBoxUI
comboBox.removeKeyListener(keyListener);
keyListener = null;
- comboBox.removeMouseListener(mouseListener);
+ arrowButton.removeMouseListener(mouseListener);
mouseListener = null;
comboBox.getModel().removeListDataListener(listDataListener);
listDataListener = null;
-
- unconfigureArrowButton();
}
/**
- * This method creates popup that will contain list of combo box's items
+ * Creates the popup that will contain list of combo box's items.
*
* @return popup containing list of combo box's items
*/
@@ -340,7 +363,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * Creates KeyListener to listen to key events.
+ * Creates a {@link KeyListener} to listen to key events.
*
* @return KeyListener that listens to key events.
*/
@@ -350,8 +373,8 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method create MouseListener that will listen to mouse event occuring
- * in combo box.
+ * Creates a {@link MouseListener} that will listen to mouse events occurring
+ * in the combo box.
*
* @return the MouseListener
*/
@@ -361,10 +384,10 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method create FocusListener that will listen to changes in this
+ * Creates the {@link FocusListener} that will listen to changes in this
* JComboBox's focus.
*
- * @return theFocusListener
+ * @return the FocusListener.
*/
protected FocusListener createFocusListener()
{
@@ -372,9 +395,9 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method create ListDataListener to listen to ComboBox's data model
+ * Creates a {@link ListDataListener} to listen to the combo box's data model.
*
- * @return ListDataListener
+ * @return The new listener.
*/
protected ListDataListener createListDataListener()
{
@@ -382,10 +405,10 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method creates ItemListener that will listen to to the changes in
+ * Creates an {@link ItemListener} that will listen to the changes in
* the JComboBox's selection.
*
- * @return the ItemListener
+ * @return The ItemListener
*/
protected ItemListener createItemListener()
{
@@ -393,10 +416,10 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method creates PropertyChangeListener to listen to the changes in
+ * Creates a {@link PropertyChangeListener} to listen to the changes in
* the JComboBox's bound properties.
*
- * @return the PropertyChangeListener
+ * @return The PropertyChangeListener
*/
protected PropertyChangeListener createPropertyChangeListener()
{
@@ -404,9 +427,10 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method returns layout manager for the combo box.
+ * Creates and returns a layout manager for the combo box. Subclasses can
+ * override this method to provide a different layout.
*
- * @return layout manager for the combo box
+ * @return a layout manager for the combo box.
*/
protected LayoutManager createLayoutManager()
{
@@ -414,10 +438,10 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method creates component that will be responsible for rendering the
+ * Creates a component that will be responsible for rendering the
* selected component in the combo box.
*
- * @return render for the combo box
+ * @return A renderer for the combo box.
*/
protected ListCellRenderer createRenderer()
{
@@ -425,58 +449,54 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * Creates component that will be responsible for displaying/editting
- * selected item in the combo box. This editor is used only when combo box
- * is editable.
+ * Creates the component that will be responsible for displaying/editing
+ * the selected item in the combo box. This editor is used only when combo
+ * box is editable.
*
- * @return component that will be responsible for displaying/editting
- * selected item in the combo box.
+ * @return A new component that will be responsible for displaying/editing
+ * the selected item in the combo box.
*/
protected ComboBoxEditor createEditor()
{
- return new BasicComboBoxEditor();
+ return new BasicComboBoxEditor.UIResource();
}
/**
- * This method installs components for this JComboBox. ArrowButton, main
- * part of combo box (upper part) and popup list of items are created and
+ * Installs the components for this JComboBox. ArrowButton, main
+ * part of combo box (upper part) and popup list of items are created and
* configured here.
*/
protected void installComponents()
{
- // create and install arrow button
- arrowButton = createArrowButton();
-
- comboBox.add(arrowButton);
-
- // Set list that will be used by BasicComboBoxRender
- // in order to determine the right colors when rendering
- listBox = new JList();
-
- Color background = arrowButton.getBackground();
- listBox.setBackground(background);
- listBox.setSelectionBackground(background.darker());
-
- Color foreground = arrowButton.getForeground();
- listBox.setForeground(foreground);
- listBox.setSelectionForeground(foreground);
+ // create drop down list of items
+ popup = createPopup();
+ listBox = popup.getList();
// set editor and renderer for the combo box. Editor is used
// only if combo box becomes editable, otherwise renderer is used
// to paint the selected item; combobox is not editable by default.
comboBox.setRenderer(createRenderer());
- comboBox.setEditor(createEditor());
- editor = comboBox.getEditor().getEditorComponent();
+ // create and install arrow button
+ arrowButton = createArrowButton();
+ configureArrowButton();
+ comboBox.add(arrowButton);
- // create drop down list of items
- popup = createPopup();
+ ComboBoxEditor currentEditor = comboBox.getEditor();
+ if (currentEditor == null || currentEditor instanceof UIResource)
+ {
+ currentEditor = createEditor();
+ comboBox.setEditor(currentEditor);
+ }
+ editor = currentEditor.getEditorComponent();
comboBox.revalidate();
}
/**
- * This method uninstalls components from this JComboBox
+ * Uninstalls components from this {@link JComboBox}.
+ *
+ * @see #installComponents()
*/
protected void uninstallComponents()
{
@@ -490,12 +510,18 @@ public class BasicComboBoxUI extends ComboBoxUI
comboBox.setRenderer(null);
- comboBox.setEditor(null);
- editor = null;
+ // if the editor is not an instanceof UIResource, it was not set by the
+ // UI delegate, so don't clear it...
+ ComboBoxEditor currentEditor = comboBox.getEditor();
+ if (currentEditor instanceof UIResource)
+ {
+ comboBox.setEditor(null);
+ editor = null;
+ }
}
/**
- * This method adds editor to the combo box
+ * Adds the current editor to the combo box.
*/
public void addEditor()
{
@@ -503,7 +529,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method removes editor from the combo box
+ * Removes the current editor from the combo box.
*/
public void removeEditor()
{
@@ -511,15 +537,17 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method configures editor for this combo box.
+ * Configures the editor for this combo box.
*/
protected void configureEditor()
{
+ editor.setFont(comboBox.getFont());
+ comboBox.getEditor().setItem(comboBox.getSelectedItem());
// FIXME: Need to implement. Set font and add listeners.
}
/**
- * This method removes all the listeners for the editor.
+ * Unconfigures the editor for this combo nox. This method is not implemented.
*/
protected void unconfigureEditor()
{
@@ -527,42 +555,50 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method adds listeners to the arrow button part of the combo box.
+ * Configures the arrow button.
+ *
+ * @see #configureArrowButton()
*/
public void configureArrowButton()
{
- arrowButton.addMouseListener(mouseListener);
+ arrowButton.setEnabled(comboBox.isEnabled());
+ arrowButton.setFont(comboBox.getFont());
}
/**
- * This method removes listeners from the arrow button part of the combo
- * box.
+ * Unconfigures the arrow button.
+ *
+ * @see #configureArrowButton()
+ *
+ * @specnote The specification says this method is implementation specific
+ * and should not be used or overridden.
*/
public void unconfigureArrowButton()
{
- arrowButton.removeMouseListener(mouseListener);
+ // Nothing to do here yet.
}
/**
- * This method create arrow button for this JComboBox. Arrow button is
- * responsible for displaying / hiding drop down list of items when it is
- * clicked.
+ * Creates an arrow button for this {@link JComboBox}. The arrow button is
+ * displayed at the right end of the combo box and is used to display/hide
+ * the drop down list of items.
*
- * @return JButton arrow button for this JComboBox.
+ * @return A new button.
*/
protected JButton createArrowButton()
{
- return new BasicArrowButton(BasicArrowButton.SOUTH);
+ return new BasicArrowButton(BasicArrowButton.SOUTH, buttonBackground,
+ buttonShadow, buttonDarkShadow, buttonHighlight);
}
/**
- * This method checks if popup part of the combo box is visible on the
- * screen
+ * Returns <code>true</code> if the popup is visible, and <code>false</code>
+ * otherwise.
*
* @param c The JComboBox to check
*
- * @return true if popup part of the JComboBox is visible and false
- * otherwise.
+ * @return <code>true</code> if popup part of the JComboBox is visible and
+ * <code>false</code> otherwise.
*/
public boolean isPopupVisible(JComboBox c)
{
@@ -570,7 +606,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * Displays/Hides JComboBox's list of items on the screen.
+ * Displays/hides the {@link JComboBox}'s list of items on the screen.
*
* @param c The combo box, for which list of items should be
* displayed/hidden
@@ -579,7 +615,10 @@ public class BasicComboBoxUI extends ComboBoxUI
public void setPopupVisible(JComboBox c, boolean v)
{
if (v)
- popup.show();
+ {
+ popup.show();
+ popup.getList().requestFocus();
+ }
else
popup.hide();
}
@@ -593,7 +632,7 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public boolean isFocusTraversable(JComboBox c)
{
- if (comboBox.isEditable())
+ if (!comboBox.isEditable())
return true;
return false;
@@ -607,56 +646,28 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public void paint(Graphics g, JComponent c)
{
- if (c instanceof JComboBox)
- {
- JComboBox cb = (JComboBox) c;
-
- paintBorder(g, comboBox.getBounds(), hasFocus);
-
- Rectangle rect = rectangleForCurrentValue();
- paintCurrentValueBackground(g, rect, hasFocus);
- paintCurrentValue(g, rect, hasFocus);
- }
- }
-
- private void paintBorder(Graphics g, Rectangle bounds, boolean hasFocus)
- {
- int x = 0;
- int y = 0;
- int width = bounds.width;
- int height = bounds.height;
-
- Color oldColor = g.getColor();
-
- if (! arrowButton.getModel().isPressed())
- BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height, Color.gray,
- Color.white, Color.gray, Color.white);
- else
- {
- g.setColor(darkShadow);
- g.drawRect(x, y, width, height);
- g.setColor(shadow);
- g.drawRect(x + 1, y + 1, width - 3, height - 3);
- }
- g.setColor(oldColor);
+ Rectangle rect = rectangleForCurrentValue();
+ paintCurrentValueBackground(g, rect, hasFocus);
+ paintCurrentValue(g, rect, hasFocus);
}
/**
- * Returns preferred size for the given menu item.
+ * Returns preferred size for the combo box.
*
* @param c comboBox for which to get preferred size
*
- * @return $Dimension$ preferred size for the given combo box
+ * @return The preferred size for the given combo box
*/
public Dimension getPreferredSize(JComponent c)
{
- // return null to indicate that combo box's layout will determin its
- // preferred size
- return null;
+ // note: overriding getMinimumSize() (for example in the MetalComboBoxUI
+ // class) affects the getPreferredSize() result, so it seems logical that
+ // this method is implemented by delegating to the getMinimumSize() method
+ return getMinimumSize(c);
}
/**
- * This method returns the minimum size for this {@link JComboBox} for this
+ * Returns the minimum size for this {@link JComboBox} for this
* look and feel.
*
* @param c The {@link JComponent} to find the minimum size for.
@@ -665,20 +676,26 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public Dimension getMinimumSize(JComponent c)
{
- return null;
+ Dimension d = getDisplaySize();
+ int arrowButtonWidth = d.height;
+ Dimension result = new Dimension(d.width + arrowButtonWidth, d.height);
+ return result;
}
+ /** The value returned by the getMaximumSize() method. */
+ private static final Dimension MAXIMUM_SIZE = new Dimension(32767, 32767);
+
/**
- * This method returns the maximum size for this {@link JComboBox} for this
+ * Returns the maximum size for this {@link JComboBox} for this
* look and feel.
*
* @param c The {@link JComponent} to find the maximum size for
*
- * @return The dimensions of the minimum size.
+ * @return The maximum size (<code>Dimension(32767, 32767)</code>).
*/
public Dimension getMaximumSize(JComponent c)
{
- return null;
+ return MAXIMUM_SIZE;
}
public int getAccessibleChildrenCount(JComponent c)
@@ -707,7 +724,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method selects next possible item relative to the current selection
+ * Selects next possible item relative to the current selection
* to be next selected item in the combo box.
*/
protected void selectNextPossibleValue()
@@ -718,7 +735,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method selects previous item relative to current selection to be
+ * Selects previous item relative to current selection to be
* next selected item.
*/
protected void selectPreviousPossibleValue()
@@ -729,8 +746,8 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method displays combo box popup if the popup is not currently shown
- * on the screen and hides it if it is currently shown
+ * Displays combo box popup if the popup is not currently shown
+ * on the screen and hides it if it is currently shown
*/
protected void toggleOpenClose()
{
@@ -738,34 +755,23 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method returns bounds in which comboBox's selected Item will be
- * displayed
+ * Returns the bounds in which comboBox's selected item will be
+ * displayed.
*
* @return rectangle bounds in which comboBox's selected Item will be
* displayed
*/
protected Rectangle rectangleForCurrentValue()
{
- Rectangle cbBounds = comboBox.getBounds();
-
- // Subtract width or the arrow button and border insets
- Rectangle rectForCurrentValue = new Rectangle(cbBounds.x
- + borderInsets.left,
- cbBounds.y
- + borderInsets.top,
- cbBounds.width
- - arrowButtonWidth
- - borderInsets.left
- - borderInsets.right,
- cbBounds.height
- - borderInsets.top
- - borderInsets.bottom);
-
+ Rectangle cbBounds = SwingUtilities.getLocalBounds(comboBox);
+ Rectangle abBounds = arrowButton.getBounds();
+ Rectangle rectForCurrentValue = new Rectangle(cbBounds.x, cbBounds.y,
+ cbBounds.width - abBounds.width, cbBounds.height);
return rectForCurrentValue;
}
/**
- * This method returns insets of the current border.
+ * Returns the insets of the current border.
*
* @return Insets representing space between combo box and its border
*/
@@ -775,7 +781,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method paints currently selected value in the main part of the combo
+ * Paints currently selected value in the main part of the combo
* box (part without popup).
*
* @param g graphics context
@@ -794,28 +800,29 @@ public class BasicComboBoxUI extends ComboBoxUI
* If there is currently no selected item we will take an empty
* String as replacement.
*/
- Component comp = comboBox.getRenderer()
- .getListCellRendererComponent(listBox,
- (currentValue != null ? currentValue : ""),
- -1,
- isPressed,
- hasFocus);
- if (! comboBox.isEnabled())
- comp.setEnabled(false);
-
- g.translate(borderInsets.left, borderInsets.top);
- comp.setBounds(0, 0, bounds.width, bounds.height);
- comp.paint(g);
- g.translate(-borderInsets.left, -borderInsets.top);
-
- comboBox.revalidate();
+ Component comp = comboBox.getRenderer().getListCellRendererComponent(
+ listBox, (currentValue != null ? currentValue : ""), -1,
+ isPressed, hasFocus);
+ if (! comboBox.isEnabled())
+ {
+ comp.setBackground(UIManager.getLookAndFeelDefaults().getColor(
+ "ComboBox.disabledBackground"));
+ comp.setForeground(UIManager.getLookAndFeelDefaults().getColor(
+ "ComboBox.disabledForeground"));
+ comp.setEnabled(false);
+ }
+ comp.setBounds(0, 0, bounds.width, bounds.height);
+ comp.setFont(comboBox.getFont());
+ comp.paint(g);
+
+ comboBox.revalidate();
}
else
comboBox.getEditor().setItem(comboBox.getSelectedItem());
}
/**
- * This method paints background of part of the combo box, where currently
+ * Paints the background of part of the combo box, where currently
* selected value is displayed. If the combo box has focus this method
* should also paint focus rectangle around the combo box.
*
@@ -832,58 +839,102 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * Returns default size for the combo box that doesn't contain any elements
- * in it
+ * Returns the default size for the display area of a combo box that does
+ * not contain any elements. This method returns the width and height of
+ * a single space in the current font, plus a margin of 1 pixel.
*
- * @return Default size of the combo box with no elements in it.
+ * @return The default display size.
+ *
+ * @see #getDisplaySize()
*/
protected Dimension getDefaultSize()
{
- return new Dimension(6, 17);
+ // There is nothing in the spec to say how this method should be
+ // implemented...so I've done some guessing, written some Mauve tests,
+ // and written something that gives dimensions that are close to the
+ // reference implementation.
+ FontMetrics fm = comboBox.getFontMetrics(comboBox.getFont());
+ int w = fm.charWidth(' ') + 2;
+ int h = fm.getHeight() + 2;
+ return new Dimension(w, h);
}
/**
- * Returns size of the largest item in the combo box. This size will be the
- * size of the combo box, not including the arrowButton.
+ * Returns the size of the display area for the combo box. This size will be
+ * the size of the combo box, not including the arrowButton.
*
- * @return dimensions of the largest item in the combo box.
+ * @return The size of the display area for the combo box.
*/
- protected Dimension getLargestItemSize()
+ protected Dimension getDisplaySize()
{
- ComboBoxModel model = comboBox.getModel();
- int numItems = model.getSize();
-
- // if combo box doesn't have any items then simply
- // return its default size
- if (numItems == 0)
+ if (!comboBox.isEditable())
{
- largestItemSize = getDefaultSize();
- return largestItemSize;
+ Object prototype = comboBox.getPrototypeDisplayValue();
+ if (prototype != null)
+ {
+ // calculate result based on prototype
+ ListCellRenderer renderer = comboBox.getRenderer();
+ Component comp = renderer.getListCellRendererComponent(listBox,
+ prototype, -1, false, false);
+ Dimension compSize = comp.getPreferredSize();
+ compSize.width += 2; // add 1 pixel margin around area
+ compSize.height += 2;
+ return compSize;
+ }
+ else
+ {
+ ComboBoxModel model = comboBox.getModel();
+ int numItems = model.getSize();
+
+ // if combo box doesn't have any items then simply
+ // return its default size
+ if (numItems == 0)
+ {
+ displaySize = getDefaultSize();
+ return displaySize;
+ }
+
+ Dimension size = new Dimension(0, 0);
+
+ // ComboBox's display size should be equal to the
+ // size of the largest item in the combo box.
+ ListCellRenderer renderer = comboBox.getRenderer();
+
+ for (int i = 0; i < numItems; i++)
+ {
+ Object item = model.getElementAt(i);
+ Component comp = renderer.getListCellRendererComponent(listBox,
+ item, -1, false, false);
+
+ Dimension compSize = comp.getPreferredSize();
+ if (compSize.width + 2 > size.width)
+ size.width = compSize.width + 2;
+ if (compSize.height + 2 > size.height)
+ size.height = compSize.height + 2;
+ }
+ displaySize = size;
+ return displaySize;
+ }
}
-
- Dimension size = new Dimension(0, 0);
-
- // ComboBox's display size should be equal to the
- // size of the largest item in the combo box.
- ListCellRenderer renderer = comboBox.getRenderer();
-
- for (int i = 0; i < numItems; i++)
+ else // an editable combo,
{
- Object item = model.getElementAt(i);
- String s = item.toString();
- Component comp = renderer.getListCellRendererComponent(listBox, item,
- -1, false, false);
-
- if (comp.getPreferredSize().getWidth() > size.getWidth())
- size = comp.getPreferredSize();
+ Component comp = comboBox.getEditor().getEditorComponent();
+ Dimension prefSize = comp.getPreferredSize();
+ int width = prefSize.width;
+ int height = prefSize.height + 2;
+ Object prototype = comboBox.getPrototypeDisplayValue();
+ if (prototype != null)
+ {
+ FontMetrics fm = comboBox.getFontMetrics(comboBox.getFont());
+ width = Math.max(width, fm.stringWidth(prototype.toString()) + 2);
+ }
+ displaySize = new Dimension(width, height);
+ return displaySize;
}
-
- largestItemSize = size;
- return largestItemSize;
}
/**
- * This method installs the keyboard actions for the JComboBox as specified
+ * Installs the keyboard actions for the {@link JComboBox} as specified
* by the look and feel.
*/
protected void installKeyboardActions()
@@ -892,7 +943,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method uninstalls the keyboard actions for the JComboBox there were
+ * Uninstalls the keyboard actions for the {@link JComboBox} there were
* installed by in {@link #installListeners}.
*/
protected void uninstallKeyboardActions()
@@ -901,22 +952,39 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This class is Layout Manager for this combo box.
+ * A {@link LayoutManager} used to position the sub-components of the
+ * {@link JComboBox}.
+ *
+ * @see BasicComboBoxUI#createLayoutManager()
*/
- public class ComboBoxLayoutManager extends Object implements LayoutManager
+ public class ComboBoxLayoutManager implements LayoutManager
{
/**
* Creates a new ComboBoxLayoutManager object.
*/
public ComboBoxLayoutManager()
{
+ // Nothing to do here.
}
+ /**
+ * Adds a component to the layout. This method does nothing, since the
+ * layout manager doesn't need to track the components.
+ *
+ * @param name the name to associate the component with (ignored).
+ * @param comp the component (ignored).
+ */
public void addLayoutComponent(String name, Component comp)
{
// Do nothing
}
+ /**
+ * Removes a component from the layout. This method does nothing, since
+ * the layout manager doesn't need to track the components.
+ *
+ * @param comp the component.
+ */
public void removeLayoutComponent(Component comp)
{
// Do nothing
@@ -925,43 +993,30 @@ public class BasicComboBoxUI extends ComboBoxUI
/**
* Returns preferred layout size of the JComboBox.
*
- * @param parent Container for which preferred size should be calculated
+ * @param parent the Container for which the preferred size should be
+ * calculated.
*
- * @return preferred size for the given container
+ * @return The preferred size for the given container
*/
public Dimension preferredLayoutSize(Container parent)
{
- Dimension d = new Dimension(0, 0);
-
- if (largestItemSize == null)
- largestItemSize = getLargestItemSize();
-
- // add size for the area that will display selected item
- d.width += largestItemSize.getWidth();
- d.height += largestItemSize.getHeight();
-
- // add size of the arrow button
- d.width += arrowButtonWidth;
-
- // add width and height of the border
- d.width += borderInsets.left + borderInsets.right;
- d.height += borderInsets.left + borderInsets.right;
-
- // Add combo box's insets
- Insets insets = parent.getInsets();
- d.width += insets.left + insets.right;
- d.width += insets.left + insets.right;
-
- return d;
+ return getPreferredSize((JComponent) parent);
}
+ /**
+ * Returns the minimum layout size.
+ *
+ * @param parent the container.
+ *
+ * @return The minimum size.
+ */
public Dimension minimumLayoutSize(Container parent)
{
return preferredLayoutSize(parent);
}
/**
- * This method layouts out the components in the container. It puts arrow
+ * Arranges the components in the container. It puts arrow
* button right end part of the comboBox. If the comboBox is editable
* then editor is placed to the left of arrow button, starting from the
* beginning.
@@ -972,21 +1027,19 @@ public class BasicComboBoxUI extends ComboBoxUI
{
// Position editor component to the left of arrow button if combo box is
// editable
- int editorWidth = comboBox.getBounds().width - arrowButtonWidth - 2;
+ int arrowSize = comboBox.getHeight();
+ int editorWidth = comboBox.getBounds().width - arrowSize;
if (comboBox.isEditable())
- editor.setBounds(borderInsets.left, borderInsets.top, editorWidth,
- comboBox.getBounds().height - borderInsets.left
- - borderInsets.top);
-
- arrowButton.setBounds(editorWidth, 2, arrowButtonWidth,
- comboBox.getBounds().height - 4);
+ editor.setBounds(0, 0, editorWidth, comboBox.getBounds().height);
+
+ arrowButton.setBounds(editorWidth, 0, arrowSize, arrowSize);
comboBox.revalidate();
}
}
/**
- * This class handles focus changes occuring in the combo box. This class is
+ * Handles focus changes occuring in the combo box. This class is
* responsible for repainting combo box whenever focus is gained or lost
* and also for hiding popup list of items whenever combo box loses its
* focus.
@@ -998,11 +1051,12 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public FocusHandler()
{
+ // Nothing to do here.
}
/**
- * This mehtod is invoked when combo box gains focus. It repaints main
- * part of combo box accordingally.
+ * Invoked when combo box gains focus. It repaints main
+ * part of combo box accordingly.
*
* @param e the FocusEvent
*/
@@ -1013,22 +1067,22 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method is invoked when combo box loses focus It repaint main part
- * of combo box accordingally and hides popup list of items.
+ * Invoked when the combo box loses focus. It repaints the main part
+ * of the combo box accordingly and hides the popup list of items.
*
* @param e the FocusEvent
*/
public void focusLost(FocusEvent e)
{
hasFocus = false;
+ setPopupVisible(comboBox, false);
comboBox.repaint();
- popup.hide();
}
}
/**
- * This class handles ItemEvent fired by the JComboBox when its selected
- * item changes.
+ * Handles {@link ItemEvent}s fired by the {@link JComboBox} when its
+ * selected item changes.
*/
public class ItemHandler extends Object implements ItemListener
{
@@ -1037,16 +1091,19 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public ItemHandler()
{
+ // Nothing to do here.
}
/**
- * This method is invoked when selected item becomes deselected or when
+ * Invoked when selected item becomes deselected or when
* new item becomes selected.
*
* @param e the ItemEvent representing item's state change.
*/
public void itemStateChanged(ItemEvent e)
{
+ if (e.getStateChange() == ItemEvent.SELECTED && comboBox.isEditable())
+ comboBox.getEditor().setItem(e.getItem());
comboBox.repaint();
}
}
@@ -1058,11 +1115,11 @@ public class BasicComboBoxUI extends ComboBoxUI
{
public KeyHandler()
{
+ // Nothing to do here.
}
- /*
- * This method is invoked whenever key is pressed while JComboBox is in
- * focus.
+ /**
+ * Invoked whenever key is pressed while JComboBox is in focus.
*/
public void keyPressed(KeyEvent e)
{
@@ -1072,7 +1129,7 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This class handles to the changes occuring in the JComboBox's data model
+ * Handles the changes occurring in the JComboBox's data model.
*/
public class ListDataHandler extends Object implements ListDataListener
{
@@ -1081,10 +1138,11 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public ListDataHandler()
{
+ // Nothing to do here.
}
/**
- * This method is invoked content's of JComboBox's data model are changed
+ * Invoked if the content's of JComboBox's data model are changed.
*
* @param e ListDataEvent describing the change.
*/
@@ -1094,36 +1152,27 @@ public class BasicComboBoxUI extends ComboBoxUI
}
/**
- * This method is invoked when items were added to the JComboBox's data
- * model.
+ * Invoked when items are added to the JComboBox's data model.
*
* @param e ListDataEvent describing the change.
*/
public void intervalAdded(ListDataEvent e)
{
- // must determine if the size of the combo box should change
- int start = e.getIndex0();
- int end = e.getIndex1();
-
ComboBoxModel model = comboBox.getModel();
ListCellRenderer renderer = comboBox.getRenderer();
- if (largestItemSize == null)
- largestItemSize = new Dimension(0, 0);
+ if (displaySize == null)
+ displaySize = getDisplaySize();
+ if (displaySize.width < getDefaultSize().width)
+ displaySize.width = getDefaultSize().width;
+ if (displaySize.height < getDefaultSize().height)
+ displaySize.height = getDefaultSize().height;
- for (int i = start; i < end; i++)
- {
- Object item = model.getElementAt(i);
- Component comp = renderer.getListCellRendererComponent(new JList(),
- item, -1,
- false, false);
- if (comp.getPreferredSize().getWidth() > largestItemSize.getWidth())
- largestItemSize = comp.getPreferredSize();
- }
+ comboBox.repaint();
}
/**
- * This method is invoked when items were removed from the JComboBox's
+ * Invoked when items are removed from the JComboBox's
* data model.
*
* @param e ListDataEvent describing the change.
@@ -1131,23 +1180,29 @@ public class BasicComboBoxUI extends ComboBoxUI
public void intervalRemoved(ListDataEvent e)
{
// recalculate display size of the JComboBox.
- largestItemSize = getLargestItemSize();
+ displaySize = getDisplaySize();
comboBox.repaint();
}
}
/**
- * This class handles PropertyChangeEvents fired by JComboBox.
+ * Handles {@link PropertyChangeEvent}s fired by the {@link JComboBox}.
*/
public class PropertyChangeHandler extends Object
implements PropertyChangeListener
{
+ /**
+ * Creates a new instance.
+ */
public PropertyChangeHandler()
{
+ // Nothing to do here.
}
/**
- * This method is invoked whenever bound property of JComboBox changes.
+ * Invoked whenever bound property of JComboBox changes.
+ *
+ * @param e the event.
*/
public void propertyChange(PropertyChangeEvent e)
{
@@ -1185,59 +1240,36 @@ public class BasicComboBoxUI extends ComboBoxUI
if ((ComboBoxModel) e.getNewValue() != null)
comboBox.getModel().addListDataListener(listDataListener);
}
+ else if (e.getPropertyName().equals("font"))
+ {
+ Font font = (Font) e.getNewValue();
+ editor.setFont(font);
+ listBox.setFont(font);
+ arrowButton.setFont(font);
+ comboBox.revalidate();
+ comboBox.repaint();
+ }
// FIXME: Need to handle changes in other bound properties.
}
}
/**
- * MouseHandler listens to mouse events occuring in the combo box. This
- * class is responsible for repainting this JComboBox whenever the mouse is
- * being pressed or released over it.
+ * A handler for mouse events occurring in the combo box. An instance of
+ * this class is returned by the <code>createMouseListener()</code> method.
*/
private class MouseHandler extends MouseAdapter
{
/**
- * This method is invoked when mouse is pressed over the combo box. It
- * repaints the combo box accordinglly
+ * Invoked when mouse is pressed over the combo box. It toggles the
+ * visibility of the popup list.
*
- * @param e the MouseEvent
+ * @param e the event
*/
public void mousePressed(MouseEvent e)
{
if (comboBox.isEnabled())
- {
- if (e.getSource() instanceof JComboBox)
- {
- arrowButton.getModel().setPressed(true);
- arrowButton.getModel().setArmed(true);
- }
-
- comboBox.repaint();
-
- if (e.getSource() instanceof BasicArrowButton)
- toggleOpenClose();
- }
- }
-
- /**
- * This method is invoked when mouse is released over the combo box. It
- * repaints the combo box accordinglly
- *
- * @param e the MouseEvent
- */
- public void mouseReleased(MouseEvent e)
- {
- if (comboBox.isEnabled())
- {
- if (e.getSource() instanceof JComboBox)
- {
- arrowButton.getModel().setPressed(false);
- arrowButton.getModel().setArmed(false);
- }
-
- comboBox.repaint();
- }
+ toggleOpenClose();
}
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java
index 73aac8d4e65..73979bb89c1 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.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.Point;
@@ -55,6 +56,7 @@ import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
+import javax.swing.BorderFactory;
import javax.swing.ComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
@@ -178,8 +180,8 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
// to display number of rows equal to 'maximumRowCount' property
int popupHeight = getPopupHeightForRowCount(comboBox.getMaximumRowCount());
- list.setPreferredSize(new Dimension(cbBounds.width, popupHeight));
- super.setPopupSize(cbBounds.width, popupHeight);
+ scroller.setPreferredSize(new Dimension(cbBounds.width, popupHeight));
+ pack();
// Highlight selected item in the combo box's drop down list
if (comboBox.getSelectedIndex() != -1)
@@ -478,6 +480,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
*/
protected void configureScroller()
{
+ scroller.setBorder(null);
scroller.getViewport().setView(list);
scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
}
@@ -488,6 +491,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
*/
protected void configurePopup()
{
+ setBorder(BorderFactory.createLineBorder(Color.BLACK));
// initialize list that will be used to display combo box's items
this.list = createList();
((JLabel) list.getCellRenderer()).setHorizontalAlignment(SwingConstants.LEFT);
@@ -714,7 +718,11 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
protected void updateListBoxSelectionForEvent(MouseEvent anEvent,
boolean shouldScroll)
{
- // FIXME: Need to implement
+ // TODO: We need to handle the shouldScroll parameter somehow.
+ int index = list.locationToIndex(anEvent.getPoint());
+ // Check for valid index.
+ if (index >= 0)
+ list.setSelectedIndex(index);
}
/**
@@ -732,6 +740,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
*/
protected InvocationMouseHandler()
{
+ // Nothing to do here.
}
/**
@@ -744,7 +753,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
public void mousePressed(MouseEvent e)
{
if (comboBox.isEnabled())
- togglePopup();
+ togglePopup();
}
/**
@@ -768,15 +777,15 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
// then change selection and close popup
if (! (releasedComponent instanceof JComboBox))
{
- // List model contains the item over which mouse is released,
- // since it is updated every time the mouse is moved over a different
- // item in the list. Now that the mouse is released we need to
- // update model of the combo box as well.
- comboBox.setSelectedIndex(list.getSelectedIndex());
-
- if (isAutoScrolling)
- stopAutoScrolling();
- hide();
+ // List model contains the item over which mouse is released,
+ // since it is updated every time the mouse is moved over a different
+ // item in the list. Now that the mouse is released we need to
+ // update model of the combo box as well.
+ comboBox.setSelectedIndex(list.getSelectedIndex());
+
+ if (isAutoScrolling)
+ stopAutoScrolling();
+ hide();
}
}
}
@@ -792,6 +801,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
*/
protected InvocationMouseMotionHandler()
{
+ // Nothing to do here.
}
/**
@@ -868,6 +878,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
*/
protected ItemHandler()
{
+ // Nothing to do here.
}
/**
@@ -877,6 +888,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
*/
public void itemStateChanged(ItemEvent e)
{
+ // TODO: What should be done here?
}
}
@@ -890,16 +902,20 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
{
protected ListMouseHandler()
{
+ // Nothing to do here.
}
public void mousePressed(MouseEvent e)
{
+ // TODO: What should be do here?
}
public void mouseReleased(MouseEvent anEvent)
{
int index = list.locationToIndex(anEvent.getPoint());
- comboBox.setSelectedIndex(index);
+ // Check for valid index.
+ if (index >= 0)
+ comboBox.setSelectedIndex(index);
hide();
}
}
@@ -913,15 +929,12 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
{
protected ListMouseMotionHandler()
{
+ // Nothing to do here.
}
public void mouseMoved(MouseEvent anEvent)
{
- // Highlight list cells over which the mouse is located.
- // This changes list model, but has no effect on combo box's data model
- int index = list.locationToIndex(anEvent.getPoint());
- list.setSelectedIndex(index);
- list.repaint();
+ updateListBoxSelectionForEvent(anEvent, false);
}
}
@@ -934,6 +947,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
{
protected PropertyChangeHandler()
{
+ // Nothing to do here.
}
public void propertyChange(PropertyChangeEvent e)
@@ -1009,18 +1023,22 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
{
public ListDataHandler()
{
+ // Nothing to do here.
}
public void contentsChanged(ListDataEvent e)
{
+ // Nothing to do here.
}
public void intervalAdded(ListDataEvent e)
{
+ // Nothing to do here.
}
public void intervalRemoved(ListDataEvent e)
{
+ // Nothing to do here.
}
}
@@ -1032,10 +1050,12 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
{
protected ListSelectionHandler()
{
+ // Nothing to do here.
}
public void valueChanged(ListSelectionEvent e)
{
+ // Nothing to do here.
}
}
@@ -1046,10 +1066,12 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup
{
public InvocationKeyHandler()
{
+ // Nothing to do here.
}
public void keyReleased(KeyEvent e)
{
+ // Nothing to do here.
}
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java
index 561b497f1c3..3f8730249da 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java
@@ -365,6 +365,7 @@ public class BasicDesktopIconUI extends DesktopIconUI
*/
public BasicDesktopIconUI()
{
+ // Nothing to do here.
}
/**
@@ -585,6 +586,7 @@ public class BasicDesktopIconUI extends DesktopIconUI
}
catch (PropertyVetoException pve)
{
+ // We do nothing if the attempt has been vetoed.
}
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java
index b59261b17f3..4116858da9d 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.swing.plaf.basic;
+import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.beans.PropertyVetoException;
@@ -49,10 +50,10 @@ import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.KeyStroke;
-import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.DesktopPaneUI;
+import javax.swing.plaf.UIResource;
/**
* This class is the UI delegate for JDesktopPane for the Basic look and feel.
@@ -74,13 +75,14 @@ public class BasicDesktopPaneUI extends DesktopPaneUI
{
if (desktop.getSelectedFrame() != null)
{
- try
- {
- desktop.getSelectedFrame().setClosed(true);
- }
- catch (PropertyVetoException pve)
- {
- }
+ try
+ {
+ desktop.getSelectedFrame().setClosed(true);
+ }
+ catch (PropertyVetoException pve)
+ {
+ // We do nothing if the attempts has been vetoed.
+ }
}
}
@@ -112,13 +114,14 @@ public class BasicDesktopPaneUI extends DesktopPaneUI
{
if (desktop.getSelectedFrame() != null)
{
- try
- {
- desktop.getSelectedFrame().setMaximum(true);
- }
- catch (PropertyVetoException pve)
- {
- }
+ try
+ {
+ desktop.getSelectedFrame().setMaximum(true);
+ }
+ catch (PropertyVetoException pve)
+ {
+ // We do nothing if the attempts has been vetoed.
+ }
}
}
@@ -150,13 +153,14 @@ public class BasicDesktopPaneUI extends DesktopPaneUI
{
if (desktop.getSelectedFrame() != null)
{
- try
- {
- desktop.getSelectedFrame().setIcon(true);
- }
- catch (PropertyVetoException pve)
- {
- }
+ try
+ {
+ desktop.getSelectedFrame().setIcon(true);
+ }
+ catch (PropertyVetoException pve)
+ {
+ // We do nothing if the attempt has been vetoed.
+ }
}
}
@@ -236,16 +240,17 @@ public class BasicDesktopPaneUI extends DesktopPaneUI
JInternalFrame frame = desktop.getSelectedFrame();
if (frame != null)
{
- try
- {
- if (frame.isIcon())
- frame.setIcon(false);
- else if (frame.isMaximum())
- frame.setMaximum(false);
- }
- catch (PropertyVetoException pve)
- {
- }
+ try
+ {
+ if (frame.isIcon())
+ frame.setIcon(false);
+ else if (frame.isMaximum())
+ frame.setMaximum(false);
+ }
+ catch (PropertyVetoException pve)
+ {
+ // We do nothing if the attempt has been vetoed.
+ }
}
}
@@ -304,6 +309,7 @@ public class BasicDesktopPaneUI extends DesktopPaneUI
*/
public BasicDesktopPaneUI()
{
+ // Nothing to do here.
}
/**
@@ -361,9 +367,9 @@ public class BasicDesktopPaneUI extends DesktopPaneUI
*/
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- desktop.setBackground(defaults.getColor("desktop"));
+ Color bg = desktop.getBackground();
+ if (bg == null || bg instanceof UIResource)
+ desktop.setBackground(UIManager.getColor("desktop"));
}
/**
@@ -381,7 +387,7 @@ public class BasicDesktopPaneUI extends DesktopPaneUI
protected void installKeyboardActions()
{
// FIXME: create actions and keystrokes.
- registerKeyboardAction();
+ registerKeyboardActions();
}
/**
@@ -405,7 +411,7 @@ public class BasicDesktopPaneUI extends DesktopPaneUI
* This method registers the actions to the appropriate Action and Input
* maps.
*/
- protected void registerKeyboardAction()
+ protected void registerKeyboardActions()
{
// FIXME: Do the binding.
// XXX: the gtk windows tend to intercept a lot of the
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java
index f74e9229893..9c639656545 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java
@@ -48,7 +48,6 @@ import java.awt.Point;
import java.awt.Polygon;
import java.awt.Window;
import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
@@ -60,9 +59,9 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
+
import javax.swing.AbstractAction;
import javax.swing.Action;
-import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.JButton;
@@ -92,25 +91,31 @@ import javax.swing.plaf.FileChooserUI;
/**
- * DOCUMENT ME!
+ * A UI delegate for the {@link JFileChooser} component under the
+ * {@link BasicLookAndFeel}.
*/
public class BasicFileChooserUI extends FileChooserUI
{
/**
- * DOCUMENT ME!
+ * A file filter that accepts all files.
*/
protected class AcceptAllFileFilter extends FileFilter
{
+ /**
+ * Creates a new instance.
+ */
public AcceptAllFileFilter()
{
+ // Nothing to do here.
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> always, as all files are accepted by this
+ * filter.
*
- * @param f DOCUMENT ME!
+ * @param f the file.
*
- * @return DOCUMENT ME!
+ * @return Always <code>true</code>.
*/
public boolean accept(File f)
{
@@ -118,9 +123,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns a description for this filter.
*
- * @return DOCUMENT ME!
+ * @return A description for the file filter.
*/
public String getDescription()
{
@@ -129,7 +134,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Handles a user action to approve the dialog selection.
+ *
+ * @see BasicFileChooserUI#getApproveSelectionAction()
*/
protected class ApproveSelectionAction extends AbstractAction
{
@@ -138,50 +145,55 @@ public class BasicFileChooserUI extends FileChooserUI
*/
protected ApproveSelectionAction()
{
+ // Nothing to do here.
}
/**
- * DOCUMENT ME!
- *
- * @param e DOCUMENT ME!
+ * Sets the current selection and closes the dialog.
+ *
+ * @param e the action event.
*/
public void actionPerformed(ActionEvent e)
{
- Object obj = filelist.getSelectedValue();
+ Object obj = new String(parentPath + entry.getText());
if (obj != null)
{
- File f = filechooser.getFileSystemView().createFileObject(obj
- .toString());
- if (filechooser.isTraversable(f) &&
- filechooser.getFileSelectionMode() == JFileChooser.FILES_ONLY)
+ File f = filechooser.getFileSystemView().createFileObject(
+ obj.toString());
+ if (filechooser.isTraversable(f)
+ && filechooser.isDirectorySelectionEnabled())
filechooser.setCurrentDirectory(f);
- else
- {
- filechooser.setSelectedFile(f);
- filechooser.approveSelection();
- closeDialog();
- }
+ else
+ {
+ filechooser.setSelectedFile(f);
+ filechooser.approveSelection();
+ closeDialog();
+ }
}
}
}
/**
- * DOCUMENT ME!
+ * Provides presentation information about files and directories.
*/
protected class BasicFileView extends FileView
{
- /** DOCUMENT ME! */
+ /** Storage for cached icons. */
protected Hashtable iconCache = new Hashtable();
+ /**
+ * Creates a new instance.
+ */
public BasicFileView()
{
+ // Nothing to do here.
}
/**
- * DOCUMENT ME!
+ * Adds an icon to the cache, associating it with the given file/directory.
*
- * @param f DOCUMENT ME!
- * @param i DOCUMENT ME!
+ * @param f the file/directory.
+ * @param i the icon.
*/
public void cacheIcon(File f, Icon i)
{
@@ -189,7 +201,7 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Clears the icon cache.
*/
public void clearIconCache()
{
@@ -197,11 +209,12 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Retrieves the icon associated with the specified file/directory, if
+ * there is one.
*
- * @param f DOCUMENT ME!
+ * @param f the file/directory.
*
- * @return DOCUMENT ME!
+ * @return The cached icon (or <code>null</code>).
*/
public Icon getCachedIcon(File f)
{
@@ -209,11 +222,13 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns a description of the given file/directory. In this
+ * implementation, the description is the same as the name returned by
+ * {@link #getName(File)}.
*
- * @param f DOCUMENT ME!
+ * @param f the file/directory.
*
- * @return DOCUMENT ME!
+ * @return A description of the given file/directory.
*/
public String getDescription(File f)
{
@@ -221,11 +236,11 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns an icon appropriate for the given file or directory.
*
- * @param f DOCUMENT ME!
+ * @param f the file/directory.
*
- * @return DOCUMENT ME!
+ * @return An icon.
*/
public Icon getIcon(File f)
{
@@ -241,11 +256,11 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns the name for the given file/directory.
*
- * @param f DOCUMENT ME!
+ * @param f the file/directory.
*
- * @return DOCUMENT ME!
+ * @return The name of the file/directory.
*/
public String getName(File f)
{
@@ -253,11 +268,11 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns a localised description for the type of file/directory.
*
- * @param f DOCUMENT ME!
+ * @param f the file/directory.
*
- * @return DOCUMENT ME!
+ * @return A type description for the given file/directory.
*/
public String getTypeDescription(File f)
{
@@ -268,34 +283,38 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns {@link Boolean#TRUE} if the given file/directory is hidden,
+ * and {@link Boolean#FALSE} otherwise.
*
- * @param f DOCUMENT ME!
+ * @param f the file/directory.
*
- * @return DOCUMENT ME!
+ * @return {@link Boolean#TRUE} or {@link Boolean#FALSE}.
*/
public Boolean isHidden(File f)
{
- return new Boolean(filechooser.getFileSystemView().isHiddenFile(f));
+ return Boolean.valueOf(filechooser.getFileSystemView().isHiddenFile(f));
}
}
/**
- * DOCUMENT ME!
+ * Handles an action to cancel the file chooser.
+ *
+ * @see BasicFileChooserUI#getCancelSelectionAction()
*/
protected class CancelSelectionAction extends AbstractAction
{
/**
- * Creates a new CancelSelectionAction object.
+ * Creates a new <code>CancelSelectionAction</code> object.
*/
protected CancelSelectionAction()
{
+ // Nothing to do here.
}
/**
- * DOCUMENT ME!
+ * Cancels the selection and closes the dialog.
*
- * @param e DOCUMENT ME!
+ * @param e the action event (ignored).
*/
public void actionPerformed(ActionEvent e)
{
@@ -305,21 +324,25 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * An action to handle changes to the parent directory (for example, via
+ * a click on the "up folder" button).
+ *
+ * @see BasicFileChooserUI#getChangeToParentDirectoryAction()
*/
protected class ChangeToParentDirectoryAction extends AbstractAction
{
/**
- * Creates a new ChangeToParentDirectoryAction object.
+ * Creates a new <code>ChangeToParentDirectoryAction</code> object.
*/
protected ChangeToParentDirectoryAction()
{
+ // Nothing to do here.
}
/**
- * DOCUMENT ME!
+ * Handles the action event.
*
- * @param e DOCUMENT ME!
+ * @param e the action event.
*/
public void actionPerformed(ActionEvent e)
{
@@ -330,11 +353,13 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * A mouse listener that handles double-click events.
+ *
+ * @see BasicFileChooserUI#createDoubleClickListener(JFileChooser, JList)
*/
protected class DoubleClickListener extends MouseAdapter
{
- /** DOCUMENT ME! */
+ /** A timer. */
private Timer timer = null;
/** DOCUMENT ME! */
@@ -358,54 +383,57 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
- *
- * @param e DOCUMENT ME!
+ * Handles a mouse click event.
+ *
+ * @param e the event.
*/
public void mouseClicked(MouseEvent e)
{
if (list.getSelectedValue() == null)
- return;
+ return;
FileSystemView fsv = filechooser.getFileSystemView();
if (timer.isRunning()
&& list.getSelectedValue().toString().equals(lastSelected.toString()))
{
- File f = fsv.createFileObject(lastSelected.toString());
- timer.stop();
- if (filechooser.isTraversable(f))
- {
- filechooser.setCurrentDirectory(f);
- filechooser.rescanCurrentDirectory();
- }
- else
- {
- filechooser.setSelectedFile(f);
- filechooser.approveSelection();
- closeDialog();
- }
+ File f = fsv.createFileObject(lastSelected.toString());
+ timer.stop();
+ if (filechooser.isTraversable(f))
+ {
+ filechooser.setCurrentDirectory(f);
+ filechooser.rescanCurrentDirectory();
+ }
+ else
+ {
+ filechooser.setSelectedFile(f);
+ filechooser.approveSelection();
+ closeDialog();
+ }
}
else
{
- File f = fsv.createFileObject(list.getSelectedValue().toString());
- if (filechooser.isTraversable(f))
- {
- setDirectorySelected(true);
- setDirectory(f);
- }
- else
- {
- setDirectorySelected(false);
- setDirectory(null);
- }
- lastSelected = list.getSelectedValue().toString();
- timer.restart();
+ String path = list.getSelectedValue().toString();
+ File f = fsv.createFileObject(path);
+ if (filechooser.isTraversable(f))
+ {
+ setDirectorySelected(true);
+ setDirectory(f);
+ }
+ else
+ {
+ setDirectorySelected(false);
+ setDirectory(null);
+ }
+ lastSelected = path;
+ parentPath = path.substring(0, path.lastIndexOf("/") + 1);
+ entry.setText(path.substring(path.lastIndexOf("/") + 1));
+ timer.restart();
}
}
/**
- * DOCUMENT ME!
- *
- * @param e DOCUMENT ME!
+ * Handles a mouse entered event (NOT IMPLEMENTED).
+ *
+ * @param e the mouse event.
*/
public void mouseEntered(MouseEvent e)
{
@@ -414,21 +442,26 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * An action that changes the file chooser to display the user's home
+ * directory.
+ *
+ * @see BasicFileChooserUI#getGoHomeAction()
*/
protected class GoHomeAction extends AbstractAction
{
/**
- * Creates a new GoHomeAction object.
+ * Creates a new <code>GoHomeAction</code> object.
*/
protected GoHomeAction()
{
+ // Nothing to do here.
}
/**
- * DOCUMENT ME!
+ * Sets the directory to the user's home directory, and repaints the
+ * file chooser component.
*
- * @param e DOCUMENT ME!
+ * @param e the action event (ignored).
*/
public void actionPerformed(ActionEvent e)
{
@@ -440,21 +473,24 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * An action that handles the creation of a new folder/directory.
+ *
+ * @see BasicFileChooserUI#getNewFolderAction()
*/
protected class NewFolderAction extends AbstractAction
{
/**
- * Creates a new NewFolderAction object.
+ * Creates a new <code>NewFolderAction</code> object.
*/
protected NewFolderAction()
{
+ // Nothing to do here.
}
/**
- * DOCUMENT ME!
+ * Handles the event by creating a new folder.
*
- * @param e DOCUMENT ME!
+ * @param e the action event (ignored).
*/
public void actionPerformed(ActionEvent e)
{
@@ -473,15 +509,18 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * A listener for selection events in the file list.
+ *
+ * @see BasicFileChooserUI#createListSelectionListener(JFileChooser)
*/
protected class SelectionListener implements ListSelectionListener
{
/**
- * Creates a new SelectionListener object.
+ * Creates a new <code>SelectionListener</code> object.
*/
protected SelectionListener()
{
+ // Nothing to do here.
}
/**
@@ -504,6 +543,8 @@ public class BasicFileChooserUI extends FileChooserUI
/**
* DOCUMENT ME!
+ *
+ * @see BasicFileChooserUI#getUpdateAction()
*/
protected class UpdateAction extends AbstractAction
{
@@ -512,28 +553,30 @@ public class BasicFileChooserUI extends FileChooserUI
*/
protected UpdateAction()
{
+ // Nothing to do here.
}
/**
- * DOCUMENT ME!
+ * NOT YET IMPLEMENTED.
*
- * @param e DOCUMENT ME!
+ * @param e the action event.
*/
public void actionPerformed(ActionEvent e)
{
+ // FIXME: implement this
}
}
- /** DOCUMENT ME! */
+ /** The localised mnemonic for the cancel button. */
protected int cancelButtonMnemonic;
- /** DOCUMENT ME! */
+ /** The localised text for the cancel button. */
protected String cancelButtonText;
- /** DOCUMENT ME! */
+ /** The localised tool tip text for the cancel button. */
protected String cancelButtonToolTipText;
- /** DOCUMENT ME! */
+ /** An icon representing a computer. */
protected Icon computerIcon = new Icon()
{
public int getIconHeight()
@@ -548,10 +591,11 @@ public class BasicFileChooserUI extends FileChooserUI
public void paintIcon(Component c, Graphics g, int x, int y)
{
+ // FIXME: is this not implemented, or is the icon intentionally blank?
}
};
- /** DOCUMENT ME! */
+ /** An icon for the "details view" button. */
protected Icon detailsViewIcon = new Icon()
{
public int getIconHeight()
@@ -580,7 +624,7 @@ public class BasicFileChooserUI extends FileChooserUI
}
};
- /** DOCUMENT ME! */
+ /** An icon representing a directory. */
protected Icon directoryIcon = new Icon()
{
public int getIconHeight()
@@ -619,16 +663,16 @@ public class BasicFileChooserUI extends FileChooserUI
}
};
- /** DOCUMENT ME! */
+ /** The localised Mnemonic for the open button. */
protected int directoryOpenButtonMnemonic;
- /** DOCUMENT ME! */
+ /** The localised text for the open button. */
protected String directoryOpenButtonText;
- /** DOCUMENT ME! */
+ /** The localised tool tip text for the open button. */
protected String directoryOpenButtonToolTipText;
- /** DOCUMENT ME! */
+ /** An icon representing a file. */
protected Icon fileIcon = new Icon()
{
public int getIconHeight()
@@ -668,7 +712,7 @@ public class BasicFileChooserUI extends FileChooserUI
}
};
- /** DOCUMENT ME! */
+ /** An icon representing a floppy drive. */
protected Icon floppyDriveIcon = new Icon()
{
public int getIconHeight()
@@ -683,10 +727,11 @@ public class BasicFileChooserUI extends FileChooserUI
public void paintIcon(Component c, Graphics g, int x, int y)
{
+ // FIXME: is this not implemented, or is the icon intentionally blank?
}
};
- /** DOCUMENT ME! */
+ /** An icon representing a hard drive. */
protected Icon hardDriveIcon = new Icon()
{
public int getIconHeight()
@@ -701,19 +746,20 @@ public class BasicFileChooserUI extends FileChooserUI
public void paintIcon(Component c, Graphics g, int x, int y)
{
+ // FIXME: is this not implemented, or is the icon intentionally blank?
}
};
- /** DOCUMENT ME! */
+ /** The localised mnemonic for the "help" button. */
protected int helpButtonMnemonic;
- /** DOCUMENT ME! */
+ /** The localised text for the "help" button. */
protected String helpButtonText;
- /** DOCUMENT ME! */
+ /** The localised tool tip text for the help button. */
protected String helpButtonToolTipText;
- /** DOCUMENT ME! */
+ /** An icon representing the user's home folder. */
protected Icon homeFolderIcon = new Icon()
{
public int getIconHeight()
@@ -753,7 +799,7 @@ public class BasicFileChooserUI extends FileChooserUI
}
};
- /** DOCUMENT ME! */
+ /** An icon for the "list view" button. */
protected Icon listViewIcon = new Icon()
{
public int getIconHeight()
@@ -795,37 +841,37 @@ public class BasicFileChooserUI extends FileChooserUI
}
};
- /** DOCUMENT ME! */
+ /** An icon for the "new folder" button. */
protected Icon newFolderIcon = directoryIcon;
- /** DOCUMENT ME! */
+ /** The localised mnemonic for the "open" button. */
protected int openButtonMnemonic;
- /** DOCUMENT ME! */
+ /** The localised text for the "open" button. */
protected String openButtonText;
- /** DOCUMENT ME! */
+ /** The localised tool tip text for the "open" button. */
protected String openButtonToolTipText;
- /** DOCUMENT ME! */
+ /** The localised mnemonic for the "save" button. */
protected int saveButtonMnemonic;
- /** DOCUMENT ME! */
+ /** The localised text for the "save" button. */
protected String saveButtonText;
- /** DOCUMENT ME! */
+ /** The localised tool tip text for the save button. */
protected String saveButtonToolTipText;
- /** DOCUMENT ME! */
+ /** The localised mnemonic for the "update" button. */
protected int updateButtonMnemonic;
- /** DOCUMENT ME! */
+ /** The localised text for the "update" button. */
protected String updateButtonText;
- /** DOCUMENT ME! */
+ /** The localised tool tip text for the "update" button. */
protected String updateButtonToolTipText;
- /** DOCUMENT ME! */
+ /** An icon for the "up folder" button. */
protected Icon upFolderIcon = new Icon()
{
public int getIconHeight()
@@ -876,77 +922,84 @@ public class BasicFileChooserUI extends FileChooserUI
// -- begin private, but package local since used in inner classes --
+ /** The file chooser component represented by this UI delegate. */
JFileChooser filechooser;
- /** DOCUMENT ME! */
+ /** The file list. */
JList filelist;
- /** DOCUMENT ME! */
+ /** The combo box used to display/select file filters. */
JComboBox filters;
- /** DOCUMENT ME! */
+ /** The model for the directory list. */
BasicDirectoryModel model;
- /** DOCUMENT ME! */
+ /** The file filter for all files. */
FileFilter acceptAll = new AcceptAllFileFilter();
- /** DOCUMENT ME! */
+ /** The default file view. */
FileView fv = new BasicFileView();
- /** DOCUMENT ME! */
+ /** The icon size. */
static final int ICON_SIZE = 24;
- /** DOCUMENT ME! */
+ /** A combo box for display/selection of parent directories. */
JComboBox parents;
- /** DOCUMENT ME! */
+ /** The current file name. */
String filename;
- /** DOCUMENT ME! */
+ /** The accept (open/save) button. */
JButton accept;
- /** DOCUMENT ME! */
+ /** The cancel button. */
JButton cancel;
- /** DOCUMENT ME! */
+ /** The button to move up to the parent directory. */
JButton upFolderButton;
- /** DOCUMENT ME! */
+ /** The button to create a new directory. */
JButton newFolderButton;
- /** DOCUMENT ME! */
+ /** The button to move to the user's home directory. */
JButton homeFolderButton;
- /** DOCUMENT ME! */
+ /** An optional accessory panel. */
JPanel accessoryPanel;
- /** DOCUMENT ME! */
+ /** A property change listener. */
PropertyChangeListener propertyChangeListener;
- /** DOCUMENT ME! */
+ /** The text describing the filter for "all files". */
String acceptAllFileFilterText;
- /** DOCUMENT ME! */
+ /** The text describing a directory type. */
String dirDescText;
- /** DOCUMENT ME! */
+ /** The text describing a file type. */
String fileDescText;
- /** DOCUMENT ME! */
+ /** Is a directory selected? */
boolean dirSelected = false;
- /** DOCUMENT ME! */
+ /** The current directory. */
File currDir = null;
+ // FIXME: describe what is contained in the bottom panel
+ /** The bottom panel. */
JPanel bottomPanel;
-
- /** DOCUMENT ME! */
+
+ /** The close panel. */
JPanel closePanel;
+ /** Text box that displays file name */
+ JTextField entry;
+
+ /** Current parent path */
+ String parentPath;
+
// -- end private --
- private class ListLabelRenderer
- extends JLabel
- implements ListCellRenderer
+ private class ListLabelRenderer extends JLabel implements ListCellRenderer
{
/** DOCUMENT ME! */
final Color selected = new Color(153, 204, 255);
@@ -988,45 +1041,8 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Closes the dialog.
*/
- public class CBLabelRenderer extends JLabel implements ListCellRenderer
- {
- /**
- * Creates a new CBLabelRenderer object.
- */
- public CBLabelRenderer()
- {
- super();
- setOpaque(true);
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param list DOCUMENT ME!
- * @param value DOCUMENT ME!
- * @param index DOCUMENT ME!
- * @param isSelected DOCUMENT ME!
- * @param cellHasFocus DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public Component getListCellRendererComponent(JList list, Object value,
- int index,
- boolean isSelected,
- boolean cellHasFocus)
- {
- setHorizontalAlignment(SwingConstants.LEFT);
- setIcon(directoryIcon);
- setText(value.toString());
- setForeground(Color.BLACK);
- setBackground(Color.WHITE);
-
- return this;
- }
- }
-
void closeDialog()
{
Window owner = SwingUtilities.windowForComponent(filechooser);
@@ -1035,9 +1051,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * Creates a new BasicFileChooserUI object.
+ * Creates a new <code>BasicFileChooserUI</code> object.
*
- * @param b DOCUMENT ME!
+ * @param b the file chooser component.
*/
public BasicFileChooserUI(JFileChooser b)
{
@@ -1045,11 +1061,11 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns a UI delegate for the given component.
*
- * @param c DOCUMENT ME!
+ * @param c the component (should be a {@link JFileChooser}).
*
- * @return DOCUMENT ME!
+ * @return A new UI delegate.
*/
public static ComponentUI createUI(JComponent c)
{
@@ -1057,28 +1073,32 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
- *
- * @param c DOCUMENT ME!
+ * Installs the UI for the specified component.
+ *
+ * @param c the component (should be a {@link JFileChooser}).
*/
public void installUI(JComponent c)
{
if (c instanceof JFileChooser)
{
- JFileChooser fc = (JFileChooser) c;
- fc.resetChoosableFileFilters();
- createModel();
- clearIconCache();
- installDefaults(fc);
- installComponents(fc);
- installListeners(fc);
+ JFileChooser fc = (JFileChooser) c;
+ fc.resetChoosableFileFilters();
+ createModel();
+ clearIconCache();
+ installDefaults(fc);
+ installComponents(fc);
+ installListeners(fc);
+
+ Object path = filechooser.getCurrentDirectory();
+ if (path != null)
+ parentPath = path.toString().substring(path.toString().lastIndexOf("/"));
}
}
/**
- * DOCUMENT ME!
- *
- * @param c DOCUMENT ME!
+ * Uninstalls this UI from the given component.
+ *
+ * @param c the component (should be a {@link JFileChooser}).
*/
public void uninstallUI(JComponent c)
{
@@ -1185,16 +1205,16 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Creates and install the subcomponents for the file chooser.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*/
public void installComponents(JFileChooser fc)
{
JLabel look = new JLabel("Look In:");
parents = new JComboBox();
- parents.setRenderer(new CBLabelRenderer());
+ parents.setRenderer(new BasicComboBoxRenderer());
boxEntries();
look.setLabelFor(parents);
JPanel parentsPanel = new JPanel();
@@ -1226,9 +1246,9 @@ public class BasicFileChooserUI extends FileChooserUI
buttonPanel.add(detailsViewButton);
JPanel topPanel = new JPanel();
- topPanel.setLayout(new java.awt.FlowLayout());
+ parentsPanel.add(buttonPanel);
+ topPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
topPanel.add(parentsPanel);
- topPanel.add(buttonPanel);
accessoryPanel = new JPanel();
if (filechooser.getAccessory() != null)
@@ -1260,7 +1280,7 @@ public class BasicFileChooserUI extends FileChooserUI
JLabel fileNameLabel = new JLabel("File Name:");
JLabel fileTypesLabel = new JLabel("Files of Type:");
- JTextField entry = new JTextField();
+ entry = new JTextField();
filters = new JComboBox();
filterEntries();
@@ -1309,9 +1329,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Uninstalls the components from the file chooser.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*/
public void uninstallComponents(JFileChooser fc)
{
@@ -1327,9 +1347,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Installs the listeners required by this UI delegate.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*/
protected void installListeners(JFileChooser fc)
{
@@ -1349,9 +1369,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Uninstalls the listeners previously installed by this UI delegate.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*/
protected void uninstallListeners(JFileChooser fc)
{
@@ -1360,9 +1380,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Installs the defaults for this UI delegate.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*/
protected void installDefaults(JFileChooser fc)
{
@@ -1371,9 +1391,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Uninstalls the defaults previously added by this UI delegate.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*/
protected void uninstallDefaults(JFileChooser fc)
{
@@ -1382,9 +1402,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Installs the icons for this UI delegate (NOT YET IMPLEMENTED).
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*/
protected void installIcons(JFileChooser fc)
{
@@ -1392,9 +1412,10 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Uninstalls the icons previously added by this UI delegate (NOT YET
+ * IMPLEMENTED).
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*/
protected void uninstallIcons(JFileChooser fc)
{
@@ -1402,9 +1423,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Installs the strings used by this UI delegate.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*/
protected void installStrings(JFileChooser fc)
{
@@ -1432,9 +1453,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Uninstalls the strings previously added by this UI delegate.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*/
protected void uninstallStrings(JFileChooser fc)
{
@@ -1460,7 +1481,7 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Creates a new directory model.
*/
protected void createModel()
{
@@ -1468,9 +1489,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns the directory model.
*
- * @return DOCUMENT ME!
+ * @return The directory model.
*/
public BasicDirectoryModel getModel()
{
@@ -1478,115 +1499,131 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
- *
- * @param fc DOCUMENT ME!
- *
- * @return DOCUMENT ME!
+ * Creates a listener to handle changes to the properties of the given
+ * file chooser component.
+ *
+ * @param fc the file chooser component.
+ *
+ * @return A new listener.
*/
public PropertyChangeListener createPropertyChangeListener(JFileChooser fc)
{
return new PropertyChangeListener()
+ {
+ public void propertyChange(PropertyChangeEvent e)
{
- public void propertyChange(PropertyChangeEvent e)
- {
- // FIXME: Multiple file selection waiting on JList multiple selection bug.
- if (e.getPropertyName().equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY))
- {
- if (filechooser.getSelectedFile() == null)
- setFileName(null);
- else
- setFileName(filechooser.getSelectedFile().toString());
- int index = -1;
- File file = filechooser.getSelectedFile();
- for (index = 0; index < model.getSize(); index++)
- if (((File) model.getElementAt(index)).equals(file))
- break;
- if (index == -1)
- return;
- filelist.setSelectedIndex(index);
- filelist.ensureIndexIsVisible(index);
- filelist.revalidate();
- filelist.repaint();
- }
- else if (e.getPropertyName().equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY))
- {
- filelist.clearSelection();
- filelist.revalidate();
- filelist.repaint();
- setDirectorySelected(false);
- setDirectory(filechooser.getCurrentDirectory());
- boxEntries();
- }
- else if (e.getPropertyName().equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY)
- || e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
- filterEntries();
- else if (e.getPropertyName().equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)
- || e.getPropertyName().equals(JFileChooser.DIALOG_TITLE_CHANGED_PROPERTY))
- {
- Window owner = SwingUtilities.windowForComponent(filechooser);
- if (owner instanceof JDialog)
- ((JDialog) owner).setTitle(getDialogTitle(filechooser));
- accept.setText(getApproveButtonText(filechooser));
- accept.setToolTipText(getApproveButtonToolTipText(filechooser));
- accept.setMnemonic(getApproveButtonMnemonic(filechooser));
- }
- else if (e.getPropertyName().equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY))
- accept.setText(getApproveButtonText(filechooser));
- else if (e.getPropertyName().equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY))
- accept.setToolTipText(getApproveButtonToolTipText(filechooser));
- else if (e.getPropertyName().equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY))
- accept.setMnemonic(getApproveButtonMnemonic(filechooser));
- else if (e.getPropertyName().equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY))
- {
- if (filechooser.getControlButtonsAreShown())
- {
- GridBagConstraints c = new GridBagConstraints();
- c.gridy = 1;
- bottomPanel.add(filters, c);
-
- c.fill = GridBagConstraints.BOTH;
- c.gridy = 2;
- c.anchor = GridBagConstraints.EAST;
- bottomPanel.add(closePanel, c);
- bottomPanel.revalidate();
- bottomPanel.repaint();
- bottomPanel.doLayout();
- }
- else
- bottomPanel.remove(closePanel);
- }
- else if (e.getPropertyName().equals(JFileChooser.ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY))
- {
- if (filechooser.isAcceptAllFileFilterUsed())
- filechooser.addChoosableFileFilter(getAcceptAllFileFilter(filechooser));
- else
- filechooser.removeChoosableFileFilter(getAcceptAllFileFilter(filechooser));
- }
- else if (e.getPropertyName().equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY))
- {
- JComponent old = (JComponent) e.getOldValue();
- if (old != null)
- getAccessoryPanel().remove(old);
- JComponent newval = (JComponent) e.getNewValue();
- if (newval != null)
- getAccessoryPanel().add(newval);
- }
- if (e.getPropertyName().equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)
- || e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)
- || e.getPropertyName().equals(JFileChooser.FILE_HIDING_CHANGED_PROPERTY))
- rescanCurrentDirectory(filechooser);
-
- filechooser.revalidate();
- filechooser.repaint();
- }
- };
+ // FIXME: Multiple file selection waiting on JList multiple selection
+ // bug.
+ if (e.getPropertyName().equals(
+ JFileChooser.SELECTED_FILE_CHANGED_PROPERTY))
+ {
+ if (filechooser.getSelectedFile() == null)
+ setFileName(null);
+ else
+ setFileName(filechooser.getSelectedFile().toString());
+ int index = -1;
+ File file = filechooser.getSelectedFile();
+ for (index = 0; index < model.getSize(); index++)
+ if (((File) model.getElementAt(index)).equals(file))
+ break;
+ if (index == -1)
+ return;
+ filelist.setSelectedIndex(index);
+ filelist.ensureIndexIsVisible(index);
+ filelist.revalidate();
+ filelist.repaint();
+ }
+ else if (e.getPropertyName().equals(
+ JFileChooser.DIRECTORY_CHANGED_PROPERTY))
+ {
+ filelist.clearSelection();
+ filelist.revalidate();
+ filelist.repaint();
+ setDirectorySelected(false);
+ setDirectory(filechooser.getCurrentDirectory());
+ boxEntries();
+ }
+ else if (e.getPropertyName().equals(
+ JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY)
+ || e.getPropertyName().equals(
+ JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
+ filterEntries();
+ else if (e.getPropertyName().equals(
+ JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)
+ || e.getPropertyName().equals(
+ JFileChooser.DIALOG_TITLE_CHANGED_PROPERTY))
+ {
+ Window owner = SwingUtilities.windowForComponent(filechooser);
+ if (owner instanceof JDialog)
+ ((JDialog) owner).setTitle(getDialogTitle(filechooser));
+ accept.setText(getApproveButtonText(filechooser));
+ accept.setToolTipText(getApproveButtonToolTipText(filechooser));
+ accept.setMnemonic(getApproveButtonMnemonic(filechooser));
+ }
+ else if (e.getPropertyName().equals(
+ JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY))
+ accept.setText(getApproveButtonText(filechooser));
+ else if (e.getPropertyName().equals(
+ JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY))
+ accept.setToolTipText(getApproveButtonToolTipText(filechooser));
+ else if (e.getPropertyName().equals(
+ JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY))
+ accept.setMnemonic(getApproveButtonMnemonic(filechooser));
+ else if (e.getPropertyName().equals(
+ JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY))
+ {
+ if (filechooser.getControlButtonsAreShown())
+ {
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridy = 1;
+ bottomPanel.add(filters, c);
+
+ c.fill = GridBagConstraints.BOTH;
+ c.gridy = 2;
+ c.anchor = GridBagConstraints.EAST;
+ bottomPanel.add(closePanel, c);
+ bottomPanel.revalidate();
+ bottomPanel.repaint();
+ bottomPanel.doLayout();
+ }
+ else
+ bottomPanel.remove(closePanel);
+ }
+ else if (e.getPropertyName().equals(
+ JFileChooser.ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY))
+ {
+ if (filechooser.isAcceptAllFileFilterUsed())
+ filechooser.addChoosableFileFilter(getAcceptAllFileFilter(filechooser));
+ else
+ filechooser.removeChoosableFileFilter(getAcceptAllFileFilter(filechooser));
+ }
+ else if (e.getPropertyName().equals(
+ JFileChooser.ACCESSORY_CHANGED_PROPERTY))
+ {
+ JComponent old = (JComponent) e.getOldValue();
+ if (old != null)
+ getAccessoryPanel().remove(old);
+ JComponent newval = (JComponent) e.getNewValue();
+ if (newval != null)
+ getAccessoryPanel().add(newval);
+ }
+ if (e.getPropertyName().equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)
+ || e.getPropertyName().equals(
+ JFileChooser.FILE_FILTER_CHANGED_PROPERTY)
+ || e.getPropertyName().equals(
+ JFileChooser.FILE_HIDING_CHANGED_PROPERTY))
+ rescanCurrentDirectory(filechooser);
+
+ filechooser.revalidate();
+ filechooser.repaint();
+ }
+ };
}
/**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
+ * Returns the current file name.
+ *
+ * @return The current file name.
*/
public String getFileName()
{
@@ -1594,9 +1631,11 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns the current directory name.
*
- * @return DOCUMENT ME!
+ * @return The directory name.
+ *
+ * @see #setDirectoryName(String)
*/
public String getDirectoryName()
{
@@ -1605,9 +1644,11 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Sets the file name.
*
- * @param filename DOCUMENT ME!
+ * @param filename the file name.
+ *
+ * @see #getFileName()
*/
public void setFileName(String filename)
{
@@ -1615,9 +1656,11 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Sets the directory name (NOT IMPLEMENTED).
*
- * @param dirname DOCUMENT ME!
+ * @param dirname the directory name.
+ *
+ * @see #getDirectoryName()
*/
public void setDirectoryName(String dirname)
{
@@ -1625,9 +1668,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Rescans the current directory.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*/
public void rescanCurrentDirectory(JFileChooser fc)
{
@@ -1636,10 +1679,10 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * NOT YET IMPLEMENTED.
*
- * @param fc DOCUMENT ME!
- * @param f DOCUMENT ME!
+ * @param fc the file chooser.
+ * @param f the file.
*/
public void ensureFileIsVisible(JFileChooser fc, File f)
{
@@ -1647,9 +1690,10 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns the {@link JFileChooser} component that this UI delegate
+ * represents.
*
- * @return DOCUMENT ME!
+ * @return The component represented by this UI delegate.
*/
public JFileChooser getFileChooser()
{
@@ -1657,9 +1701,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns the optional accessory panel.
*
- * @return DOCUMENT ME!
+ * @return The optional accessory panel.
*/
public JPanel getAccessoryPanel()
{
@@ -1667,11 +1711,11 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Creates and returns an approve (open or save) button for the dialog.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*
- * @return DOCUMENT ME!
+ * @return The button.
*/
public JButton getApproveButton(JFileChooser fc)
{
@@ -1682,11 +1726,14 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns the tool tip text for the approve (open/save) button. This first
+ * checks the file chooser to see if a value has been explicitly set - if
+ * not, a default value appropriate for the type of file chooser is
+ * returned.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser.
*
- * @return DOCUMENT ME!
+ * @return The tool tip text.
*/
public String getApproveButtonToolTipText(JFileChooser fc)
{
@@ -1699,7 +1746,7 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Clears the icon cache.
*/
public void clearIconCache()
{
@@ -1708,11 +1755,11 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Creates a new listener to handle selections in the file list.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser component.
*
- * @return DOCUMENT ME!
+ * @return A new instance of {@link SelectionListener}.
*/
public ListSelectionListener createListSelectionListener(JFileChooser fc)
{
@@ -1720,12 +1767,12 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Creates a new listener to handle double-click events.
*
- * @param fc DOCUMENT ME!
- * @param list DOCUMENT ME!
+ * @param fc the file chooser component.
+ * @param list the list.
*
- * @return DOCUMENT ME!
+ * @return A new instance of {@link DoubleClickListener}.
*/
protected MouseListener createDoubleClickListener(JFileChooser fc, JList list)
{
@@ -1733,9 +1780,10 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns <code>true</code> if a directory is selected, and
+ * <code>false</code> otherwise.
*
- * @return DOCUMENT ME!
+ * @return A boolean.
*/
protected boolean isDirectorySelected()
{
@@ -1743,9 +1791,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Sets the flag that indicates whether the current directory is selected.
*
- * @param selected DOCUMENT ME!
+ * @param selected the new flag value.
*/
protected void setDirectorySelected(boolean selected)
{
@@ -1753,9 +1801,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns the current directory.
*
- * @return DOCUMENT ME!
+ * @return The current directory.
*/
protected File getDirectory()
{
@@ -1763,9 +1811,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Sets the current directory.
*
- * @param f DOCUMENT ME!
+ * @param f the directory.
*/
protected void setDirectory(File f)
{
@@ -1773,11 +1821,11 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns the "accept all" file filter.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser component.
*
- * @return DOCUMENT ME!
+ * @return The "accept all" file filter.
*/
public FileFilter getAcceptAllFileFilter(JFileChooser fc)
{
@@ -1785,25 +1833,29 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns the file view for the file chooser. This returns either the
+ * file view that has been explicitly set for the {@link JFileChooser}, or
+ * a default file view.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser component.
*
- * @return DOCUMENT ME!
+ * @return The file view.
+ *
+ * @see JFileChooser#getFileView()
*/
public FileView getFileView(JFileChooser fc)
{
- if (fc.getFileView() != null)
- return fc.getFileView();
return fv;
}
/**
- * DOCUMENT ME!
+ * Returns the dialog title.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser (<code>null</code> not permitted).
*
- * @return DOCUMENT ME!
+ * @return The dialog title.
+ *
+ * @see JFileChooser#getDialogTitle()
*/
public String getDialogTitle(JFileChooser fc)
{
@@ -1828,11 +1880,13 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns the approve button mnemonic.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser (<code>null</code> not permitted).
*
- * @return DOCUMENT ME!
+ * @return The approve button mnemonic.
+ *
+ * @see JFileChooser#getApproveButtonMnemonic()
*/
public int getApproveButtonMnemonic(JFileChooser fc)
{
@@ -1845,11 +1899,13 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Returns the approve button text.
*
- * @param fc DOCUMENT ME!
+ * @param fc the file chooser (<code>null</code> not permitted).
*
- * @return DOCUMENT ME!
+ * @return The approve button text.
+ *
+ * @see JFileChooser#getApproveButtonText()
*/
public String getApproveButtonText(JFileChooser fc)
{
@@ -1862,9 +1918,10 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Creates and returns a new action that will be used with the "new folder"
+ * button.
*
- * @return DOCUMENT ME!
+ * @return A new instance of {@link GoHomeAction}.
*/
public Action getNewFolderAction()
{
@@ -1872,9 +1929,10 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Creates and returns a new action that will be used with the "home folder"
+ * button.
*
- * @return DOCUMENT ME!
+ * @return A new instance of {@link GoHomeAction}.
*/
public Action getGoHomeAction()
{
@@ -1882,9 +1940,10 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Creates and returns a new action that will be used with the "up folder"
+ * button.
*
- * @return DOCUMENT ME!
+ * @return A new instance of {@link ChangeToParentDirectoryAction}.
*/
public Action getChangeToParentDirectoryAction()
{
@@ -1892,9 +1951,10 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Creates and returns a new action that will be used with the "approve"
+ * button.
*
- * @return DOCUMENT ME!
+ * @return A new instance of {@link ApproveSelectionAction}.
*/
public Action getApproveSelectionAction()
{
@@ -1902,9 +1962,10 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Creates and returns a new action that will be used with the "cancel"
+ * button.
*
- * @return DOCUMENT ME!
+ * @return A new instance of {@link CancelSelectionAction}.
*/
public Action getCancelSelectionAction()
{
@@ -1912,9 +1973,9 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Creates and returns a new instance of {@link UpdateAction}.
*
- * @return DOCUMENT ME!
+ * @return An action.
*/
public Action getUpdateAction()
{
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java
index 3abd76fe2d3..9c7f1c4c5d1 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java
@@ -1,5 +1,5 @@
/* BasicFormattedTextFieldUI.java
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,6 +39,7 @@ exception statement from your version. */
package javax.swing.plaf.basic;
import javax.swing.JComponent;
+import javax.swing.UIDefaults;
import javax.swing.plaf.ComponentUI;
/**
@@ -48,6 +49,7 @@ public class BasicFormattedTextFieldUI extends BasicTextFieldUI
{
public BasicFormattedTextFieldUI()
{
+ // Nothing to do here.
}
public static ComponentUI createUI(JComponent c)
@@ -55,6 +57,11 @@ public class BasicFormattedTextFieldUI extends BasicTextFieldUI
return new BasicFormattedTextFieldUI();
}
+ /**
+ * Returns the prefix for entries in the {@link UIDefaults} table.
+ *
+ * @return "FormattedTextField"
+ */
protected String getPropertyPrefix()
{
return "FormattedTextField";
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java b/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java
index 757ac47c903..068de345bec 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java
@@ -71,6 +71,7 @@ public class BasicGraphicsUtils
*/
public BasicGraphicsUtils()
{
+ // Nothing to do here.
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java b/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java
index 56a67b02935..6debd649509 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java
@@ -41,7 +41,6 @@ package javax.swing.plaf.basic;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
-import java.awt.Polygon;
import java.io.Serializable;
import javax.swing.Icon;
@@ -241,34 +240,33 @@ public class BasicIconFactory implements Serializable
{
return new DummyIcon();
}
+
+ /**
+ * Returns a new instance of a 4 x 8 icon showing a small black triangle that
+ * points to the right. This is displayed in menu items that have a
+ * sub menu.
+ *
+ * @return The icon.
+ */
public static Icon getMenuArrowIcon()
{
return new Icon()
{
public int getIconHeight()
{
- return 12;
+ return 8;
}
-
public int getIconWidth()
{
- return 12;
+ return 4;
}
-
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));
-
+ for (int i = 0; i < 4; i++)
+ g.drawLine(x + i, y + i, x + i, y + 7 - i);
g.setColor(saved);
- g.translate(-x, -y);
}
};
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java
index cc262948ded..73d3e6173d3 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java
@@ -84,6 +84,14 @@ public class BasicInternalFrameTitlePane extends JComponent
public class CloseAction extends AbstractAction
{
/**
+ * Creates a new action.
+ */
+ public CloseAction()
+ {
+ super("Close");
+ }
+
+ /**
* This method is called when something closes the JInternalFrame.
*
* @param e The ActionEvent.
@@ -92,13 +100,14 @@ public class BasicInternalFrameTitlePane extends JComponent
{
if (frame.isClosable())
{
- try
- {
- frame.setClosed(true);
- }
- catch (PropertyVetoException pve)
- {
- }
+ try
+ {
+ frame.setClosed(true);
+ }
+ catch (PropertyVetoException pve)
+ {
+ // We do nothing if the attempt has been vetoed.
+ }
}
}
}
@@ -113,6 +122,14 @@ public class BasicInternalFrameTitlePane extends JComponent
public class IconifyAction extends AbstractAction
{
/**
+ * Creates a new action.
+ */
+ public IconifyAction()
+ {
+ super("Minimize");
+ }
+
+ /**
* This method is called when the user wants to iconify the
* JInternalFrame.
*
@@ -122,13 +139,14 @@ public class BasicInternalFrameTitlePane extends JComponent
{
if (frame.isIconifiable() && ! frame.isIcon())
{
- try
- {
- frame.setIcon(true);
- }
- catch (PropertyVetoException pve)
- {
- }
+ try
+ {
+ frame.setIcon(true);
+ }
+ catch (PropertyVetoException pve)
+ {
+ // We do nothing if the attempt has been vetoed.
+ }
}
}
}
@@ -143,6 +161,13 @@ public class BasicInternalFrameTitlePane extends JComponent
public class MaximizeAction extends AbstractAction
{
/**
+ * Creates a new action.
+ */
+ public MaximizeAction()
+ {
+ super("Maximize");
+ }
+ /**
* This method is called when the user wants to maximize the
* JInternalFrame.
*
@@ -152,13 +177,14 @@ public class BasicInternalFrameTitlePane extends JComponent
{
try
{
- if (frame.isMaximizable() && ! frame.isMaximum())
- frame.setMaximum(true);
- else if (frame.isMaximum())
- frame.setMaximum(false);
+ if (frame.isMaximizable() && ! frame.isMaximum())
+ frame.setMaximum(true);
+ else if (frame.isMaximum())
+ frame.setMaximum(false);
}
catch (PropertyVetoException pve)
{
+ // We do nothing if the attempt has been vetoed.
}
}
}
@@ -173,6 +199,13 @@ public class BasicInternalFrameTitlePane extends JComponent
public class MoveAction extends AbstractAction
{
/**
+ * Creates a new action.
+ */
+ public MoveAction()
+ {
+ super("Move");
+ }
+ /**
* This method is called when the user wants to drag the JInternalFrame.
*
* @param e The ActionEvent.
@@ -194,6 +227,13 @@ public class BasicInternalFrameTitlePane extends JComponent
public class RestoreAction extends AbstractAction
{
/**
+ * Creates a new action.
+ */
+ public RestoreAction()
+ {
+ super("Restore");
+ }
+ /**
* This method is called when the user wants to restore the
* JInternalFrame.
*
@@ -203,13 +243,14 @@ public class BasicInternalFrameTitlePane extends JComponent
{
if (frame.isMaximum())
{
- try
- {
- frame.setMaximum(false);
- }
- catch (PropertyVetoException pve)
- {
- }
+ try
+ {
+ frame.setMaximum(false);
+ }
+ catch (PropertyVetoException pve)
+ {
+ // We do nothing if the attempt has been vetoed.
+ }
}
}
}
@@ -224,6 +265,13 @@ public class BasicInternalFrameTitlePane extends JComponent
public class SizeAction extends AbstractAction
{
/**
+ * Creates a new action.
+ */
+ public SizeAction()
+ {
+ super("Size");
+ }
+ /**
* This method is called when the user wants to resize the JInternalFrame.
*
* @param e The ActionEvent.
@@ -377,24 +425,26 @@ public class BasicInternalFrameTitlePane extends JComponent
int loc = width + insets.left - 1;
int top = insets.top + 1;
- int buttonWidth = height - 2;
int buttonHeight = height - 4;
if (closeButton.isVisible())
{
- loc -= buttonWidth + 2;
- closeButton.setBounds(loc, top, buttonWidth, buttonHeight);
+ int buttonWidth = closeIcon.getIconWidth();
+ loc -= buttonWidth + 2;
+ closeButton.setBounds(loc, top, buttonWidth, buttonHeight);
}
if (maxButton.isVisible())
{
- loc -= buttonWidth + 2;
- maxButton.setBounds(loc, top, buttonWidth, buttonHeight);
+ int buttonWidth = maxIcon.getIconWidth();
+ loc -= buttonWidth + 2;
+ maxButton.setBounds(loc, top, buttonWidth, buttonHeight);
}
if (iconButton.isVisible())
{
- loc -= buttonWidth + 2;
- iconButton.setBounds(loc, top, buttonWidth, buttonHeight);
+ int buttonWidth = iconIcon.getIconWidth();
+ loc -= buttonWidth + 2;
+ iconButton.setBounds(loc, top, buttonWidth, buttonHeight);
}
if (title != null)
@@ -435,6 +485,7 @@ public class BasicInternalFrameTitlePane extends JComponent
*/
public void removeLayoutComponent(Component c)
{
+ // Nothing to do here.
}
}
@@ -466,6 +517,7 @@ public class BasicInternalFrameTitlePane extends JComponent
// These buttons cannot be given focus.
return false;
}
+
}
/** The action command for the Close action. */
@@ -522,6 +574,9 @@ public class BasicInternalFrameTitlePane extends JComponent
/** The icon displayed in the iconify button. */
protected Icon iconIcon = BasicIconFactory.createEmptyFrameIcon();
+ /** The icon displayed in the close button. */
+ protected Icon closeIcon;
+
/** The JInternalFrame that this TitlePane is used in. */
protected JInternalFrame frame;
@@ -645,7 +700,7 @@ public class BasicInternalFrameTitlePane extends JComponent
*/
protected void installListeners()
{
- propertyChangeListener = new PropertyChangeHandler();
+ propertyChangeListener = createPropertyChangeListener();
frame.addPropertyChangeListener(propertyChangeListener);
}
@@ -663,14 +718,17 @@ public class BasicInternalFrameTitlePane extends JComponent
*/
protected void installDefaults()
{
- // FIXME: move icons to defaults.
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- setFont(defaults.getFont("InternalFrame.titleFont"));
+ title.setFont(defaults.getFont("InternalFrame.titleFont"));
selectedTextColor = defaults.getColor("InternalFrame.activeTitleForeground");
selectedTitleColor = defaults.getColor("InternalFrame.activeTitleBackground");
notSelectedTextColor = defaults.getColor("InternalFrame.inactiveTitleForeground");
notSelectedTitleColor = defaults.getColor("InternalFrame.inactiveTitleBackground");
+
+ closeIcon = UIManager.getIcon("InternalFrame.closeIcon");
+ iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon");
+ maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon");
}
/**
@@ -683,6 +741,10 @@ public class BasicInternalFrameTitlePane extends JComponent
selectedTitleColor = null;
notSelectedTextColor = null;
notSelectedTitleColor = null;
+
+ closeIcon = null;
+ iconIcon = null;
+ maxIcon = null;
}
/**
@@ -691,12 +753,15 @@ public class BasicInternalFrameTitlePane extends JComponent
protected void createButtons()
{
closeButton = new PaneButton(closeAction);
+ closeButton.setText(null);
if (!frame.isClosable())
closeButton.setVisible(false);
iconButton = new PaneButton(iconifyAction);
+ iconButton.setText(null);
if (!frame.isIconifiable())
iconButton.setVisible(false);
maxButton = new PaneButton(maximizeAction);
+ maxButton.setText(null);
if (!frame.isMaximizable())
maxButton.setVisible(false);
}
@@ -706,15 +771,12 @@ public class BasicInternalFrameTitlePane extends JComponent
*/
protected void setButtonIcons()
{
- Icon icon = UIManager.getIcon("InternalFrame.closeIcon");
- if (icon != null)
- closeButton.setIcon(icon);
- icon = UIManager.getIcon("InternalFrame.iconifyIcon");
- if (icon != null)
- iconButton.setIcon(icon);
- icon = UIManager.getIcon("InternalFrame.maximizeIcon");
- if (icon != null)
- maxButton.setIcon(icon);
+ if (closeIcon != null && closeButton != null)
+ closeButton.setIcon(closeIcon);
+ if (iconIcon != null && iconButton != null)
+ iconButton.setIcon(iconIcon);
+ if (maxIcon != null && maxButton != null)
+ maxButton.setIcon(maxIcon);
}
/**
@@ -816,11 +878,12 @@ public class BasicInternalFrameTitlePane extends JComponent
public void paintComponent(Graphics g)
{
paintTitleBackground(g);
- Font f = g.getFont();
- FontMetrics fm = g.getFontMetrics(f);
if (frame.getTitle() != null && title != null)
{
Color saved = g.getColor();
+ Font f = title.getFont();
+ g.setFont(f);
+ FontMetrics fm = g.getFontMetrics(f);
if (frame.isSelected())
g.setColor(selectedTextColor);
else
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java
index 8f76ea0cc19..d9dadda688a 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java
@@ -56,20 +56,17 @@ import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
-import javax.swing.BorderFactory;
import javax.swing.DefaultDesktopManager;
import javax.swing.DesktopManager;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.KeyStroke;
+import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
-import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
-import javax.swing.border.BevelBorder;
-import javax.swing.border.Border;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
import javax.swing.event.MouseInputAdapter;
@@ -202,67 +199,66 @@ public class BasicInternalFrameUI extends InternalFrameUI
*/
public void mouseDragged(MouseEvent e)
{
- // If the frame is maximized, there is nothing that
+ // If the frame is maximized, there is nothing that
// can be dragged around.
if (frame.isMaximum())
- return;
+ return;
DesktopManager dm = getDesktopManager();
Rectangle b = frame.getBounds();
Dimension min = frame.getMinimumSize();
if (min == null)
- min = new Dimension(0, 0);
+ min = new Dimension(0, 0);
Insets insets = frame.getInsets();
int x = e.getX();
int y = e.getY();
if (e.getSource() == frame && frame.isResizable())
{
- switch (direction)
- {
- case NORTH:
- cacheRect.setBounds(b.x,
- Math.min(b.y + y, b.y + b.height
- - min.height), b.width, b.height
- - y);
- break;
- case NORTH_EAST:
- cacheRect.setBounds(b.x,
- Math.min(b.y + y, b.y + b.height
- - min.height), x, b.height - y);
- break;
- case EAST:
- cacheRect.setBounds(b.x, b.y, x, b.height);
- break;
- case SOUTH_EAST:
- cacheRect.setBounds(b.x, b.y, x, y);
- break;
- case SOUTH:
- cacheRect.setBounds(b.x, b.y, b.width, y);
- break;
- case SOUTH_WEST:
- cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width),
- b.y, b.width - x, y);
- break;
- case WEST:
- cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width),
- b.y, b.width - x, b.height);
- break;
- case NORTH_WEST:
- cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width),
- Math.min(b.y + y, b.y + b.height
- - min.height), b.width - x,
- b.height - y);
- break;
- }
- dm.resizeFrame(frame, cacheRect.x, cacheRect.y,
- Math.max(min.width, cacheRect.width),
- Math.max(min.height, cacheRect.height));
+ switch (direction)
+ {
+ case NORTH:
+ cacheRect.setBounds(b.x, Math.min(b.y + y, b.y + b.height
+ - min.height),
+ b.width, b.height - y);
+ break;
+ case NORTH_EAST:
+ cacheRect.setBounds(b.x, Math.min(b.y + y, b.y + b.height
+ - min.height), x,
+ b.height - y);
+ break;
+ case EAST:
+ cacheRect.setBounds(b.x, b.y, x, b.height);
+ break;
+ case SOUTH_EAST:
+ cacheRect.setBounds(b.x, b.y, x, y);
+ break;
+ case SOUTH:
+ cacheRect.setBounds(b.x, b.y, b.width, y);
+ break;
+ case SOUTH_WEST:
+ cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width),
+ b.y, b.width - x, y);
+ break;
+ case WEST:
+ cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width),
+ b.y, b.width - x, b.height);
+ break;
+ case NORTH_WEST:
+ cacheRect.setBounds(
+ Math.min(b.x + x, b.x + b.width - min.width),
+ Math.min(b.y + y, b.y + b.height - min.height),
+ b.width - x, b.height - y);
+ break;
+ }
+ dm.resizeFrame(frame, cacheRect.x, cacheRect.y,
+ Math.max(min.width, cacheRect.width),
+ Math.max(min.height, cacheRect.height));
}
else if (e.getSource() == titlePane)
{
- Rectangle fBounds = frame.getBounds();
+ Rectangle fBounds = frame.getBounds();
- dm.dragFrame(frame, e.getX() - xOffset + b.x,
- e.getY() - yOffset + b.y);
+ dm.dragFrame(frame, e.getX() - xOffset + b.x, e.getY() - yOffset
+ + b.y);
}
}
@@ -304,17 +300,17 @@ public class BasicInternalFrameUI extends InternalFrameUI
if (e.getSource() == frame && frame.isResizable())
{
- direction = sectionOfClick(x, y);
- dm.beginResizingFrame(frame, direction);
+ direction = sectionOfClick(x, y);
+ dm.beginResizingFrame(frame, direction);
}
else if (e.getSource() == titlePane)
{
- Rectangle tBounds = titlePane.getBounds();
+ Rectangle tBounds = titlePane.getBounds();
- xOffset = e.getX() - tBounds.x + insets.left;
- yOffset = e.getY() - tBounds.y + insets.top;
+ xOffset = e.getX() - tBounds.x + insets.left;
+ yOffset = e.getY() - tBounds.y + insets.top;
- dm.beginDraggingFrame(frame);
+ dm.beginDraggingFrame(frame);
}
}
@@ -329,9 +325,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
xOffset = 0;
yOffset = 0;
if (e.getSource() == frame && frame.isResizable())
- dm.endResizingFrame(frame);
+ dm.endResizingFrame(frame);
else if (e.getSource() == titlePane)
- dm.endDraggingFrame(frame);
+ dm.endDraggingFrame(frame);
}
/**
@@ -348,21 +344,21 @@ public class BasicInternalFrameUI extends InternalFrameUI
Insets insets = frame.getInsets();
Rectangle b = frame.getBounds();
if (x < insets.left && y < insets.top)
- return NORTH_WEST;
+ return NORTH_WEST;
else if (x > b.width - insets.right && y < insets.top)
- return NORTH_EAST;
+ return NORTH_EAST;
else if (x > b.width - insets.right && y > b.height - insets.bottom)
- return SOUTH_EAST;
+ return SOUTH_EAST;
else if (x < insets.left && y > b.height - insets.bottom)
- return SOUTH_WEST;
+ return SOUTH_WEST;
else if (y < insets.top)
- return NORTH;
+ return NORTH;
else if (x < insets.left)
- return WEST;
+ return WEST;
else if (y > b.height - insets.bottom)
- return SOUTH;
+ return SOUTH;
else if (x > b.width - insets.right)
- return EAST;
+ return EAST;
return -1;
}
@@ -377,8 +373,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
{
/**
* This method is called when the JDesktopPane is hidden.
- *
- * @param e The ComponentEvent fired.
+ *
+ * @param e
+ * The ComponentEvent fired.
*/
public void componentHidden(ComponentEvent e)
{
@@ -387,8 +384,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method is called when the JDesktopPane is moved.
- *
- * @param e The ComponentEvent fired.
+ *
+ * @param e
+ * The ComponentEvent fired.
*/
public void componentMoved(ComponentEvent e)
{
@@ -397,22 +395,23 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method is called when the JDesktopPane is resized.
- *
- * @param e The ComponentEvent fired.
+ *
+ * @param e
+ * The ComponentEvent fired.
*/
public void componentResized(ComponentEvent e)
{
if (frame.isMaximum())
{
- JDesktopPane pane = (JDesktopPane) e.getSource();
- Insets insets = pane.getInsets();
- Rectangle bounds = pane.getBounds();
-
- frame.setBounds(bounds.x + insets.left, bounds.y + insets.top,
- bounds.width - insets.left - insets.right,
- bounds.height - insets.top - insets.bottom);
- frame.revalidate();
- frame.repaint();
+ JDesktopPane pane = (JDesktopPane) e.getSource();
+ Insets insets = pane.getInsets();
+ Rectangle bounds = pane.getBounds();
+
+ frame.setBounds(bounds.x + insets.left, bounds.y + insets.top,
+ bounds.width - insets.left - insets.right,
+ bounds.height - insets.top - insets.bottom);
+ frame.revalidate();
+ frame.repaint();
}
// Sun also resizes the icons. but it doesn't seem to do anything.
@@ -420,8 +419,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method is called when the JDesktopPane is shown.
- *
- * @param e The ComponentEvent fired.
+ *
+ * @param e
+ * The ComponentEvent fired.
*/
public void componentShown(ComponentEvent e)
{
@@ -435,21 +435,25 @@ public class BasicInternalFrameUI extends InternalFrameUI
public class InternalFrameLayout implements LayoutManager
{
/**
- * This method is called when the given Component is added to the
+ * This method is called when the given Component is added to the
* JInternalFrame.
- *
- * @param name The name of the Component.
- * @param c The Component added.
+ *
+ * @param name
+ * The name of the Component.
+ * @param c
+ * The Component added.
*/
public void addLayoutComponent(String name, Component c)
{
+ // Nothing to do here.
}
/**
* This method is used to set the bounds of the children of the
* JInternalFrame.
- *
- * @param c The Container to lay out.
+ *
+ * @param c
+ * The Container to lay out.
*/
public void layoutContainer(Container c)
{
@@ -468,38 +472,38 @@ public class BasicInternalFrameUI extends InternalFrameUI
if (northPane != null)
{
- Dimension nDims = northPane.getPreferredSize();
- nh = Math.min(nDims.height, dims.height);
+ Dimension nDims = northPane.getPreferredSize();
+ nh = Math.min(nDims.height, dims.height);
- northPane.setBounds(insets.left, insets.top, dims.width, nh);
+ northPane.setBounds(insets.left, insets.top, dims.width, nh);
}
if (southPane != null)
{
- Dimension sDims = southPane.getPreferredSize();
- sh = Math.min(sDims.height, dims.height - nh);
+ Dimension sDims = southPane.getPreferredSize();
+ sh = Math.min(sDims.height, dims.height - nh);
- southPane.setBounds(insets.left, insets.top + dims.height - sh,
- dims.width, sh);
+ southPane.setBounds(insets.left, insets.top + dims.height - sh,
+ dims.width, sh);
}
int remHeight = dims.height - sh - nh;
if (westPane != null)
{
- Dimension wDims = westPane.getPreferredSize();
- ww = Math.min(dims.width, wDims.width);
+ Dimension wDims = westPane.getPreferredSize();
+ ww = Math.min(dims.width, wDims.width);
- westPane.setBounds(insets.left, insets.top + nh, ww, remHeight);
+ westPane.setBounds(insets.left, insets.top + nh, ww, remHeight);
}
if (eastPane != null)
{
- Dimension eDims = eastPane.getPreferredSize();
- ew = Math.min(eDims.width, dims.width - ww);
+ Dimension eDims = eastPane.getPreferredSize();
+ ew = Math.min(eDims.width, dims.width - ww);
- eastPane.setBounds(insets.left + dims.width - ew, insets.top + nh,
- ew, remHeight);
+ eastPane.setBounds(insets.left + dims.width - ew, insets.top + nh,
+ ew, remHeight);
}
int remWidth = dims.width - ww - ew;
@@ -510,9 +514,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method returns the minimum layout size.
- *
- * @param c The Container to find a minimum layout size for.
- *
+ *
+ * @param c
+ * The Container to find a minimum layout size for.
* @return The minimum dimensions for the JInternalFrame.
*/
public Dimension minimumLayoutSize(Container c)
@@ -522,9 +526,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method returns the maximum layout size.
- *
- * @param c The Container to find a maximum layout size for.
- *
+ *
+ * @param c
+ * The Container to find a maximum layout size for.
* @return The maximum dimensions for the JInternalFrame.
*/
public Dimension maximumLayoutSize(Container c)
@@ -534,9 +538,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* Th8is method returns the preferred layout size.
- *
- * @param c The Container to find a preferred layout size for.
- *
+ *
+ * @param c
+ * The Container to find a preferred layout size for.
* @return The preferred dimensions for the JInternalFrame.
*/
public Dimension preferredLayoutSize(Container c)
@@ -546,10 +550,11 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* DOCUMENT ME!
- *
- * @param c DOCUMENT ME!
- * @param min DOCUMENT ME!
- *
+ *
+ * @param c
+ * DOCUMENT ME!
+ * @param min
+ * DOCUMENT ME!
* @return DOCUMENT ME!
*/
private Dimension getSize(Container c, boolean min)
@@ -558,7 +563,7 @@ public class BasicInternalFrameUI extends InternalFrameUI
Dimension contentDims = frame.getContentPane().getPreferredSize();
if (min)
- contentDims.width = contentDims.height = 0;
+ contentDims.width = contentDims.height = 0;
int nWidth = 0;
int nHeight = 0;
int sWidth = 0;
@@ -571,42 +576,42 @@ public class BasicInternalFrameUI extends InternalFrameUI
if (northPane != null)
{
- dims = northPane.getPreferredSize();
- if (dims != null)
- {
- nWidth = dims.width;
- nHeight = dims.height;
- }
+ dims = northPane.getPreferredSize();
+ if (dims != null)
+ {
+ nWidth = dims.width;
+ nHeight = dims.height;
+ }
}
if (southPane != null)
{
- dims = southPane.getPreferredSize();
- if (dims != null)
- {
- sWidth = dims.width;
- sHeight = dims.height;
- }
+ dims = southPane.getPreferredSize();
+ if (dims != null)
+ {
+ sWidth = dims.width;
+ sHeight = dims.height;
+ }
}
if (eastPane != null)
{
- dims = eastPane.getPreferredSize();
- if (dims != null)
- {
- sWidth = dims.width;
- sHeight = dims.height;
- }
+ dims = eastPane.getPreferredSize();
+ if (dims != null)
+ {
+ sWidth = dims.width;
+ sHeight = dims.height;
+ }
}
if (westPane != null)
{
- dims = westPane.getPreferredSize();
- if (dims != null)
- {
- wWidth = dims.width;
- wHeight = dims.height;
- }
+ dims = westPane.getPreferredSize();
+ if (dims != null)
+ {
+ wWidth = dims.width;
+ wHeight = dims.height;
+ }
}
int width = Math.max(sWidth, nWidth);
@@ -630,6 +635,7 @@ public class BasicInternalFrameUI extends InternalFrameUI
*/
public void removeLayoutComponent(Component c)
{
+ // Nothing to do here.
}
}
@@ -657,8 +663,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method is called when the mouse enters the glass pane.
- *
- * @param e The MouseEvent.
+ *
+ * @param e
+ * The MouseEvent.
*/
public void mouseEntered(MouseEvent e)
{
@@ -667,8 +674,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method is called when the mouse is clicked on the glass pane.
- *
- * @param e The MouseEvent.
+ *
+ * @param e
+ * The MouseEvent.
*/
public void mouseClicked(MouseEvent e)
{
@@ -677,8 +685,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method is called when the mouse is dragged in the glass pane.
- *
- * @param e The MouseEvent.
+ *
+ * @param e
+ * The MouseEvent.
*/
public void mouseDragged(MouseEvent e)
{
@@ -687,8 +696,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method is called when the mouse exits the glass pane.
- *
- * @param e The MouseEvent.
+ *
+ * @param e
+ * The MouseEvent.
*/
public void mouseExited(MouseEvent e)
{
@@ -697,8 +707,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method is called when the mouse is moved in the glass pane.
- *
- * @param e The MouseEvent.
+ *
+ * @param e
+ * The MouseEvent.
*/
public void mouseMoved(MouseEvent e)
{
@@ -706,9 +717,10 @@ public class BasicInternalFrameUI extends InternalFrameUI
}
/**
- * This method is called when the mouse is pressed in the glass pane.
- *
- * @param e The MouseEvent.
+ * This method is called when the mouse is pressed in the glass pane.
+ *
+ * @param e
+ * The MouseEvent.
*/
public void mousePressed(MouseEvent e)
{
@@ -717,9 +729,10 @@ public class BasicInternalFrameUI extends InternalFrameUI
}
/**
- * This method is called when the mouse is released in the glass pane.
- *
- * @param e The MouseEvent.
+ * This method is called when the mouse is released in the glass pane.
+ *
+ * @param e
+ * The MouseEvent.
*/
public void mouseReleased(MouseEvent e)
{
@@ -727,10 +740,10 @@ public class BasicInternalFrameUI extends InternalFrameUI
}
/**
- * This method acquires a candidate component to dispatch the MouseEvent
- * to.
- *
- * @param me The MouseEvent to acquire a component for.
+ * This method acquires a candidate component to dispatch the MouseEvent to.
+ *
+ * @param me
+ * The MouseEvent to acquire a component for.
*/
private void acquireComponentForMouseEvent(MouseEvent me)
{
@@ -738,134 +751,137 @@ public class BasicInternalFrameUI extends InternalFrameUI
int y = me.getY();
// Find the candidate which should receive this event.
- Component parent = frame.getContentPane();
+ Component parent = frame.getLayeredPane();
if (parent == null)
- return;
+ return;
Component candidate = null;
Point p = me.getPoint();
while (candidate == null && parent != null)
{
- candidate = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y);
- if (candidate == null)
- {
- p = SwingUtilities.convertPoint(parent, p.x, p.y,
- parent.getParent());
- parent = parent.getParent();
- }
+ candidate = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y);
+ if (candidate == null)
+ {
+ p = SwingUtilities.convertPoint(parent, p.x, p.y,
+ parent.getParent());
+ parent = parent.getParent();
+ }
}
// If the only candidate we found was the native container itself,
- // don't dispatch any event at all. We only care about the lightweight
+ // don't dispatch any event at all. We only care about the lightweight
// children here.
if (candidate == frame.getContentPane())
- candidate = null;
+ candidate = null;
// If our candidate is new, inform the old target we're leaving.
if (lastComponentEntered != null && lastComponentEntered.isShowing()
&& lastComponentEntered != candidate)
{
- Point tp = SwingUtilities.convertPoint(frame.getContentPane(), x, y,
- lastComponentEntered);
- MouseEvent exited = new MouseEvent(lastComponentEntered,
- MouseEvent.MOUSE_EXITED,
- me.getWhen(), me.getModifiersEx(),
- tp.x, tp.y, me.getClickCount(),
- me.isPopupTrigger(),
- me.getButton());
+ Point tp = SwingUtilities.convertPoint(frame.getContentPane(), x, y,
+ lastComponentEntered);
+ MouseEvent exited = new MouseEvent(lastComponentEntered,
+ MouseEvent.MOUSE_EXITED,
+ me.getWhen(), me.getModifiersEx(),
+ tp.x, tp.y, me.getClickCount(),
+ me.isPopupTrigger(),
+ me.getButton());
tempComponent = lastComponentEntered;
- lastComponentEntered = null;
- tempComponent.dispatchEvent(exited);
+ lastComponentEntered = null;
+ tempComponent.dispatchEvent(exited);
}
// If we have a candidate, maybe enter it.
if (candidate != null)
{
- mouseEventTarget = candidate;
- if (candidate.isLightweight() && candidate.isShowing()
- && candidate != frame.getContentPane()
- && candidate != lastComponentEntered)
- {
- lastComponentEntered = mouseEventTarget;
- Point cp = SwingUtilities.convertPoint(frame.getContentPane(),
- x, y, lastComponentEntered);
- MouseEvent entered = new MouseEvent(lastComponentEntered,
- MouseEvent.MOUSE_ENTERED,
- me.getWhen(),
- me.getModifiersEx(), cp.x,
- cp.y, me.getClickCount(),
- me.isPopupTrigger(),
- me.getButton());
- lastComponentEntered.dispatchEvent(entered);
- }
+ mouseEventTarget = candidate;
+ if (candidate.isLightweight() && candidate.isShowing()
+ && candidate != frame.getContentPane()
+ && candidate != lastComponentEntered)
+ {
+ lastComponentEntered = mouseEventTarget;
+ Point cp = SwingUtilities.convertPoint(frame.getContentPane(), x,
+ y, lastComponentEntered);
+ MouseEvent entered = new MouseEvent(lastComponentEntered,
+ MouseEvent.MOUSE_ENTERED,
+ me.getWhen(),
+ me.getModifiersEx(), cp.x,
+ cp.y, me.getClickCount(),
+ me.isPopupTrigger(),
+ me.getButton());
+ lastComponentEntered.dispatchEvent(entered);
+ }
}
if (me.getID() == MouseEvent.MOUSE_RELEASED
|| me.getID() == MouseEvent.MOUSE_PRESSED && pressCount > 0
|| me.getID() == MouseEvent.MOUSE_DRAGGED)
- // If any of the following events occur while a button is held down,
- // they should be dispatched to the same component to which the
- // original MOUSE_PRESSED event was dispatched:
- // - MOUSE_RELEASED
- // - MOUSE_PRESSED: another button pressed while the first is held down
- // - MOUSE_DRAGGED
- mouseEventTarget = pressedComponent;
+ // If any of the following events occur while a button is held down,
+ // they should be dispatched to the same component to which the
+ // original MOUSE_PRESSED event was dispatched:
+ // - MOUSE_RELEASED
+ // - MOUSE_PRESSED: another button pressed while the first is held down
+ // - MOUSE_DRAGGED
+ mouseEventTarget = pressedComponent;
else if (me.getID() == MouseEvent.MOUSE_CLICKED)
{
- // Don't dispatch CLICKED events whose target is not the same as the
- // target for the original PRESSED event.
- if (candidate != pressedComponent)
- mouseEventTarget = null;
- else if (pressCount == 0)
- pressedComponent = null;
+ // Don't dispatch CLICKED events whose target is not the same as the
+ // target for the original PRESSED event.
+ if (candidate != pressedComponent)
+ mouseEventTarget = null;
+ else if (pressCount == 0)
+ pressedComponent = null;
}
}
/**
- * This is a helper method that dispatches the GlassPane MouseEvents to
- * the proper component.
- *
- * @param e The AWTEvent to be dispatched. Usually an instance of
- * MouseEvent.
+ * This is a helper method that dispatches the GlassPane MouseEvents to the
+ * proper component.
+ *
+ * @param e
+ * The AWTEvent to be dispatched. Usually an instance of
+ * MouseEvent.
*/
private void handleEvent(AWTEvent e)
{
if (e instanceof MouseEvent)
{
- MouseEvent me = SwingUtilities.convertMouseEvent(frame.getRootPane()
- .getGlassPane(),
- (MouseEvent) e,
- frame.getRootPane()
- .getGlassPane());
-
- acquireComponentForMouseEvent(me);
-
- // Avoid dispatching ENTERED and EXITED events twice.
- if (mouseEventTarget != null && mouseEventTarget.isShowing()
- && e.getID() != MouseEvent.MOUSE_ENTERED
- && e.getID() != MouseEvent.MOUSE_EXITED)
- {
- MouseEvent newEvt = SwingUtilities.convertMouseEvent(frame
- .getContentPane(),
- me,
- mouseEventTarget);
- mouseEventTarget.dispatchEvent(newEvt);
-
- switch (e.getID())
- {
- case MouseEvent.MOUSE_PRESSED:
- if (pressCount++ == 0)
- pressedComponent = mouseEventTarget;
- break;
- case MouseEvent.MOUSE_RELEASED:
- // Clear our memory of the original PRESSED event, only if
- // we're not expecting a CLICKED event after this. If
- // there is a CLICKED event after this, it will do clean up.
- if (--pressCount == 0
- && mouseEventTarget != pressedComponent)
- pressedComponent = null;
- break;
- }
- }
+ MouseEvent me = (MouseEvent) e;
+ acquireComponentForMouseEvent(me);
+
+ //If there is no target, return
+ if (mouseEventTarget == null)
+ return;
+
+ //Avoid re-dispatching to ourselves and causing an infinite loop
+ if (mouseEventTarget.equals(frame.getGlassPane()))
+ return;
+
+ // Avoid dispatching ENTERED and EXITED events twice.
+ if (mouseEventTarget.isShowing()
+ && e.getID() != MouseEvent.MOUSE_ENTERED
+ && e.getID() != MouseEvent.MOUSE_EXITED)
+ {
+ MouseEvent newEvt = SwingUtilities.convertMouseEvent(
+ frame.getGlassPane(),
+ me,
+ mouseEventTarget);
+ mouseEventTarget.dispatchEvent(newEvt);
+
+ switch (e.getID())
+ {
+ case MouseEvent.MOUSE_PRESSED:
+ if (pressCount++ == 0)
+ pressedComponent = mouseEventTarget;
+ break;
+ case MouseEvent.MOUSE_RELEASED:
+ // Clear our memory of the original PRESSED event, only if
+ // we're not expecting a CLICKED event after this. If
+ // there is a CLICKED event after this, it will do clean up.
+ if (--pressCount == 0 && mouseEventTarget != pressedComponent)
+ pressedComponent = null;
+ break;
+ }
+ }
}
}
}
@@ -874,17 +890,18 @@ public class BasicInternalFrameUI extends InternalFrameUI
* This helper class listens for PropertyChangeEvents from the
* JInternalFrame.
*/
- public class InternalFramePropertyChangeListener
- implements PropertyChangeListener, VetoableChangeListener
+ public class InternalFramePropertyChangeListener implements
+ PropertyChangeListener, VetoableChangeListener
{
/**
- * This method is called when one of the JInternalFrame's properties
- * change. This method is to allow JInternalFrame to veto an attempt
- * to close the internal frame. This allows JInternalFrame to honour
- * its defaultCloseOperation if that is DO_NOTHING_ON_CLOSE.
+ * This method is called when one of the JInternalFrame's properties change.
+ * This method is to allow JInternalFrame to veto an attempt to close the
+ * internal frame. This allows JInternalFrame to honour its
+ * defaultCloseOperation if that is DO_NOTHING_ON_CLOSE.
*/
- public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
+ public void vetoableChange(PropertyChangeEvent e)
+ throws PropertyVetoException
{
if (e.getPropertyName().equals(JInternalFrame.IS_CLOSED_PROPERTY))
{
@@ -892,75 +909,78 @@ public class BasicInternalFrameUI extends InternalFrameUI
{
frame.setVisible(false);
frame.getDesktopPane().repaint();
- throw new PropertyVetoException ("close operation is HIDE_ON_CLOSE\n", e);
+ throw new PropertyVetoException(
+ "close operation is HIDE_ON_CLOSE\n",
+ e);
}
else if (frame.getDefaultCloseOperation() == JInternalFrame.DISPOSE_ON_CLOSE)
closeFrame(frame);
else
- throw new PropertyVetoException ("close operation is DO_NOTHING_ON_CLOSE\n", e);
+ throw new PropertyVetoException(
+ "close operation is DO_NOTHING_ON_CLOSE\n",
+ e);
}
}
-
+
/**
- * This method is called when one of the JInternalFrame's properties
- * change.
- *
- * @param evt The PropertyChangeEvent.
+ * This method is called when one of the JInternalFrame's properties change.
+ *
+ * @param evt
+ * The PropertyChangeEvent.
*/
public void propertyChange(PropertyChangeEvent evt)
{
if (evt.getPropertyName().equals(JInternalFrame.IS_MAXIMUM_PROPERTY))
{
- if (frame.isMaximum())
- maximizeFrame(frame);
- else
- minimizeFrame(frame);
+ if (frame.isMaximum())
+ maximizeFrame(frame);
+ else
+ minimizeFrame(frame);
}
else if (evt.getPropertyName().equals(JInternalFrame.IS_ICON_PROPERTY))
{
- if (frame.isIcon())
- iconifyFrame(frame);
- else
- deiconifyFrame(frame);
+ if (frame.isIcon())
+ iconifyFrame(frame);
+ else
+ deiconifyFrame(frame);
}
else if (evt.getPropertyName().equals(JInternalFrame.IS_SELECTED_PROPERTY))
{
- if (frame.isSelected())
- activateFrame(frame);
- else
- getDesktopManager().deactivateFrame(frame);
+ if (frame.isSelected())
+ activateFrame(frame);
+ else
+ deactivateFrame(frame);
}
else if (evt.getPropertyName().equals(JInternalFrame.ROOT_PANE_PROPERTY)
- || evt.getPropertyName().equals(JInternalFrame.GLASS_PANE_PROPERTY))
+ || evt.getPropertyName().equals(
+ JInternalFrame.GLASS_PANE_PROPERTY))
{
- Component old = (Component) evt.getOldValue();
- old.removeMouseListener(glassPaneDispatcher);
- old.removeMouseMotionListener(glassPaneDispatcher);
+ Component old = (Component) evt.getOldValue();
+ old.removeMouseListener(glassPaneDispatcher);
+ old.removeMouseMotionListener(glassPaneDispatcher);
- Component newPane = (Component) evt.getNewValue();
- newPane.addMouseListener(glassPaneDispatcher);
- newPane.addMouseMotionListener(glassPaneDispatcher);
+ Component newPane = (Component) evt.getNewValue();
+ newPane.addMouseListener(glassPaneDispatcher);
+ newPane.addMouseMotionListener(glassPaneDispatcher);
- frame.revalidate();
+ frame.revalidate();
}
- /* FIXME: need to add ancestor properties to JComponents.
- else if (evt.getPropertyName().equals(JComponent.ANCESTOR_PROPERTY))
- {
- if (desktopPane != null)
- desktopPane.removeComponentListener(componentListener);
- desktopPane = frame.getDesktopPane();
- if (desktopPane != null)
- desktopPane.addComponentListener(componentListener);
- }
- */
+ /*
+ * FIXME: need to add ancestor properties to JComponents. else if
+ * (evt.getPropertyName().equals(JComponent.ANCESTOR_PROPERTY)) { if
+ * (desktopPane != null)
+ * desktopPane.removeComponentListener(componentListener); desktopPane =
+ * frame.getDesktopPane(); if (desktopPane != null)
+ * desktopPane.addComponentListener(componentListener); }
+ */
}
}
/**
* This helper class is the border for the JInternalFrame.
*/
- private class InternalFrameBorder extends AbstractBorder
- implements UIResource
+ private class InternalFrameBorder extends AbstractBorder implements
+ UIResource
{
/** The width of the border. */
private static final int bSize = 5;
@@ -970,7 +990,7 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method returns whether the border is opaque.
- *
+ *
* @return Whether the border is opaque.
*/
public boolean isBorderOpaque()
@@ -980,9 +1000,9 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method returns the insets of the border.
- *
- * @param c The Component to find border insets for.
- *
+ *
+ * @param c
+ * The Component to find border insets for.
* @return The border insets.
*/
public Insets getBorderInsets(Component c)
@@ -992,13 +1012,19 @@ public class BasicInternalFrameUI extends InternalFrameUI
/**
* This method paints the border.
- *
- * @param c The Component that owns the border.
- * @param g The Graphics object to paint with.
- * @param x The x coordinate to paint at.
- * @param y The y coordinate to paint at.
- * @param width The width of the Component.
- * @param height The height of the Component.
+ *
+ * @param c
+ * The Component that owns the border.
+ * @param g
+ * The Graphics object to paint with.
+ * @param x
+ * The x coordinate to paint at.
+ * @param y
+ * The y coordinate to paint at.
+ * @param width
+ * The width of the Component.
+ * @param height
+ * The height of the Component.
*/
public void paintBorder(Component c, Graphics g, int x, int y, int width,
int height)
@@ -1111,6 +1137,7 @@ public class BasicInternalFrameUI extends InternalFrameUI
*/
public BasicInternalFrameUI(JInternalFrame b)
{
+ // Nothing to do here.
}
/**
@@ -1135,21 +1162,21 @@ public class BasicInternalFrameUI extends InternalFrameUI
{
if (c instanceof JInternalFrame)
{
- frame = (JInternalFrame) c;
+ frame = (JInternalFrame) c;
- internalFrameLayout = createLayoutManager();
- frame.setLayout(internalFrameLayout);
+ internalFrameLayout = createLayoutManager();
+ frame.setLayout(internalFrameLayout);
- ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(false);
- frame.getRootPane().getGlassPane().setVisible(true);
+ ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(false);
+ frame.getRootPane().getGlassPane().setVisible(true);
- installDefaults();
- installListeners();
- installComponents();
- installKeyboardActions();
+ installDefaults();
+ installListeners();
+ installComponents();
+ installKeyboardActions();
- frame.setOpaque(true);
- frame.invalidate();
+ frame.setOpaque(true);
+ frame.invalidate();
}
}
@@ -1177,10 +1204,8 @@ public class BasicInternalFrameUI extends InternalFrameUI
*/
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- Border border = defaults.getBorder("InternalFrame.border");
- frame.setBorder(border);
- frame.setFrameIcon(defaults.getIcon("InternalFrame.icon"));
+ LookAndFeel.installBorder(frame, "InternalFrame.border");
+ frame.setFrameIcon(UIManager.getIcon("InternalFrame.icon"));
// InternalFrames are invisible by default.
frame.setVisible(false);
}
@@ -1343,14 +1368,14 @@ public class BasicInternalFrameUI extends InternalFrameUI
{
if (currentPane != null)
{
- deinstallMouseHandlers(currentPane);
- frame.remove(currentPane);
+ deinstallMouseHandlers(currentPane);
+ frame.remove(currentPane);
}
if (newPane != null)
{
- installMouseHandlers(newPane);
- frame.add(newPane);
+ installMouseHandlers(newPane);
+ frame.add(newPane);
}
}
@@ -1678,6 +1703,16 @@ public class BasicInternalFrameUI extends InternalFrameUI
}
/**
+ * This is a convenience method that deactivates the JInternalFrame.
+ *
+ * @param f the JInternalFrame to deactivate
+ */
+ protected void deactivateFrame(JInternalFrame f)
+ {
+ getDesktopManager().deactivateFrame(f);
+ }
+
+ /**
* This method returns a new ComponentListener for the JDesktopPane.
*
* @return A new ComponentListener.
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java
index bb9ce6cb1d9..c8f677fa0a0 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java
@@ -50,9 +50,8 @@ import java.beans.PropertyChangeListener;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
+import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
-import javax.swing.UIDefaults;
-import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.LabelUI;
@@ -60,9 +59,7 @@ import javax.swing.plaf.LabelUI;
* This is the Basic Look and Feel class for the JLabel. One BasicLabelUI
* object is used to paint all JLabels that utilize the Basic Look and Feel.
*/
-public class BasicLabelUI
- extends LabelUI
- implements PropertyChangeListener
+public class BasicLabelUI extends LabelUI implements PropertyChangeListener
{
/** The labelUI that is shared by all labels. */
protected static BasicLabelUI labelUI;
@@ -345,11 +342,8 @@ public class BasicLabelUI
*/
protected void installDefaults(JLabel c)
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- c.setForeground(defaults.getColor("Label.foreground"));
- c.setBackground(defaults.getColor("Label.background"));
- c.setFont(defaults.getFont("Label.font"));
+ LookAndFeel.installColorsAndFont(c, "Label.background", "Label.foreground",
+ "Label.font");
//XXX: There are properties we don't use called disabledForeground
//and disabledShadow.
}
@@ -417,8 +411,6 @@ public class BasicLabelUI
*/
public void propertyChange(PropertyChangeEvent e)
{
- JLabel c = (JLabel) e.getSource();
- c.revalidate();
- c.repaint();
+ // What to do here?
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java
index 841bd670f67..33932991473 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java
@@ -38,31 +38,35 @@ 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.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
+import javax.swing.AbstractAction;
+import javax.swing.ActionMap;
import javax.swing.CellRendererPane;
+import javax.swing.DefaultListSelectionModel;
+import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JViewport;
+import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
+import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ListDataEvent;
@@ -70,7 +74,9 @@ import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.MouseInputListener;
+import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.InputMapUIResource;
import javax.swing.plaf.ListUI;
/**
@@ -125,8 +131,9 @@ public class BasicListUI extends ListUI
* Helper method to repaint the focused cell's
* lost or acquired focus state.
*/
- void repaintCellFocus()
+ protected void repaintCellFocus()
{
+ // TODO: Implement this properly.
}
}
@@ -183,141 +190,231 @@ public class BasicListUI extends ListUI
*/
public void valueChanged(ListSelectionEvent e)
{
+ int index1 = e.getFirstIndex();
+ int index2 = e.getLastIndex();
+ Rectangle damaged = getCellBounds(list, index1, index2);
+ list.repaint(damaged);
}
}
/**
- * A helper class which listens for {@link KeyEvents}s
- * from the {@link JList}.
+ * This class is used to mimmic the behaviour of the JDK when registering
+ * keyboard actions. It is the same as the private class used in JComponent
+ * for the same reason. This class receives an action event and dispatches
+ * it to the true receiver after altering the actionCommand property of the
+ * event.
*/
- private class KeyHandler extends KeyAdapter
+ private static class ActionListenerProxy
+ extends AbstractAction
{
- public KeyHandler()
+ ActionListener target;
+ String bindingCommandName;
+
+ public ActionListenerProxy(ActionListener li,
+ String cmd)
{
+ target = li;
+ bindingCommandName = cmd;
}
-
- public void keyPressed( KeyEvent evt )
+
+ public void actionPerformed(ActionEvent e)
+ {
+ ActionEvent derivedEvent = new ActionEvent(e.getSource(),
+ e.getID(),
+ bindingCommandName,
+ e.getModifiers());
+ target.actionPerformed(derivedEvent);
+ }
+ }
+
+ class ListAction extends AbstractAction
+ {
+ public void actionPerformed (ActionEvent e)
{
- int lead = BasicListUI.this.list.getLeadSelectionIndex();
- int max = BasicListUI.this.list.getModel().getSize() - 1;
+ int lead = list.getLeadSelectionIndex();
+ int max = list.getModel().getSize() - 1;
+ DefaultListSelectionModel selModel = (DefaultListSelectionModel)list.getSelectionModel();
+ String command = e.getActionCommand();
// Do nothing if list is empty
if (max == -1)
return;
-
- // Process the key event. Bindings can be found in
- // javax.swing.plaf.basic.BasicLookAndFeel.java
- if ((evt.getKeyCode() == KeyEvent.VK_DOWN)
- || (evt.getKeyCode() == KeyEvent.VK_KP_DOWN))
+
+ if (command.equals("selectNextRow"))
{
- if (evt.getModifiers() == 0)
- {
- BasicListUI.this.list.clearSelection();
- BasicListUI.this.list.setSelectedIndex(Math.min(lead+1,max));
- }
- else if (evt.getModifiers() == InputEvent.SHIFT_MASK)
+ selectNextIndex();
+ }
+ else if (command.equals("selectPreviousRow"))
+ {
+ selectPreviousIndex();
+ }
+ else if (command.equals("clearSelection"))
+ {
+ list.clearSelection();
+ }
+ else if (command.equals("selectAll"))
+ {
+ list.setSelectionInterval(0, max);
+ // this next line is to restore the lead selection index to the old
+ // position, because select-all should not change the lead index
+ list.addSelectionInterval(lead, lead);
+ }
+ else if (command.equals("selectLastRow"))
+ {
+ list.setSelectedIndex(list.getModel().getSize() - 1);
+ }
+ else if (command.equals("selectLastRowChangeLead"))
+ {
+ selModel.moveLeadSelectionIndex(list.getModel().getSize() - 1);
+ }
+ else if (command.equals("scrollDownExtendSelection"))
+ {
+ int target;
+ if (lead == list.getLastVisibleIndex())
{
- BasicListUI.this.list.getSelectionModel().
- setLeadSelectionIndex(Math.min(lead+1,max));
+ target = Math.min
+ (max, lead + (list.getLastVisibleIndex() -
+ list.getFirstVisibleIndex() + 1));
}
+ else
+ target = list.getLastVisibleIndex();
+ selModel.setLeadSelectionIndex(target);
}
- else if ((evt.getKeyCode() == KeyEvent.VK_UP)
- || (evt.getKeyCode() == KeyEvent.VK_KP_UP))
+ else if (command.equals("scrollDownChangeLead"))
{
- if (evt.getModifiers() == 0)
+ int target;
+ if (lead == list.getLastVisibleIndex())
{
- BasicListUI.this.list.clearSelection();
- BasicListUI.this.list.setSelectedIndex(Math.max(lead-1,0));
+ target = Math.min
+ (max, lead + (list.getLastVisibleIndex() -
+ list.getFirstVisibleIndex() + 1));
}
- else if (evt.getModifiers() == InputEvent.SHIFT_MASK)
+ else
+ target = list.getLastVisibleIndex();
+ selModel.moveLeadSelectionIndex(target);
+ }
+ else if (command.equals("scrollUpExtendSelection"))
+ {
+ int target;
+ if (lead == list.getFirstVisibleIndex())
{
- BasicListUI.this.list.getSelectionModel().
- setLeadSelectionIndex(Math.max(lead-1,0));
+ target = Math.max
+ (0, lead - (list.getLastVisibleIndex() -
+ list.getFirstVisibleIndex() + 1));
}
+ else
+ target = list.getFirstVisibleIndex();
+ selModel.setLeadSelectionIndex(target);
}
- else if (evt.getKeyCode() == KeyEvent.VK_PAGE_UP)
+ else if (command.equals("scrollUpChangeLead"))
{
int target;
- if (lead == BasicListUI.this.list.getFirstVisibleIndex())
+ if (lead == list.getFirstVisibleIndex())
{
target = Math.max
- (0, lead - (BasicListUI.this.list.getLastVisibleIndex() -
- BasicListUI.this.list.getFirstVisibleIndex() + 1));
+ (0, lead - (list.getLastVisibleIndex() -
+ list.getFirstVisibleIndex() + 1));
}
else
+ target = list.getFirstVisibleIndex();
+ selModel.moveLeadSelectionIndex(target);
+ }
+ else if (command.equals("selectNextRowExtendSelection"))
+ {
+ selModel.setLeadSelectionIndex(Math.min(lead + 1,max));
+ }
+ else if (command.equals("selectFirstRow"))
+ {
+ list.setSelectedIndex(0);
+ }
+ else if (command.equals("selectFirstRowChangeLead"))
+ {
+ selModel.moveLeadSelectionIndex(0);
+ }
+ else if (command.equals("selectFirstRowExtendSelection"))
+ {
+ selModel.setLeadSelectionIndex(0);
+ }
+ else if (command.equals("selectPreviousRowExtendSelection"))
+ {
+ selModel.setLeadSelectionIndex(Math.max(0,lead - 1));
+ }
+ else if (command.equals("scrollUp"))
+ {
+ int target;
+ if (lead == list.getFirstVisibleIndex())
{
- target = BasicListUI.this.list.getFirstVisibleIndex();
+ target = Math.max
+ (0, lead - (list.getLastVisibleIndex() -
+ list.getFirstVisibleIndex() + 1));
}
- if (evt.getModifiers() == 0)
- BasicListUI.this.list.setSelectedIndex(target);
- else if (evt.getModifiers() == InputEvent.SHIFT_MASK)
- BasicListUI.this.list.getSelectionModel().
- setLeadSelectionIndex(target);
+ else
+ target = list.getFirstVisibleIndex();
+ list.setSelectedIndex(target);
}
- else if (evt.getKeyCode() == KeyEvent.VK_PAGE_DOWN)
+ else if (command.equals("selectLastRowExtendSelection"))
+ {
+ selModel.setLeadSelectionIndex(list.getModel().getSize() - 1);
+ }
+ else if (command.equals("scrollDown"))
{
int target;
- if (lead == BasicListUI.this.list.getLastVisibleIndex())
+ if (lead == list.getLastVisibleIndex())
{
target = Math.min
- (max, lead + (BasicListUI.this.list.getLastVisibleIndex() -
- BasicListUI.this.list.getFirstVisibleIndex() + 1));
+ (max, lead + (list.getLastVisibleIndex() -
+ list.getFirstVisibleIndex() + 1));
}
else
+ target = list.getLastVisibleIndex();
+ list.setSelectedIndex(target);
+ }
+ else if (command.equals("selectNextRowChangeLead"))
+ {
+ if (selModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
+ selectNextIndex();
+ else
+ {
+ selModel.moveLeadSelectionIndex(Math.min(max, lead + 1));
+ }
+ }
+ else if (command.equals("selectPreviousRowChangeLead"))
+ {
+ if (selModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
+ selectPreviousIndex();
+ else
{
- target = BasicListUI.this.list.getLastVisibleIndex();
+ selModel.moveLeadSelectionIndex(Math.max(0, lead - 1));
}
- if (evt.getModifiers() == 0)
- BasicListUI.this.list.setSelectedIndex(target);
- else if (evt.getModifiers() == InputEvent.SHIFT_MASK)
- BasicListUI.this.list.getSelectionModel().
- setLeadSelectionIndex(target);
- }
- else if (evt.getKeyCode() == KeyEvent.VK_BACK_SLASH
- && (evt.getModifiers() == InputEvent.CTRL_MASK))
+ }
+ else if (command.equals("addToSelection"))
{
- BasicListUI.this.list.clearSelection();
+ list.addSelectionInterval(lead, lead);
}
- else if ((evt.getKeyCode() == KeyEvent.VK_HOME)
- || evt.getKeyCode() == KeyEvent.VK_END)
+ else if (command.equals("extendTo"))
{
- if (evt.getModifiers() != 0 &&
- evt.getModifiers() != InputEvent.SHIFT_MASK)
- return;
- // index is either 0 for HOME, or last cell for END
- int index = (evt.getKeyCode() == KeyEvent.VK_HOME) ? 0 : max;
-
- if (!evt.isShiftDown() ||(BasicListUI.this.list.getSelectionMode()
- == ListSelectionModel.SINGLE_SELECTION))
- BasicListUI.this.list.setSelectedIndex(index);
- else if (BasicListUI.this.list.getSelectionMode() ==
- ListSelectionModel.SINGLE_INTERVAL_SELECTION)
- BasicListUI.this.list.setSelectionInterval
- (BasicListUI.this.list.getAnchorSelectionIndex(), index);
- else
- BasicListUI.this.list.getSelectionModel().
- setLeadSelectionIndex(index);
+ selModel.setSelectionInterval(selModel.getAnchorSelectionIndex(),
+ lead);
}
- else if ((evt.getKeyCode() == KeyEvent.VK_A || evt.getKeyCode()
- == KeyEvent.VK_SLASH) && (evt.getModifiers() ==
- InputEvent.CTRL_MASK))
+ else if (command.equals("toggleAndAnchor"))
{
- BasicListUI.this.list.setSelectionInterval(0, max);
- // this next line is to restore the lead selection index to the old
- // position, because select-all should not change the lead index
- BasicListUI.this.list.addSelectionInterval(lead, lead);
+ if (!list.isSelectedIndex(lead))
+ list.addSelectionInterval(lead, lead);
+ else
+ list.removeSelectionInterval(lead, lead);
+ selModel.setAnchorSelectionIndex(lead);
}
- else if (evt.getKeyCode() == KeyEvent.VK_SPACE &&
- (evt.getModifiers() == InputEvent.CTRL_MASK))
+ else
{
- BasicListUI.this.list.getSelectionModel().
- setLeadSelectionIndex(Math.min(lead+1,max));
+ // DEBUG: uncomment the following line to print out
+ // key bindings that aren't implemented yet
+
+ // System.out.println ("not implemented: "+e.getActionCommand());
}
-
- BasicListUI.this.list.ensureIndexIsVisible
- (BasicListUI.this.list.getLeadSelectionIndex());
+
+ list.ensureIndexIsVisible(list.getLeadSelectionIndex());
}
}
-
+
/**
* A helper class which listens for {@link MouseEvent}s
* from the {@link JList}.
@@ -333,48 +430,46 @@ public class BasicListUI extends ListUI
public void mouseClicked(MouseEvent event)
{
Point click = event.getPoint();
- int index = BasicListUI.this.locationToIndex(list, click);
+ int index = locationToIndex(list, click);
if (index == -1)
return;
if (event.isShiftDown())
{
- if (BasicListUI.this.list.getSelectionMode() ==
- ListSelectionModel.SINGLE_SELECTION)
- BasicListUI.this.list.setSelectedIndex(index);
- else if (BasicListUI.this.list.getSelectionMode() ==
+ if (list.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION)
+ list.setSelectedIndex(index);
+ else if (list.getSelectionMode() ==
ListSelectionModel.SINGLE_INTERVAL_SELECTION)
// COMPAT: the IBM VM is compatible with the following line of code.
// However, compliance with Sun's VM would correspond to replacing
// getAnchorSelectionIndex() with getLeadSelectionIndex().This is
// both unnatural and contradictory to the way they handle other
// similar UI interactions.
- BasicListUI.this.list.setSelectionInterval
- (BasicListUI.this.list.getAnchorSelectionIndex(), index);
+ list.setSelectionInterval(list.getAnchorSelectionIndex(), index);
else
// COMPAT: both Sun and IBM are compatible instead with:
- // BasicListUI.this.list.setSelectionInterval
- // (BasicListUI.this.list.getLeadSelectionIndex(),index);
+ // list.setSelectionInterval
+ // (list.getLeadSelectionIndex(),index);
// Note that for IBM this is contradictory to what they did in
// the above situation for SINGLE_INTERVAL_SELECTION.
// The most natural thing to do is the following:
- BasicListUI.this.list.getSelectionModel().
- setLeadSelectionIndex(index);
+ if (list.isSelectedIndex(list.getAnchorSelectionIndex()))
+ list.getSelectionModel().setLeadSelectionIndex(index);
+ else
+ list.addSelectionInterval(list.getAnchorSelectionIndex(), index);
}
else if (event.isControlDown())
{
- if (BasicListUI.this.list.getSelectionMode() ==
- ListSelectionModel.SINGLE_SELECTION)
- BasicListUI.this.list.setSelectedIndex(index);
- else if (BasicListUI.this.list.isSelectedIndex(index))
- BasicListUI.this.list.removeSelectionInterval(index,index);
+ if (list.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION)
+ list.setSelectedIndex(index);
+ else if (list.isSelectedIndex(index))
+ list.removeSelectionInterval(index,index);
else
- BasicListUI.this.list.addSelectionInterval(index,index);
+ list.addSelectionInterval(index,index);
}
else
- BasicListUI.this.list.setSelectedIndex(index);
+ list.setSelectedIndex(index);
- BasicListUI.this.list.ensureIndexIsVisible
- (BasicListUI.this.list.getLeadSelectionIndex());
+ list.ensureIndexIsVisible(list.getLeadSelectionIndex());
}
/**
@@ -385,6 +480,7 @@ public class BasicListUI extends ListUI
*/
public void mousePressed(MouseEvent event)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -395,6 +491,7 @@ public class BasicListUI extends ListUI
*/
public void mouseReleased(MouseEvent event)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -405,6 +502,7 @@ public class BasicListUI extends ListUI
*/
public void mouseEntered(MouseEvent event)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -415,6 +513,7 @@ public class BasicListUI extends ListUI
*/
public void mouseExited(MouseEvent event)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -425,6 +524,7 @@ public class BasicListUI extends ListUI
*/
public void mouseDragged(MouseEvent event)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -435,6 +535,7 @@ public class BasicListUI extends ListUI
*/
public void mouseMoved(MouseEvent event)
{
+ // TODO: What should be done here, if anything?
}
}
@@ -459,11 +560,61 @@ public class BasicListUI extends ListUI
if (e.getNewValue() != null && e.getNewValue() instanceof ListModel)
((ListModel) e.getNewValue()).addListDataListener(BasicListUI.this.listDataListener);
}
+ // Update the updateLayoutStateNeeded flag.
+ if (e.getPropertyName().equals("model"))
+ updateLayoutStateNeeded += modelChanged;
+ else if (e.getPropertyName().equals("selectionModel"))
+ updateLayoutStateNeeded += selectionModelChanged;
+ else if (e.getPropertyName().equals("font"))
+ updateLayoutStateNeeded += fontChanged;
+ else if (e.getPropertyName().equals("fixedCellWidth"))
+ updateLayoutStateNeeded += fixedCellWidthChanged;
+ else if (e.getPropertyName().equals("fixedCellHeight"))
+ updateLayoutStateNeeded += fixedCellHeightChanged;
+ else if (e.getPropertyName().equals("prototypeCellValue"))
+ updateLayoutStateNeeded += prototypeCellValueChanged;
+ else if (e.getPropertyName().equals("cellRenderer"))
+ updateLayoutStateNeeded += cellRendererChanged;
BasicListUI.this.damageLayout();
}
}
/**
+ * A constant to indicate that the model has changed.
+ */
+ protected static final int modelChanged = 1;
+
+ /**
+ * A constant to indicate that the selection model has changed.
+ */
+ protected static final int selectionModelChanged = 2;
+
+ /**
+ * A constant to indicate that the font has changed.
+ */
+ protected static final int fontChanged = 4;
+
+ /**
+ * A constant to indicate that the fixedCellWidth has changed.
+ */
+ protected static final int fixedCellWidthChanged = 8;
+
+ /**
+ * A constant to indicate that the fixedCellHeight has changed.
+ */
+ protected static final int fixedCellHeightChanged = 16;
+
+ /**
+ * A constant to indicate that the prototypeCellValue has changed.
+ */
+ protected static final int prototypeCellValueChanged = 32;
+
+ /**
+ * A constant to indicate that the cellRenderer has changed.
+ */
+ protected static final int cellRendererChanged = 64;
+
+ /**
* Creates a new BasicListUI for the component.
*
* @param c The component to create a UI for
@@ -487,9 +638,6 @@ public class BasicListUI extends ListUI
/** The mouse listener listening to the list. */
protected MouseInputListener mouseInputListener;
- /** The key listener listening to the list */
- private KeyHandler keyListener;
-
/** The property change listener listening to the list. */
protected PropertyChangeListener propertyChangeListener;
@@ -501,7 +649,11 @@ public class BasicListUI extends ListUI
/** Saved reference to the list this UI was created for. */
protected JList list;
- /** The height of a single cell in the list. */
+ /**
+ * The height of a single cell in the list. This field is used when the
+ * fixedCellHeight property of the list is set. Otherwise this field is
+ * set to <code>-1</code> and {@link #cellHeights} is used instead.
+ */
protected int cellHeight;
/** The width of a single cell in the list. */
@@ -509,14 +661,25 @@ public class BasicListUI extends ListUI
/**
* An array of varying heights of cells in the list, in cases where each
- * cell might have a different height.
+ * cell might have a different height. This field is used when the
+ * <code>fixedCellHeight</code> property of the list is not set. Otherwise
+ * this field is <code>null</code> and {@link #cellHeight} is used.
*/
protected int[] cellHeights;
/**
- * A simple counter. When nonzero, indicates that the UI class is out of
+ * A bitmask that indicates which properties of the JList have changed.
+ * When nonzero, indicates that the UI class is out of
* date with respect to the underlying list, and must recalculate the
* list layout before painting or performing size calculations.
+ *
+ * @see #modelChanged
+ * @see #selectionModelChanged
+ * @see #fontChanged
+ * @see #fixedCellWidthChanged
+ * @see #fixedCellHeightChanged
+ * @see #prototypeCellValueChanged
+ * @see #cellRendererChanged
*/
protected int updateLayoutStateNeeded;
@@ -524,6 +687,9 @@ public class BasicListUI extends ListUI
* The {@link CellRendererPane} that is used for painting.
*/
protected CellRendererPane rendererPane;
+
+ /** The action bound to KeyStrokes. */
+ ListAction action;
/**
* Calculate the height of a particular row. If there is a fixed {@link
@@ -611,19 +777,51 @@ public class BasicListUI extends ListUI
* @param y0 The Y coordinate to calculate the row number for
*
* @return The row number containing the specified Y value, or <code>-1</code>
- * if the specified Y coordinate is invalid
+ * if the list model is empty
+ *
+ * @specnote This method is specified to return -1 for an invalid Y
+ * coordinate. However, some simple tests show that the behaviour
+ * is to return the index of the last list element for an Y
+ * coordinate that lies outside of the list bounds (even for
+ * negative indices). <code>-1</code>
+ * is only returned if the list model is empty.
*/
protected int convertYToRow(int y0)
{
- for (int row = 0; row < cellHeights.length; ++row)
- {
- int h = getRowHeight(row);
+ if (list.getModel().getSize() == 0)
+ return -1;
+
+ // When y0 < 0, then the JDK returns the maximum row index of the list. So
+ // do we.
+ if (y0 < 0)
+ return list.getModel().getSize() - 1;
+
+ // Update the layout if necessary.
+ maybeUpdateLayoutState();
+
+ int index = list.getModel().getSize() - 1;;
- if (y0 < h)
- return row;
- y0 -= h;
+ // If a fixed cell height is set, then we can work more efficient.
+ if (cellHeight > 0)
+ {
+ index = Math.max(y0 / cellHeight, index);
+ }
+ // If we have no fixed cell height, we must add up each cell height up
+ // to y0.
+ else
+ {
+ int h = 0;
+ for (int row = 0; row < cellHeights.length; ++row)
+ {
+ h += cellHeights[row];
+ if (y0 < h)
+ {
+ index = row;
+ break;
+ }
+ }
}
- return -1;
+ return index;
}
/**
@@ -638,29 +836,47 @@ public class BasicListUI extends ListUI
cellWidth = -1;
if (cellHeights == null || cellHeights.length != nrows)
cellHeights = new int[nrows];
- if (list.getFixedCellHeight() == -1 || list.getFixedCellWidth() == -1)
+ ListCellRenderer rend = list.getCellRenderer();
+ // Update the cellHeight(s) fields.
+ int fixedCellHeight = list.getFixedCellHeight();
+ if (fixedCellHeight > 0)
+ {
+ cellHeight = fixedCellHeight;
+ cellHeights = null;
+ }
+ else
{
- ListCellRenderer rend = list.getCellRenderer();
+ cellHeight = -1;
for (int i = 0; i < nrows; ++i)
{
- Component flyweight = rend.getListCellRendererComponent(list,
- list.getModel()
- .getElementAt(i),
- 0, false,
- false);
+ Component flyweight =
+ rend.getListCellRendererComponent(list,
+ list.getModel().getElementAt(i),
+ i, list.isSelectedIndex(i),
+ list.getSelectionModel().getAnchorSelectionIndex() == i);
Dimension dim = flyweight.getPreferredSize();
cellHeights[i] = dim.height;
- // compute average cell height (little hack here)
- cellHeight = (cellHeight * i + cellHeights[i]) / (i + 1);
- cellWidth = Math.max(cellWidth, dim.width);
- if (list.getLayoutOrientation() == JList.VERTICAL)
- cellWidth = Math.max(cellWidth, list.getSize().width);
}
}
+
+ // Update the cellWidth field.
+ int fixedCellWidth = list.getFixedCellWidth();
+ if (fixedCellWidth > 0)
+ cellWidth = fixedCellWidth;
else
{
- cellHeight = list.getFixedCellHeight();
- cellWidth = list.getFixedCellWidth();
+ for (int i = 0; i < nrows; ++i)
+ {
+ Component flyweight =
+ rend.getListCellRendererComponent(list,
+ list.getModel().getElementAt(i),
+ i, list.isSelectedIndex(i),
+ list.getSelectionModel().getAnchorSelectionIndex() == i);
+ Dimension dim = flyweight.getPreferredSize();
+ cellWidth = Math.max(cellWidth, dim.width);
+ }
+ if (list.getLayoutOrientation() == JList.VERTICAL)
+ cellWidth = Math.max(cellWidth, list.getSize().width);
}
}
@@ -694,13 +910,6 @@ public class BasicListUI extends ListUI
*/
public BasicListUI()
{
- focusListener = new FocusHandler();
- listDataListener = new ListDataHandler();
- listSelectionListener = new ListSelectionHandler();
- mouseInputListener = new MouseInputHandler();
- keyListener = new KeyHandler();
- propertyChangeListener = new PropertyChangeHandler();
- componentListener = new ComponentHandler();
updateLayoutStateNeeded = 1;
rendererPane = new CellRendererPane();
}
@@ -713,11 +922,10 @@ public class BasicListUI extends ListUI
*/
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- list.setForeground(defaults.getColor("List.foreground"));
- list.setBackground(defaults.getColor("List.background"));
- list.setSelectionForeground(defaults.getColor("List.selectionForeground"));
- list.setSelectionBackground(defaults.getColor("List.selectionBackground"));
+ LookAndFeel.installColorsAndFont(list, "List.background",
+ "List.foreground", "List.font");
+ list.setSelectionForeground(UIManager.getColor("List.selectionForeground"));
+ list.setSelectionBackground(UIManager.getColor("List.selectionBackground"));
list.setOpaque(true);
}
@@ -727,7 +935,6 @@ public class BasicListUI extends ListUI
*/
protected void uninstallDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
list.setForeground(null);
list.setBackground(null);
list.setSelectionForeground(null);
@@ -742,14 +949,28 @@ public class BasicListUI extends ListUI
*/
protected void installListeners()
{
+ if (focusListener == null)
+ focusListener = createFocusListener();
list.addFocusListener(focusListener);
+ if (listDataListener == null)
+ listDataListener = createListDataListener();
list.getModel().addListDataListener(listDataListener);
+ if (listSelectionListener == null)
+ listSelectionListener = createListSelectionListener();
list.addListSelectionListener(listSelectionListener);
+ if (mouseInputListener == null)
+ mouseInputListener = createMouseInputListener();
list.addMouseListener(mouseInputListener);
- list.addKeyListener(keyListener);
list.addMouseMotionListener(mouseInputListener);
+ if (propertyChangeListener == null)
+ propertyChangeListener = createPropertyChangeListener();
list.addPropertyChangeListener(propertyChangeListener);
+
+ // FIXME: Are these two really needed? At least they are not documented.
+ //keyListener = new KeyHandler();
+ componentListener = new ComponentHandler();
list.addComponentListener(componentListener);
+ //list.addKeyListener(keyListener);
}
/**
@@ -761,16 +982,41 @@ public class BasicListUI extends ListUI
list.getModel().removeListDataListener(listDataListener);
list.removeListSelectionListener(listSelectionListener);
list.removeMouseListener(mouseInputListener);
- list.removeKeyListener(keyListener);
+ //list.removeKeyListener(keyListener);
list.removeMouseMotionListener(mouseInputListener);
list.removePropertyChangeListener(propertyChangeListener);
}
-
+
/**
* Installs keyboard actions for this UI in the {@link JList}.
*/
protected void installKeyboardActions()
{
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ InputMap focusInputMap = (InputMap)defaults.get("List.focusInputMap");
+ InputMapUIResource parentInputMap = new InputMapUIResource();
+ // FIXME: The JDK uses a LazyActionMap for parentActionMap
+ ActionMap parentActionMap = new ActionMapUIResource();
+ action = new ListAction();
+ Object keys[] = focusInputMap.allKeys();
+ // Register key bindings in the UI InputMap-ActionMap pair
+ for (int i = 0; i < keys.length; i++)
+ {
+ KeyStroke stroke = (KeyStroke)keys[i];
+ String actionString = (String) focusInputMap.get(stroke);
+ parentInputMap.put(KeyStroke.getKeyStroke(stroke.getKeyCode(),
+ stroke.getModifiers()),
+ actionString);
+
+ parentActionMap.put (actionString,
+ new ActionListenerProxy(action, actionString));
+ }
+ // Register the new InputMap-ActionMap as the parents of the list's
+ // InputMap and ActionMap
+ parentInputMap.setParent(list.getInputMap().getParent());
+ parentActionMap.setParent(list.getActionMap().getParent());
+ list.getInputMap().setParent(parentInputMap);
+ list.getActionMap().setParent(parentActionMap);
}
/**
@@ -778,6 +1024,7 @@ public class BasicListUI extends ListUI
*/
protected void uninstallKeyboardActions()
{
+ // TODO: Implement this properly.
}
/**
@@ -855,22 +1102,6 @@ public class BasicListUI extends ListUI
}
/**
- * Paints the packground of the list using the background color
- * of the specified component.
- *
- * @param g The graphics context to paint in
- * @param c The component to paint the background of
- */
- private void paintBackground(Graphics g, JComponent c)
- {
- Dimension size = getPreferredSize(c);
- Color save = g.getColor();
- g.setColor(c.getBackground());
- g.fillRect(0, 0, size.width, size.height);
- g.setColor(save);
- }
-
- /**
* Paints a single cell in the list.
*
* @param g The graphics context to paint in
@@ -892,14 +1123,12 @@ public class BasicListUI extends ListUI
Component comp = rend.getListCellRendererComponent(list,
data.getElementAt(row),
0, isSel, hasFocus);
- //comp.setBounds(new Rectangle(0, 0, bounds.width, bounds.height));
- //comp.paint(g);
rendererPane.paintComponent(g, comp, list, bounds);
}
/**
- * Paints the list by calling {@link #paintBackground} and then repeatedly
- * calling {@link #paintCell} for each visible cell in the list.
+ * Paints the list by repeatedly calling {@link #paintCell} for each visible
+ * cell in the list.
*
* @param g The graphics context to paint with
* @param c Ignored; uses the saved {@link JList} reference
@@ -916,9 +1145,12 @@ public class BasicListUI extends ListUI
ListSelectionModel sel = list.getSelectionModel();
int lead = sel.getLeadSelectionIndex();
Rectangle clip = g.getClipBounds();
- paintBackground(g, list);
- for (int row = 0; row < nrows; ++row)
+ int startIndex = list.locationToIndex(new Point(clip.x, clip.y));
+ int endIndex = list.locationToIndex(new Point(clip.x + clip.width,
+ clip.y + clip.height));
+
+ for (int row = startIndex; row <= endIndex; ++row)
{
Rectangle bounds = getCellBounds(list, row, row);
if (bounds.intersects(clip))
@@ -927,13 +1159,15 @@ public class BasicListUI extends ListUI
}
/**
- * Computes the index of a list cell given a point within the list.
+ * Computes the index of a list cell given a point within the list. If the
+ * location lies outside the bounds of the list, the greatest index in the
+ * list model is returned.
*
* @param list the list which on which the computation is based on
* @param location the coordinates
*
* @return the index of the list item that is located at the given
- * coordinates or <code>null</code> if the location is invalid
+ * coordinates or <code>-1</code> if the list model is empty
*/
public int locationToIndex(JList list, Point location)
{
@@ -983,7 +1217,6 @@ public class BasicListUI extends ListUI
int numberOfItems2 = list.getModel().getSize();
int cellsPerRow2 = numberOfItems2 / visibleRows2 + 1;
- Dimension listDim2 = list.getSize();
int gridX2 = Math.min(location.x / cellWidth, cellsPerRow2 - 1);
int gridY2 = Math.min(location.y / cellHeight, visibleRows2);
index = gridY2 + gridX2 * visibleRows2;
@@ -1045,4 +1278,82 @@ public class BasicListUI extends ListUI
}
return loc;
}
+
+ /**
+ * Creates and returns the focus listener for this UI.
+ *
+ * @return the focus listener for this UI
+ */
+ protected FocusListener createFocusListener()
+ {
+ return new FocusHandler();
+ }
+
+ /**
+ * Creates and returns the list data listener for this UI.
+ *
+ * @return the list data listener for this UI
+ */
+ protected ListDataListener createListDataListener()
+ {
+ return new ListDataHandler();
+ }
+
+ /**
+ * Creates and returns the list selection listener for this UI.
+ *
+ * @return the list selection listener for this UI
+ */
+ protected ListSelectionListener createListSelectionListener()
+ {
+ return new ListSelectionHandler();
+ }
+
+ /**
+ * Creates and returns the mouse input listener for this UI.
+ *
+ * @return the mouse input listener for this UI
+ */
+ protected MouseInputListener createMouseInputListener()
+ {
+ return new MouseInputHandler();
+ }
+
+ /**
+ * Creates and returns the property change listener for this UI.
+ *
+ * @return the property change listener for this UI
+ */
+ protected PropertyChangeListener createPropertyChangeListener()
+ {
+ return new PropertyChangeHandler();
+ }
+
+ /**
+ * Selects the next list item and force it to be visible.
+ */
+ protected void selectNextIndex()
+ {
+ int index = list.getSelectionModel().getLeadSelectionIndex();
+ if (index < list.getModel().getSize() - 1)
+ {
+ index++;
+ list.setSelectedIndex(index);
+ }
+ list.ensureIndexIsVisible(index);
+ }
+
+ /**
+ * Selects the previous list item and force it to be visible.
+ */
+ protected void selectPreviousIndex()
+ {
+ int index = list.getSelectionModel().getLeadSelectionIndex();
+ if (index > 0)
+ {
+ index--;
+ list.setSelectedIndex(index);
+ }
+ list.ensureIndexIsVisible(index);
+ }
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java
index d35ac9eb926..8ebe650350c 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java
@@ -273,7 +273,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"Button.foreground", new ColorUIResource(Color.BLACK),
"Button.highlight", new ColorUIResource(Color.WHITE),
"Button.light", new ColorUIResource(Color.LIGHT_GRAY),
- "Button.margin", new InsetsUIResource(2, 2, 2, 2),
+ "Button.margin", new InsetsUIResource(2, 14, 2, 14),
"Button.shadow", new ColorUIResource(Color.GRAY),
"Button.textIconGap", new Integer(4),
"Button.textShiftOffset", new Integer(0),
@@ -362,16 +362,16 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"HOME", "homePassThrough",
"END", "endPassThrough"
}),
- "ComboBox.background", new ColorUIResource(light),
+ "ComboBox.background", new ColorUIResource(Color.white),
"ComboBox.buttonBackground", new ColorUIResource(light),
- "ComboBox.buttonDarkShadow", new ColorUIResource(shadow),
+ "ComboBox.buttonDarkShadow", new ColorUIResource(darkShadow),
"ComboBox.buttonHighlight", new ColorUIResource(highLight),
"ComboBox.buttonShadow", new ColorUIResource(shadow),
"ComboBox.disabledBackground", new ColorUIResource(light),
"ComboBox.disabledForeground", new ColorUIResource(Color.gray),
"ComboBox.font", new FontUIResource("SansSerif", Font.PLAIN, 12),
"ComboBox.foreground", new ColorUIResource(Color.black),
- "ComboBox.selectionBackground", new ColorUIResource(Color.black),
+ "ComboBox.selectionBackground", new ColorUIResource(0, 0, 128),
"ComboBox.selectionForeground", new ColorUIResource(Color.white),
"Desktop.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] {
"KP_LEFT", "left",
@@ -397,7 +397,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"DesktopIcon.border", new BorderUIResource.CompoundBorderUIResource(null,
null),
"EditorPane.background", new ColorUIResource(Color.white),
- "EditorPane.border", new BasicBorders.MarginBorder(),
+ "EditorPane.border", BasicBorders.getMarginBorder(),
"EditorPane.caretBlinkRate", new Integer(500),
"EditorPane.caretForeground", new ColorUIResource(Color.black),
"EditorPane.font", new FontUIResource("Serif", Font.PLAIN, 12),
@@ -466,6 +466,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"FocusManagerClassName", "TODO",
"FormattedTextField.background", new ColorUIResource(light),
"FormattedTextField.caretForeground", new ColorUIResource(Color.black),
+ "FormattedTextField.font",
+ new FontUIResource("SansSerif", Font.PLAIN, 12),
"FormattedTextField.foreground", new ColorUIResource(Color.black),
"FormattedTextField.inactiveBackground", new ColorUIResource(light),
"FormattedTextField.inactiveForeground", new ColorUIResource(Color.gray),
@@ -528,30 +530,74 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"Label.disabledShadow", new ColorUIResource(shadow),
"Label.font", new FontUIResource("Dialog", Font.PLAIN, 12),
"Label.foreground", new ColorUIResource(darkShadow),
- "List.background", new ColorUIResource(light),
+ "List.background", new ColorUIResource(Color.white),
"List.border", new BasicBorders.MarginBorder(),
"List.focusInputMap", new UIDefaults.LazyInputMap(new Object[] {
- "PAGE_UP", "scrollUp",
- "ctrl \\", "clearSelection",
- "PAGE_DOWN", "scrollDown",
- "shift PAGE_DOWN","scrollDownExtendSelection",
+ "ctrl DOWN", "selectNextRowChangeLead",
+ "shift UP", "selectPreviousRowExtendSelection",
+ "ctrl RIGHT", "selectNextColumnChangeLead",
+ "shift ctrl LEFT", "selectPreviousColumnExtendSelection",
+ "shift KP_UP", "selectPreviousRowChangeLead",
+ "DOWN", "selectNextRow",
+ "ctrl UP", "selectPreviousRowChangeLead",
+ "ctrl LEFT", "selectPreviousColumnChangeLead",
+ "CUT", "cut",
"END", "selectLastRow",
- "HOME", "selectFirstRow",
- "shift END", "selectLastRowExtendSelection",
+ "shift PAGE_UP","scrollUpExtendSelection",
+ "KP_UP", "selectPreviousRow",
+ "shift ctrl UP", "selectPreviousRowExtendSelection",
+ "ctrl HOME", "selectFirstRowChangeLead",
+ "shift LEFT", "selectPreviousColumnExtendSelection",
+ "ctrl END", "selectLastRowChangeLead",
+ "ctrl PAGE_DOWN", "scrollDownChangeLead",
+ "shift ctrl RIGHT", "selectNextColumnExtendSelection",
+ "LEFT", "selectPreviousColumn",
+ "ctrl PAGE_UP", "scrollUpChangeLead",
+ "KP_LEFT", "selectPreviousColumn",
+ "shift KP_RIGHT", "selectNextColumnExtendSelection",
+ "SPACE", "addToSelection",
+ "ctrl SPACE", "toggleAndAnchor",
+ "shift SPACE", "extendTo",
+ "shift ctrl SPACE", "moveSelectionTo",
+ "shift ctrl DOWN", "selectNextRowExtendSelection",
+ "ctrl BACK_SLASH", "clearSelection",
"shift HOME", "selectFirstRowExtendSelection",
- "UP", "selectPreviousRow",
- "ctrl /", "selectAll",
- "ctrl A", "selectAll",
- "DOWN", "selectNextRow",
- "shift UP", "selectPreviousRowExtendSelection",
- "ctrl SPACE", "selectNextRowExtendSelection",
+ "RIGHT", "selectNextColumn",
+ "shift ctrl PAGE_UP", "scrollUpExtendSelection",
"shift DOWN", "selectNextRowExtendSelection",
- "KP_UP", "selectPreviousRow",
- "shift PAGE_UP","scrollUpExtendSelection",
- "KP_DOWN", "selectNextRow"
+ "PAGE_DOWN", "scrollDown",
+ "shift ctrl KP_UP", "selectPreviousRowExtendSelection",
+ "shift KP_LEFT", "selectPreviousColumnExtendSelection",
+ "ctrl X", "cut",
+ "shift ctrl PAGE_DOWN", "scrollDownExtendSelection",
+ "ctrl SLASH", "selectAll",
+ "ctrl C", "copy",
+ "ctrl KP_RIGHT", "selectNextColumnChangeLead",
+ "shift END", "selectLastRowExtendSelection",
+ "shift ctrl KP_DOWN", "selectNextRowExtendSelection",
+ "ctrl KP_LEFT", "selectPreviousColumnChangeLead",
+ "HOME", "selectFirstRow",
+ "ctrl V", "paste",
+ "KP_DOWN", "selectNextRow",
+ "ctrl KP_DOWN", "selectNextRowChangeLead",
+ "shift RIGHT", "selectNextColumnExtendSelection",
+ "ctrl A", "selectAll",
+ "shift ctrl END", "selectLastRowExtendSelection",
+ "COPY", "copy",
+ "ctrl KP_UP", "selectPreviousRowChangeLead",
+ "shift ctrl KP_LEFT", "selectPreviousColumnExtendSelection",
+ "shift KP_DOWN", "selectNextRowExtendSelection",
+ "UP", "selectPreviousRow",
+ "shift ctrl HOME", "selectFirstRowExtendSelection",
+ "shift PAGE_DOWN", "scrollDownExtendSelection",
+ "KP_RIGHT", "selectNextColumn",
+ "shift ctrl KP_RIGHT", "selectNextColumnExtendSelection",
+ "PAGE_UP", "scrollUp",
+ "PASTE", "paste"
}),
- "List.foreground", new ColorUIResource(darkShadow),
- "List.selectionBackground", new ColorUIResource(Color.black),
+ "List.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "List.foreground", new ColorUIResource(Color.black),
+ "List.selectionBackground", new ColorUIResource(0, 0, 128),
"List.selectionForeground", new ColorUIResource(Color.white),
"List.focusCellHighlightBorder",
new BorderUIResource.
@@ -601,7 +647,6 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"MenuItem.background", new ColorUIResource(light),
"MenuItem.border", new BasicBorders.MarginBorder(),
"MenuItem.borderPainted", Boolean.FALSE,
- "MenuItem.checkIcon", BasicIconFactory.getMenuItemCheckIcon(),
"MenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12),
"MenuItem.foreground", new ColorUIResource(darkShadow),
"MenuItem.margin", new InsetsUIResource(2, 2, 2, 2),
@@ -624,7 +669,9 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"OptionPane.messageAreaBorder",
new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0),
"OptionPane.messageForeground", new ColorUIResource(darkShadow),
- "OptionPane.minimumSize", new DimensionUIResource(262, 90),
+ "OptionPane.minimumSize",
+ new DimensionUIResource(BasicOptionPaneUI.MinimumWidth,
+ BasicOptionPaneUI.MinimumHeight),
"OptionPane.noButtonText", "No",
"OptionPane.okButtonText", "OK",
// XXX Don't use gif
@@ -660,16 +707,17 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"PopupMenu.border", new BorderUIResource.BevelBorderUIResource(0),
"PopupMenu.font", new FontUIResource("Dialog", Font.PLAIN, 12),
"PopupMenu.foreground", new ColorUIResource(darkShadow),
- "ProgressBar.background", new ColorUIResource(light),
- "ProgressBar.border", new BorderUIResource.LineBorderUIResource(Color.darkGray),
+ "ProgressBar.background", new ColorUIResource(Color.LIGHT_GRAY),
+ "ProgressBar.border",
+ new BorderUIResource.LineBorderUIResource(Color.GREEN, 2),
"ProgressBar.cellLength", new Integer(1),
"ProgressBar.cellSpacing", new Integer(0),
"ProgressBar.font", new FontUIResource("Dialog", Font.PLAIN, 12),
- "ProgressBar.foreground", new ColorUIResource(Color.black),
- "ProgressBar.selectionBackground", new ColorUIResource(Color.black),
- "ProgressBar.selectionForeground", new ColorUIResource(light),
- "ProgressBar.repaintInterval", new Integer(250),
- "ProgressBar.cycleTime", new Integer(6000),
+ "ProgressBar.foreground", new ColorUIResource(0, 0, 128),
+ "ProgressBar.selectionBackground", new ColorUIResource(0, 0, 128),
+ "ProgressBar.selectionForeground", new ColorUIResource(Color.LIGHT_GRAY),
+ "ProgressBar.repaintInterval", new Integer(50),
+ "ProgressBar.cycleTime", new Integer(3000),
"RadioButton.background", new ColorUIResource(light),
"RadioButton.border", new BorderUIResource.CompoundBorderUIResource(null,
null),
@@ -742,6 +790,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"ScrollBar.thumbShadow", new ColorUIResource(shadow),
"ScrollBar.track", new ColorUIResource(light),
"ScrollBar.trackHighlight", new ColorUIResource(shadow),
+ "ScrollBar.width", new Integer(16),
"ScrollPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] {
"PAGE_UP", "scrollUp",
"KP_LEFT", "unitScrollLeft",
@@ -846,6 +895,24 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"TabbedPane.tabRunOverlay", new Integer(2),
"TabbedPane.textIconGap", new Integer(4),
"Table.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] {
+ "ctrl DOWN", "selectNextRowChangeLead",
+ "ctrl RIGHT", "selectNextColumnChangeLead",
+ "ctrl UP", "selectPreviousRowChangeLead",
+ "ctrl LEFT", "selectPreviousColumnChangeLead",
+ "CUT", "cut",
+ "SPACE", "addToSelection",
+ "ctrl SPACE", "toggleAndAnchor",
+ "shift SPACE", "extendTo",
+ "shift ctrl SPACE", "moveSelectionTo",
+ "ctrl X", "cut",
+ "ctrl C", "copy",
+ "ctrl KP_RIGHT", "selectNextColumnChangeLead",
+ "ctrl KP_LEFT", "selectPreviousColumnChangeLead",
+ "ctrl V", "paste",
+ "ctrl KP_DOWN", "selectNextRowChangeLead",
+ "COPY", "copy",
+ "ctrl KP_UP", "selectPreviousRowChangeLead",
+ "PASTE", "paste",
"shift PAGE_DOWN","scrollDownExtendSelection",
"PAGE_DOWN", "scrollDownChangeSelection",
"END", "selectLastColumn",
@@ -896,25 +963,26 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"ctrl SLASH", "selectAll",
"ctrl shift KP_DOWN", "selectNextRowExtendSelection",
}),
- "Table.background", new ColorUIResource(light),
- "Table.focusCellBackground", new ColorUIResource(light),
- "Table.focusCellForeground", new ColorUIResource(darkShadow),
+ "Table.background", new ColorUIResource(new ColorUIResource(255, 255, 255)),
+ "Table.focusCellBackground", new ColorUIResource(new ColorUIResource(255, 255, 255)),
+ "Table.focusCellForeground", new ColorUIResource(new ColorUIResource(0, 0, 0)),
"Table.focusCellHighlightBorder",
new BorderUIResource.LineBorderUIResource(
new ColorUIResource(255, 255, 0)),
"Table.font", new FontUIResource("Dialog", Font.PLAIN, 12),
- "Table.foreground", new ColorUIResource(darkShadow),
- "Table.gridColor", new ColorUIResource(Color.gray),
+ "Table.foreground", new ColorUIResource(new ColorUIResource(0, 0, 0)),
+ "Table.gridColor", new ColorUIResource(new ColorUIResource(128, 128, 128)),
"Table.scrollPaneBorder", new BorderUIResource.BevelBorderUIResource(0),
- "Table.selectionBackground", new ColorUIResource(Color.black),
- "Table.selectionForeground", new ColorUIResource(Color.white),
- "TableHeader.background", new ColorUIResource(light),
+ "Table.selectionBackground", new ColorUIResource(new ColorUIResource(0, 0, 128)),
+ "Table.selectionForeground", new ColorUIResource(new ColorUIResource(255, 255, 255)),
+ "TableHeader.background", new ColorUIResource(new ColorUIResource(192, 192, 192)),
"TableHeader.cellBorder", new BorderUIResource.BevelBorderUIResource(0),
"TableHeader.font", new FontUIResource("Dialog", Font.PLAIN, 12),
- "TableHeader.foreground", new ColorUIResource(darkShadow),
+ "TableHeader.foreground", new ColorUIResource(new ColorUIResource(0, 0, 0)),
"TextArea.background", new ColorUIResource(light),
- "TextArea.border", new BasicBorders.MarginBorder(),
+ "TextArea.border",
+ new BorderUIResource(BasicBorders.getMarginBorder()),
"TextArea.caretBlinkRate", new Integer(500),
"TextArea.caretForeground", new ColorUIResource(Color.black),
"TextArea.font", new FontUIResource("MonoSpaced", Font.PLAIN, 12),
@@ -945,8 +1013,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"TextField.font", new FontUIResource("SansSerif", Font.PLAIN, 12),
"TextField.foreground", new ColorUIResource(Color.black),
"TextField.highlight", new ColorUIResource(highLight),
- "TextField.inactiveBackground", new ColorUIResource(light),
- "TextField.inactiveForeground", new ColorUIResource(Color.gray),
+ "TextField.inactiveBackground", new ColorUIResource(Color.LIGHT_GRAY),
+ "TextField.inactiveForeground", new ColorUIResource(Color.GRAY),
"TextField.light", new ColorUIResource(highLight),
"TextField.highlight", new ColorUIResource(light),
"TextField.keyBindings", new JTextComponent.KeyBinding[] {
@@ -964,7 +1032,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"TextField.selectionBackground", new ColorUIResource(Color.black),
"TextField.selectionForeground", new ColorUIResource(Color.white),
"TextPane.background", new ColorUIResource(Color.white),
- "TextPane.border", new BasicBorders.MarginBorder(),
+ "TextPane.border", BasicBorders.getMarginBorder(),
"TextPane.caretBlinkRate", new Integer(500),
"TextPane.caretForeground", new ColorUIResource(Color.black),
"TextPane.font", new FontUIResource("Serif", Font.PLAIN, 12),
@@ -1036,7 +1104,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"Tree.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] {
"ESCAPE", "cancel"
}),
- "Tree.background", new ColorUIResource(light),
+ "Tree.background", new ColorUIResource(new Color(255, 255, 255)),
"Tree.changeSelectionWithFocus", Boolean.TRUE,
// "Tree.closedIcon", new IconUIResource(new ImageIcon("icons/TreeClosed.png")),
// "Tree.collapsedIcon", new IconUIResource(new ImageIcon("icons/TreeCollapsed.png")),
@@ -1086,20 +1154,20 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"PAGE_UP", "scrollUpChangeSelection",
"ctrl PAGE_DOWN", "scrollDownChangeLead"
}),
- "Tree.font", new FontUIResource(new Font("Helvetica", Font.PLAIN, 12)),
+ "Tree.font", new FontUIResource("Dialog", Font.PLAIN, 12),
"Tree.foreground", new ColorUIResource(Color.black),
"Tree.hash", new ColorUIResource(new Color(128, 128, 128)),
"Tree.leftChildIndent", new Integer(7),
"Tree.rightChildIndent", new Integer(13),
- "Tree.rowHeight", new Integer(20), // FIXME
+ "Tree.rowHeight", new Integer(16),
"Tree.scrollsOnExpand", Boolean.TRUE,
"Tree.selectionBackground", new ColorUIResource(Color.black),
- "Tree.nonSelectionBackground", new ColorUIResource(new Color(239, 235, 231)),
+ "Tree.nonSelectionBackground", new ColorUIResource(new Color(255, 255, 255)),
"Tree.selectionBorderColor", new ColorUIResource(Color.black),
"Tree.selectionBorder", new BorderUIResource.LineBorderUIResource(Color.black),
"Tree.selectionForeground", new ColorUIResource(new Color(255, 255, 255)),
- "Tree.textBackground", new ColorUIResource(new Color(255, 255, 255)),
- "Tree.textForeground", new ColorUIResource(Color.black),
+ "Tree.textBackground", new ColorUIResource(new Color(192, 192, 192)),
+ "Tree.textForeground", new ColorUIResource(new Color(0, 0, 0)),
"Viewport.background", new ColorUIResource(light),
"Viewport.foreground", new ColorUIResource(Color.black),
"Viewport.font", new FontUIResource("Dialog", Font.PLAIN, 12)
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java
index 95f6b84fb7c..daa9b0d6b63 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java
@@ -41,16 +41,19 @@ package javax.swing.plaf.basic;
import java.awt.Dimension;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
+import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
+import javax.swing.JMenu;
import javax.swing.JMenuBar;
-import javax.swing.UIDefaults;
-import javax.swing.UIManager;
+import javax.swing.LookAndFeel;
+import javax.swing.MenuElement;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
+import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.MenuBarUI;
@@ -63,12 +66,15 @@ public class BasicMenuBarUI extends MenuBarUI
/*ContainerListener that listens to the ContainerEvents fired from menu bar*/
protected ContainerListener containerListener;
-
+
/*Property change listeners that listener to PropertyChangeEvent from menu bar*/
protected PropertyChangeListener propertyChangeListener;
/* menu bar for which this UI delegate is for*/
protected JMenuBar menuBar;
+
+ /* MouseListener that listens to the mouseEvents fired from menu bar*/
+ private MouseInputListener mouseListener;
/**
* Creates a new BasicMenuBarUI object.
@@ -78,6 +84,7 @@ public class BasicMenuBarUI extends MenuBarUI
changeListener = createChangeListener();
containerListener = createContainerListener();
propertyChangeListener = new PropertyChangeHandler();
+ mouseListener = new MouseInputHandler();
}
/**
@@ -159,12 +166,9 @@ public class BasicMenuBarUI extends MenuBarUI
*/
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"));
+ LookAndFeel.installBorder(menuBar, "MenuBar.border");
+ LookAndFeel.installColorsAndFont(menuBar, "MenuBar.background",
+ "MenuBar.foreground", "MenuBar.font");
menuBar.setOpaque(true);
}
@@ -183,6 +187,7 @@ public class BasicMenuBarUI extends MenuBarUI
{
menuBar.addContainerListener(containerListener);
menuBar.addPropertyChangeListener(propertyChangeListener);
+ menuBar.addMouseListener(mouseListener);
}
/**
@@ -229,6 +234,7 @@ public class BasicMenuBarUI extends MenuBarUI
{
menuBar.removeContainerListener(containerListener);
menuBar.removePropertyChangeListener(propertyChangeListener);
+ menuBar.removeMouseListener(mouseListener);
}
/**
@@ -250,6 +256,7 @@ public class BasicMenuBarUI extends MenuBarUI
{
public void stateChanged(ChangeEvent event)
{
+ // TODO: What should be done here, if anything?
}
}
@@ -301,4 +308,84 @@ public class BasicMenuBarUI extends MenuBarUI
menuBar.repaint();
}
}
+
+ private class MouseInputHandler implements MouseInputListener
+ {
+ /**
+ * Handles mouse clicked event
+ *
+ * @param e Mouse event
+ */
+ public void mouseClicked(MouseEvent e)
+ {
+ MenuElement[] me = menuBar.getSubElements();
+
+ for (int i = 0; i < me.length; i++)
+ {
+ JMenu menu = menuBar.getMenu(i);
+ if (menu != null)
+ menu.setSelected(false);
+ }
+ }
+
+ /**
+ * Handles mouse pressed event
+ *
+ * @param e Mouse event
+ */
+ public void mousePressed(MouseEvent e)
+ {
+ // TODO: What should be done here, if anything?
+ }
+
+ /**
+ * Handles mouse released event
+ *
+ * @param e Mouse event
+ */
+ public void mouseReleased(MouseEvent e)
+ {
+ // TODO: What should be done here, if anything?
+ }
+
+ /**
+ * Handles mouse exited event
+ *
+ * @param e Mouse event
+ */
+ public void mouseExited(MouseEvent e)
+ {
+ // TODO: What should be done here, if anything?
+ }
+
+ /**
+ * Handles mouse dragged event
+ *
+ * @param e Mouse event
+ */
+ public void mouseDragged(MouseEvent e)
+ {
+ // TODO: What should be done here, if anything?
+ }
+
+ /**
+ * Handles mouse moved event
+ *
+ * @param e Mouse event
+ */
+ public void mouseMoved(MouseEvent e)
+ {
+ // TODO: What should be done here, if anything?
+ }
+
+ /**
+ * Handles mouse entered event
+ *
+ * @param e Mouse event
+ */
+ public void mouseEntered(MouseEvent e)
+ {
+ // TODO: What should be done here, if anything?
+ }
+ }
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java
index 8aa1193bcc4..2a3556a5db9 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java
@@ -7,7 +7,7 @@ GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-
+
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@@ -46,18 +46,27 @@ import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
+import javax.swing.AbstractAction;
+import javax.swing.ActionMap;
+import javax.swing.ButtonModel;
import javax.swing.Icon;
+import javax.swing.InputMap;
+import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
+import javax.swing.LookAndFeel;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingConstants;
@@ -69,6 +78,8 @@ import javax.swing.event.MenuDragMouseListener;
import javax.swing.event.MenuKeyEvent;
import javax.swing.event.MenuKeyListener;
import javax.swing.event.MouseInputListener;
+import javax.swing.plaf.ActionMapUIResource;
+import javax.swing.plaf.ComponentInputMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.MenuItemUI;
@@ -109,7 +120,7 @@ public class BasicMenuItemUI extends MenuItemUI
* Number of spaces between icon and text.
*/
protected int defaultTextIconGap = 4;
-
+
/**
* Color of the text when menu item is disabled
*/
@@ -156,16 +167,69 @@ public class BasicMenuItemUI extends MenuItemUI
private String acceleratorDelimiter;
/**
- * PropertyChangeListener to listen for property changes in the menu item
+ * ItemListener to listen for item changes in the menu item
*/
- private PropertyChangeListener propertyChangeListener;
+ private ItemListener itemListener;
/**
* Number of spaces between accelerator and menu item's label.
*/
- private int defaultAcceleratorLabelGap = 4;
+ private int defaultAcceleratorLabelGap = 10;
/**
+ * The gap between different menus on the MenuBar.
+ */
+ private int MenuGap = 10;
+
+ /** A PropertyChangeListener to make UI updates after property changes **/
+ PropertyChangeHandler propertyChangeListener;
+
+ /**
+ * A class to handle PropertChangeEvents for the JMenuItem
+ * @author Anthony Balkissoon abalkiss at redhat dot com.
+ */
+ class PropertyChangeHandler implements PropertyChangeListener
+ {
+ /**
+ * This method is called when a property of the menuItem is changed.
+ * Currently it is only used to update the accelerator key bindings.
+ *
+ * @param e
+ * the PropertyChangeEvent
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName() == "accelerator")
+ {
+ InputMap map = SwingUtilities.getUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW);
+ if (map != null)
+ map.remove((KeyStroke)e.getOldValue());
+ else
+ map = new ComponentInputMapUIResource(menuItem);
+ map.put((KeyStroke)e.getNewValue(), "doClick");
+ }
+ }
+ }
+
+ /**
+ * A class to handle accelerator keys. This is the Action we will
+ * perform when the accelerator key for this JMenuItem is pressed.
+ * @author Anthony Balkissoon abalkiss at redhat dot com
+ *
+ */
+ class ClickAction extends AbstractAction
+ {
+ /**
+ * This is what is done when the accelerator key for the JMenuItem is
+ * pressed.
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ doClick(MenuSelectionManager.defaultManager());
+ }
+ }
+
+ /**
* Creates a new BasicMenuItemUI object.
*/
public BasicMenuItemUI()
@@ -173,14 +237,15 @@ public class BasicMenuItemUI extends MenuItemUI
mouseInputListener = createMouseInputListener(menuItem);
menuDragMouseListener = createMenuDragMouseListener(menuItem);
menuKeyListener = createMenuKeyListener(menuItem);
+ itemListener = new ItemHandler();
propertyChangeListener = new PropertyChangeHandler();
}
/**
* Create MenuDragMouseListener to listen for mouse dragged events.
- *
- * @param c menu item to listen to
- *
+ *
+ * @param c
+ * menu item to listen to
* @return The MenuDragMouseListener
*/
protected MenuDragMouseListener createMenuDragMouseListener(JComponent c)
@@ -189,11 +254,11 @@ public class BasicMenuItemUI extends MenuItemUI
}
/**
- * Creates MenuKeyListener to listen to key events occuring when menu item
- * is visible on the screen.
- *
- * @param c menu item to listen to
- *
+ * Creates MenuKeyListener to listen to key events occuring when menu item is
+ * visible on the screen.
+ *
+ * @param c
+ * menu item to listen to
* @return The MenuKeyListener
*/
protected MenuKeyListener createMenuKeyListener(JComponent c)
@@ -203,9 +268,9 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Handles mouse input events occuring for this menu item
- *
- * @param c menu item to listen to
- *
+ *
+ * @param c
+ * menu item to listen to
* @return The MouseInputListener
*/
protected MouseInputListener createMouseInputListener(JComponent c)
@@ -216,9 +281,9 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Factory method to create a BasicMenuItemUI for the given {@link
* JComponent}, which should be a {@link JMenuItem}.
- *
- * @param c The {@link JComponent} a UI is being created for.
- *
+ *
+ * @param c
+ * The {@link JComponent} a UI is being created for.
* @return A BasicMenuItemUI for the {@link JComponent}.
*/
public static ComponentUI createUI(JComponent c)
@@ -228,8 +293,9 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Programatically clicks menu item.
- *
- * @param msm MenuSelectionManager for the menu hierarchy
+ *
+ * @param msm
+ * MenuSelectionManager for the menu hierarchy
*/
protected void doClick(MenuSelectionManager msm)
{
@@ -239,9 +305,9 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Returns maximum size for the specified menu item
- *
- * @param c component for which to get maximum size
- *
+ *
+ * @param c
+ * component for which to get maximum size
* @return Maximum size for the specified menu item.
*/
public Dimension getMaximumSize(JComponent c)
@@ -251,9 +317,9 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Returns minimum size for the specified menu item
- *
- * @param c component for which to get minimum size
- *
+ *
+ * @param c
+ * component for which to get minimum size
* @return Minimum size for the specified menu item.
*/
public Dimension getMinimumSize(JComponent c)
@@ -263,9 +329,9 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Returns path to this menu item.
- *
- * @return $MenuElement[]$ Returns array of menu elements
- * that constitute a path to this menu item.
+ *
+ * @return $MenuElement[]$ Returns array of menu elements that constitute a
+ * path to this menu item.
*/
public MenuElement[] getPath()
{
@@ -278,12 +344,12 @@ public class BasicMenuItemUI extends MenuItemUI
Component c = menuItem;
while (c instanceof MenuElement)
{
- path.add(0, (MenuElement) c);
+ path.add(0, (MenuElement) c);
- if (c instanceof JPopupMenu)
- c = ((JPopupMenu) c).getInvoker();
- else
- c = c.getParent();
+ if (c instanceof JPopupMenu)
+ c = ((JPopupMenu) c).getInvoker();
+ else
+ c = c.getParent();
}
MenuElement[] pathArray = new MenuElement[path.size()];
@@ -293,12 +359,15 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Returns preferred size for the given menu item.
- *
- * @param c menu item for which to get preferred size
- * @param checkIcon check icon displayed in the given menu item
- * @param arrowIcon arrow icon displayed in the given menu item
- * @param defaultTextIconGap space between icon and text in the given menuItem
- *
+ *
+ * @param c
+ * menu item for which to get preferred size
+ * @param checkIcon
+ * check icon displayed in the given menu item
+ * @param arrowIcon
+ * arrow icon displayed in the given menu item
+ * @param defaultTextIconGap
+ * space between icon and text in the given menuItem
* @return $Dimension$ preferred size for the given menu item
*/
protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon,
@@ -308,7 +377,7 @@ public class BasicMenuItemUI extends MenuItemUI
JMenuItem m = (JMenuItem) c;
Dimension d = BasicGraphicsUtils.getPreferredButtonSize(m,
defaultTextIconGap);
-
+
// if menu item has accelerator then take accelerator's size into account
// when calculating preferred size.
KeyStroke accelerator = m.getAccelerator();
@@ -316,52 +385,57 @@ public class BasicMenuItemUI extends MenuItemUI
if (accelerator != null)
{
- rect = getAcceleratorRect(accelerator,
- m.getToolkit().getFontMetrics(acceleratorFont));
+ rect = getAcceleratorRect(
+ accelerator,
+ m.getToolkit().getFontMetrics(acceleratorFont));
- // add width of accelerator's text
- d.width = d.width + rect.width + defaultAcceleratorLabelGap;
+ // add width of accelerator's text
+ d.width += rect.width + defaultAcceleratorLabelGap;
- // adjust the heigth of the preferred size if necessary
- if (d.height < rect.height)
- d.height = rect.height;
+ // 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;
+ d.width += checkIcon.getIconWidth() + defaultTextIconGap;
- if (checkIcon.getIconHeight() > d.height)
- d.height = checkIcon.getIconHeight();
+ 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();
+ int pWidth = m.getParent().getWidth();
+ if (!((JMenu)c).isTopLevelMenu() && d.width < pWidth)
+ d.width = pWidth
+ - m.getInsets().left - m.getInsets().right;
+ else
+ d.width += arrowIcon.getIconWidth() + MenuGap;
+
+ if (arrowIcon.getIconHeight() > d.height)
+ d.height = arrowIcon.getIconHeight();
}
-
+
return d;
}
/**
* Returns preferred size of the given component
- *
- * @param c component for which to return preferred size
- *
+ *
+ * @param c
+ * component for which to return preferred size
* @return $Dimension$ preferred size for the given component
*/
public Dimension getPreferredSize(JComponent c)
{
- return getPreferredMenuItemSize(c, checkIcon, arrowIcon,
- defaultTextIconGap);
+ return getPreferredMenuItemSize(c, checkIcon, arrowIcon, defaultTextIconGap);
}
/**
* Returns the prefix for entries in the {@link UIDefaults} table.
- *
+ *
* @return "MenuItem"
*/
protected String getPropertyPrefix()
@@ -371,8 +445,9 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* This method installs the components for this {@link JMenuItem}.
- *
- * @param menuItem The {@link JMenuItem} to install components for.
+ *
+ * @param menuItem
+ * The {@link JMenuItem} to install components for.
*/
protected void installComponents(JMenuItem menuItem)
{
@@ -380,28 +455,27 @@ public class BasicMenuItemUI extends MenuItemUI
}
/**
- * This method installs the defaults that are defined in the Basic look and
+ * This method installs the defaults that are defined in the Basic look and
* feel for this {@link JMenuItem}.
*/
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- menuItem.setBackground(defaults.getColor("MenuItem.background"));
- menuItem.setBorder(defaults.getBorder("MenuItem.border"));
- 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");
- selectionBackground = defaults.getColor("MenuItem.selectionBackground");
- selectionForeground = defaults.getColor("MenuItem.selectionForeground");
- acceleratorDelimiter = defaults.getString("MenuItem.acceleratorDelimiter");
-
+ String prefix = getPropertyPrefix();
+ LookAndFeel.installBorder(menuItem, prefix + ".border");
+ LookAndFeel.installColorsAndFont(menuItem, prefix + ".background",
+ prefix + ".foreground", prefix + ".font");
+ menuItem.setMargin(UIManager.getInsets(prefix + ".margin"));
+ acceleratorFont = UIManager.getFont(prefix + ".acceleratorFont");
+ acceleratorForeground = UIManager.getColor(prefix + ".acceleratorForeground");
+ acceleratorSelectionForeground = UIManager.getColor(prefix + ".acceleratorSelectionForeground");
+ selectionBackground = UIManager.getColor(prefix + ".selectionBackground");
+ selectionForeground = UIManager.getColor(prefix + ".selectionForeground");
+ acceleratorDelimiter = UIManager.getString(prefix + ".acceleratorDelimiter");
+ checkIcon = UIManager.getIcon(prefix + ".checkIcon");
+
menuItem.setHorizontalTextPosition(SwingConstants.TRAILING);
menuItem.setHorizontalAlignment(SwingConstants.LEADING);
+ menuItem.setOpaque(true);
}
/**
@@ -409,7 +483,17 @@ public class BasicMenuItemUI extends MenuItemUI
*/
protected void installKeyboardActions()
{
- // FIXME: Need to implement
+ InputMap focusedWindowMap = SwingUtilities.getUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW);
+ if (focusedWindowMap == null)
+ focusedWindowMap = new ComponentInputMapUIResource(menuItem);
+ focusedWindowMap.put(menuItem.getAccelerator(), "doClick");
+ SwingUtilities.replaceUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW, focusedWindowMap);
+
+ ActionMap UIActionMap = SwingUtilities.getUIActionMap(menuItem);
+ if (UIActionMap == null)
+ UIActionMap = new ActionMapUIResource();
+ UIActionMap.put("doClick", new ClickAction());
+ SwingUtilities.replaceUIActionMap(menuItem, UIActionMap);
}
/**
@@ -421,15 +505,17 @@ public class BasicMenuItemUI extends MenuItemUI
menuItem.addMouseMotionListener(mouseInputListener);
menuItem.addMenuDragMouseListener(menuDragMouseListener);
menuItem.addMenuKeyListener(menuKeyListener);
+ menuItem.addItemListener(itemListener);
menuItem.addPropertyChangeListener(propertyChangeListener);
}
/**
- * Installs and initializes all fields for this UI delegate. Any properties
- * of the UI that need to be initialized and/or set to defaults will be
- * done now. It will also install any listeners necessary.
- *
- * @param c The {@link JComponent} that is having this UI installed.
+ * Installs and initializes all fields for this UI delegate. Any properties of
+ * the UI that need to be initialized and/or set to defaults will be done now.
+ * It will also install any listeners necessary.
+ *
+ * @param c
+ * The {@link JComponent} that is having this UI installed.
*/
public void installUI(JComponent c)
{
@@ -438,13 +524,16 @@ public class BasicMenuItemUI extends MenuItemUI
installDefaults();
installComponents(menuItem);
installListeners();
+ installKeyboardActions();
}
/**
* Paints given menu item using specified graphics context
- *
- * @param g The graphics context used to paint this menu item
- * @param c Menu Item to paint
+ *
+ * @param g
+ * The graphics context used to paint this menu item
+ * @param c
+ * Menu Item to paint
*/
public void paint(Graphics g, JComponent c)
{
@@ -454,10 +543,13 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Paints background of the menu item
- *
- * @param g The graphics context used to paint this menu item
- * @param menuItem menu item to paint
- * @param bgColor Background color to use when painting menu item
+ *
+ * @param g
+ * The graphics context used to paint this menu item
+ * @param menuItem
+ * menu item to paint
+ * @param bgColor
+ * Background color to use when painting menu item
*/
protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor)
{
@@ -470,15 +562,21 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Paints specified menu item
- *
- * @param g The graphics context used to paint this menu item
- * @param c menu item to paint
- * @param checkIcon check icon to use when painting menu item
- * @param arrowIcon arrow icon to use when painting menu item
- * @param background Background color of the menu item
- * @param foreground Foreground color of the menu item
- * @param defaultTextIconGap space to use between icon and
- * text when painting menu item
+ *
+ * @param g
+ * The graphics context used to paint this menu item
+ * @param c
+ * menu item to paint
+ * @param checkIcon
+ * check icon to use when painting menu item
+ * @param arrowIcon
+ * arrow icon to use when painting menu item
+ * @param background
+ * Background color of the menu item
+ * @param foreground
+ * Foreground color of the menu item
+ * @param defaultTextIconGap
+ * space to use between icon and text when painting menu item
*/
protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon,
Icon arrowIcon, Color background,
@@ -496,7 +594,7 @@ public class BasicMenuItemUI extends MenuItemUI
int horAlign = m.getHorizontalAlignment();
int vertTextPos = m.getVerticalTextPosition();
int horTextPos = m.getHorizontalTextPosition();
-
+
Font f = m.getFont();
g.setFont(f);
FontMetrics fm = g.getFontMetrics(f);
@@ -504,8 +602,10 @@ public class BasicMenuItemUI extends MenuItemUI
SwingUtilities.calculateInsetArea(br, m.getInsets(), vr);
paintBackground(g, m, m.getBackground());
- /* MenuItems insets are equal to menuItems margin, space between text and
- menuItems border. We need to paint insets region as well. */
+ /*
+ * MenuItems insets are equal to menuItems margin, space between text and
+ * menuItems border. We need to paint insets region as well.
+ */
Insets insets = m.getInsets();
br.x -= insets.left;
br.y -= insets.top;
@@ -514,89 +614,93 @@ public class BasicMenuItemUI extends MenuItemUI
// Menu item is considered to be highlighted when it is selected.
// But we don't want to paint the background of JCheckBoxMenuItems
- if ((m.isSelected() && checkIcon == null) || m.getModel().isArmed() &&
- (m.getParent() instanceof MenuElement))
+ ButtonModel mod = m.getModel();
+ if ((m.isSelected() && checkIcon == null) || (mod != null &&
+ mod.isArmed())
+ && (m.getParent() instanceof MenuElement))
{
- if (m.isContentAreaFilled())
- {
- g.setColor(selectionBackground);
- g.fillRect(br.x, br.y, br.width, br.height);
- }
+ if (m.isContentAreaFilled())
+ {
+ g.setColor(selectionBackground);
+ g.fillRect(br.x, br.y, br.width, br.height);
+ }
}
else
{
- if (m.isContentAreaFilled())
- {
- g.setColor(m.getBackground());
- g.fillRect(br.x, br.y, br.width, br.height);
- }
+ if (m.isContentAreaFilled())
+ {
+ g.setColor(m.getBackground());
+ g.fillRect(br.x, br.y, br.width, br.height);
+ }
}
// If this menu item is a JCheckBoxMenuItem then paint check icon
if (checkIcon != null)
{
- SwingUtilities.layoutCompoundLabel(m, fm, null, checkIcon, vertAlign,
- horAlign, vertTextPos, horTextPos,
- vr, cr, tr, defaultTextIconGap);
+ SwingUtilities.layoutCompoundLabel(m, fm, null, checkIcon, vertAlign,
+ horAlign, vertTextPos, horTextPos,
+ vr, cr, tr, defaultTextIconGap);
checkIcon.paintIcon(m, 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.
- // So we need to adjust view rectangle s.t. its starting point is at
- // checkIcon.width + defaultTextIconGap.
- vr.x = cr.x + cr.width + defaultTextIconGap;
+ // 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;
}
// if this is a submenu, then paint arrow icon to indicate it.
if (arrowIcon != null && (c instanceof JMenu))
{
- if (! ((JMenu) c).isTopLevelMenu())
- {
- int width = arrowIcon.getIconWidth();
- int height = arrowIcon.getIconHeight();
-
- arrowIcon.paintIcon(m, g, vr.width - width + defaultTextIconGap,
- vr.y + 2);
- }
+ if (!((JMenu) c).isTopLevelMenu())
+ {
+ int width = arrowIcon.getIconWidth();
+ int height = arrowIcon.getIconHeight();
+ int offset = (vr.height - height) / 2;
+ arrowIcon.paintIcon(m, g, vr.width - width, vr.y + offset);
+ }
}
- // paint text and user menu icon if it exists
+ // paint text and user menu icon if it exists
Icon i = m.getIcon();
- SwingUtilities.layoutCompoundLabel(c, fm, m.getText(), i,
- vertAlign, horAlign, vertTextPos,
- horTextPos, vr, ir, tr,
- defaultTextIconGap);
+ SwingUtilities.layoutCompoundLabel(c, fm, m.getText(), i, vertAlign,
+ horAlign, vertTextPos, horTextPos, vr,
+ ir, tr, defaultTextIconGap);
if (i != null)
i.paintIcon(c, g, ir.x, ir.y);
paintText(g, m, tr, m.getText());
- // paint accelerator
+ // paint accelerator
String acceleratorText = "";
if (m.getAccelerator() != null)
{
- acceleratorText = getAcceleratorText(m.getAccelerator());
- fm = g.getFontMetrics(acceleratorFont);
- ar.width = fm.stringWidth(acceleratorText);
- ar.x = br.width - ar.width;
- vr.x = br.width - ar.width;
-
- SwingUtilities.layoutCompoundLabel(m, fm, acceleratorText, null,
- vertAlign, horAlign, vertTextPos,
- horTextPos, vr, ir, ar,
- defaultTextIconGap);
-
- paintAccelerator(g, m, ar, acceleratorText);
+ acceleratorText = getAcceleratorText(m.getAccelerator());
+ fm = g.getFontMetrics(acceleratorFont);
+ ar.width = fm.stringWidth(acceleratorText);
+ ar.x = br.width - ar.width;
+ vr.x = br.width - ar.width - defaultTextIconGap;
+
+ SwingUtilities.layoutCompoundLabel(m, fm, acceleratorText, null,
+ vertAlign, horAlign, vertTextPos,
+ horTextPos, vr, ir, ar,
+ defaultTextIconGap);
+
+ paintAccelerator(g, m, ar, acceleratorText);
}
}
/**
* Paints label for the given menu item
- *
- * @param g The graphics context used to paint this menu item
- * @param menuItem menu item for which to draw its label
- * @param textRect rectangle specifiying position of the text relative to
- * the given menu item
- * @param text label of the menu item
+ *
+ * @param g
+ * The graphics context used to paint this menu item
+ * @param menuItem
+ * menu item for which to draw its label
+ * @param textRect
+ * rectangle specifiying position of the text relative to the given
+ * menu item
+ * @param text
+ * label of the menu item
*/
protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect,
String text)
@@ -605,43 +709,46 @@ public class BasicMenuItemUI extends MenuItemUI
g.setFont(f);
FontMetrics fm = g.getFontMetrics(f);
- if (text != null && ! text.equals(""))
+ if (text != null && !text.equals(""))
{
- if (menuItem.isEnabled())
+ if (menuItem.isEnabled())
{
// Menu item is considered to be highlighted when it is selected.
// But not if it's a JCheckBoxMenuItem
- if ((menuItem.isSelected() && checkIcon == null) || menuItem.getModel().isArmed() &&
- (menuItem.getParent() instanceof MenuElement))
+ ButtonModel mod = menuItem.getModel();
+ if ((menuItem.isSelected() && checkIcon == null)
+ || (mod != null && mod.isArmed())
+ && (menuItem.getParent() instanceof MenuElement))
g.setColor(selectionForeground);
else
g.setColor(menuItem.getForeground());
}
- else
- // FIXME: should fix this to use 'disabledForeground', but its
- // default value in BasicLookAndFeel is null.
-
+ else
+ // FIXME: should fix this to use 'disabledForeground', but its
+ // default value in BasicLookAndFeel is null.
+
// FIXME: should there be different foreground colours for selected
// or deselected, when disabled?
g.setColor(Color.gray);
- int mnemonicIndex = menuItem.getDisplayedMnemonicIndex();
+ int mnemonicIndex = menuItem.getDisplayedMnemonicIndex();
- if (mnemonicIndex != -1)
- BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex,
- textRect.x,
- textRect.y
- + fm.getAscent());
- else
- BasicGraphicsUtils.drawString(g, text, 0, textRect.x,
- textRect.y + fm.getAscent());
+ if (mnemonicIndex != -1)
+ BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex,
+ textRect.x,
+ textRect.y
+ + fm.getAscent());
+ else
+ BasicGraphicsUtils.drawString(g, text, 0, textRect.x,
+ textRect.y + fm.getAscent());
}
}
/**
* This method uninstalls the components for this {@link JMenuItem}.
- *
- * @param menuItem The {@link JMenuItem} to uninstall components for.
+ *
+ * @param menuItem
+ * The {@link JMenuItem} to uninstall components for.
*/
protected void uninstallComponents(JMenuItem menuItem)
{
@@ -676,8 +783,9 @@ public class BasicMenuItemUI extends MenuItemUI
* Uninstalls any keyboard actions.
*/
protected void uninstallKeyboardActions()
- {
- // FIXME: need to implement
+ {
+ SwingUtilities.replaceUIInputMap(menuItem,
+ JComponent.WHEN_IN_FOCUSED_WINDOW, null);
}
/**
@@ -688,15 +796,17 @@ public class BasicMenuItemUI extends MenuItemUI
menuItem.removeMouseListener(mouseInputListener);
menuItem.removeMenuDragMouseListener(menuDragMouseListener);
menuItem.removeMenuKeyListener(menuKeyListener);
+ menuItem.removeItemListener(itemListener);
menuItem.removePropertyChangeListener(propertyChangeListener);
}
/**
* Performs the opposite of installUI. Any properties or resources that need
- * to be cleaned up will be done now. It will also uninstall any listeners
- * it has. In addition, any properties of this UI will be nulled.
- *
- * @param c The {@link JComponent} that is having this UI uninstalled.
+ * to be cleaned up will be done now. It will also uninstall any listeners it
+ * has. In addition, any properties of this UI will be nulled.
+ *
+ * @param c
+ * The {@link JComponent} that is having this UI uninstalled.
*/
public void uninstallUI(JComponent c)
{
@@ -708,9 +818,11 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* This method calls paint.
- *
- * @param g The graphics context used to paint this menu item
- * @param c The menu item to paint
+ *
+ * @param g
+ * The graphics context used to paint this menu item
+ * @param c
+ * The menu item to paint
*/
public void update(Graphics g, JComponent c)
{
@@ -719,9 +831,9 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Return text representation of the specified accelerator
- *
- * @param accelerator Accelerator for which to return string representation
- *
+ *
+ * @param accelerator
+ * Accelerator for which to return string representation
* @return $String$ Text representation of the given accelerator
*/
private String getAcceleratorText(KeyStroke accelerator)
@@ -744,10 +856,11 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Calculates and return rectange in which accelerator should be displayed
- *
- * @param accelerator accelerator for which to return the display rectangle
- * @param fm The font metrics used to measure the text
- *
+ *
+ * @param accelerator
+ * accelerator for which to return the display rectangle
+ * @param fm
+ * The font metrics used to measure the text
* @return $Rectangle$ reactangle which will be used to display accelerator
*/
private Rectangle getAcceleratorRect(KeyStroke accelerator, FontMetrics fm)
@@ -759,12 +872,16 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* Paints accelerator inside menu item
- *
- * @param g The graphics context used to paint the border
- * @param menuItem Menu item for which to draw accelerator
- * @param acceleratorRect rectangle representing position
- * of the accelerator relative to the menu item
- * @param acceleratorText accelerator's text
+ *
+ * @param g
+ * The graphics context used to paint the border
+ * @param menuItem
+ * Menu item for which to draw accelerator
+ * @param acceleratorRect
+ * rectangle representing position of the accelerator relative to the
+ * menu item
+ * @param acceleratorText
+ * accelerator's text
*/
private void paintAccelerator(Graphics g, JMenuItem menuItem,
Rectangle acceleratorRect,
@@ -785,10 +902,9 @@ public class BasicMenuItemUI extends MenuItemUI
}
/**
- * This class handles mouse events occuring inside the menu item.
- * Most of the events are forwarded for processing to MenuSelectionManager
- * of the current menu hierarchy.
- *
+ * This class handles mouse events occuring inside the menu item. Most of the
+ * events are forwarded for processing to MenuSelectionManager of the current
+ * menu hierarchy.
*/
protected class MouseInputHandler implements MouseInputListener
{
@@ -797,13 +913,15 @@ public class BasicMenuItemUI extends MenuItemUI
*/
protected MouseInputHandler()
{
+ // Nothing to do here.
}
/**
- * This method is called when mouse is clicked on the menu item.
- * It forwards this event to MenuSelectionManager.
- *
- * @param e A {@link MouseEvent}.
+ * This method is called when mouse is clicked on the menu item. It forwards
+ * this event to MenuSelectionManager.
+ *
+ * @param e
+ * A {@link MouseEvent}.
*/
public void mouseClicked(MouseEvent e)
{
@@ -812,10 +930,11 @@ public class BasicMenuItemUI extends MenuItemUI
}
/**
- * This method is called when mouse is dragged inside the menu item.
- * It forwards this event to MenuSelectionManager.
- *
- * @param e A {@link MouseEvent}.
+ * This method is called when mouse is dragged inside the menu item. It
+ * forwards this event to MenuSelectionManager.
+ *
+ * @param e
+ * A {@link MouseEvent}.
*/
public void mouseDragged(MouseEvent e)
{
@@ -824,29 +943,31 @@ public class BasicMenuItemUI extends MenuItemUI
}
/**
- * This method is called when mouse enters menu item.
- * When this happens menu item is considered to be selected and selection path
- * in MenuSelectionManager is set. This event is also forwarded to MenuSelection
- * Manager for further processing.
- *
- * @param e A {@link MouseEvent}.
+ * This method is called when mouse enters menu item. When this happens menu
+ * item is considered to be selected and selection path in
+ * MenuSelectionManager is set. This event is also forwarded to
+ * MenuSelection Manager for further processing.
+ *
+ * @param e
+ * A {@link MouseEvent}.
*/
public void mouseEntered(MouseEvent e)
{
Component source = (Component) e.getSource();
if (source.getParent() instanceof MenuElement)
{
- MenuSelectionManager manager = MenuSelectionManager.defaultManager();
- manager.setSelectedPath(getPath());
- manager.processMouseEvent(e);
+ MenuSelectionManager manager = MenuSelectionManager.defaultManager();
+ manager.setSelectedPath(getPath());
+ manager.processMouseEvent(e);
}
}
/**
- * This method is called when mouse exits menu item. The event is
- * forwarded to MenuSelectionManager for processing.
- *
- * @param e A {@link MouseEvent}.
+ * This method is called when mouse exits menu item. The event is forwarded
+ * to MenuSelectionManager for processing.
+ *
+ * @param e
+ * A {@link MouseEvent}.
*/
public void mouseExited(MouseEvent e)
{
@@ -855,10 +976,11 @@ public class BasicMenuItemUI extends MenuItemUI
}
/**
- * This method is called when mouse is inside the menu item.
- * This event is forwarder to MenuSelectionManager for further processing.
- *
- * @param e A {@link MouseEvent}.
+ * This method is called when mouse is inside the menu item. This event is
+ * forwarder to MenuSelectionManager for further processing.
+ *
+ * @param e
+ * A {@link MouseEvent}.
*/
public void mouseMoved(MouseEvent e)
{
@@ -869,8 +991,9 @@ public class BasicMenuItemUI extends MenuItemUI
/**
* This method is called when mouse is pressed. This event is forwarded to
* MenuSelectionManager for further processing.
- *
- * @param e A {@link MouseEvent}.
+ *
+ * @param e
+ * A {@link MouseEvent}.
*/
public void mousePressed(MouseEvent e)
{
@@ -882,8 +1005,9 @@ public class BasicMenuItemUI extends MenuItemUI
* This method is called when mouse is released. If the mouse is released
* inside this menuItem, then this menu item is considered to be chosen and
* the menu hierarchy should be closed.
- *
- * @param e A {@link MouseEvent}.
+ *
+ * @param e
+ * A {@link MouseEvent}.
*/
public void mouseReleased(MouseEvent e)
{
@@ -892,24 +1016,25 @@ public class BasicMenuItemUI extends MenuItemUI
if (e.getX() > 0 && e.getX() < size.width && e.getY() > 0
&& e.getY() < size.height)
{
- manager.clearSelectedPath();
- menuItem.doClick();
+ manager.clearSelectedPath();
+ menuItem.doClick();
}
else
- manager.processMouseEvent(e);
+ manager.processMouseEvent(e);
}
}
/**
* This class handles mouse dragged events.
*/
- protected class MenuDragMouseHandler implements MenuDragMouseListener
+ private class MenuDragMouseHandler implements MenuDragMouseListener
{
/**
* Tbis method is invoked when mouse is dragged over the menu item.
- *
- * @param e The MenuDragMouseEvent
+ *
+ * @param e
+ * The MenuDragMouseEvent
*/
public void menuDragMouseDragged(MenuDragMouseEvent e)
{
@@ -918,10 +1043,11 @@ public class BasicMenuItemUI extends MenuItemUI
}
/**
- * Tbis method is invoked when mouse enters the menu item while it is
- * being dragged.
- *
- * @param e The MenuDragMouseEvent
+ * Tbis method is invoked when mouse enters the menu item while it is being
+ * dragged.
+ *
+ * @param e
+ * The MenuDragMouseEvent
*/
public void menuDragMouseEntered(MenuDragMouseEvent e)
{
@@ -930,27 +1056,29 @@ public class BasicMenuItemUI extends MenuItemUI
}
/**
- * Tbis method is invoked when mouse exits the menu item while
- * it is being dragged
- *
- * @param e The MenuDragMouseEvent
+ * Tbis method is invoked when mouse exits the menu item while it is being
+ * dragged
+ *
+ * @param e the MenuDragMouseEvent
*/
public void menuDragMouseExited(MenuDragMouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
- * Tbis method is invoked when mouse was dragged and released
- * inside the menu item.
- *
- * @param e The MenuDragMouseEvent
+ * Tbis method is invoked when mouse was dragged and released inside the
+ * menu item.
+ *
+ * @param e
+ * The MenuDragMouseEvent
*/
public void menuDragMouseReleased(MenuDragMouseEvent e)
{
MenuElement[] path = e.getPath();
if (path[path.length - 1] instanceof JMenuItem)
- ((JMenuItem) path[path.length - 1]).doClick();
+ ((JMenuItem) path[path.length - 1]).doClick();
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
manager.clearSelectedPath();
@@ -961,50 +1089,63 @@ public class BasicMenuItemUI extends MenuItemUI
* This class handles key events occuring when menu item is visible on the
* screen.
*/
- protected class MenuKeyHandler implements MenuKeyListener
+ private class MenuKeyHandler implements MenuKeyListener
{
/**
* This method is invoked when key has been pressed
- *
- * @param e A {@link MenuKeyEvent}.
+ *
+ * @param e
+ * A {@link MenuKeyEvent}.
*/
public void menuKeyPressed(MenuKeyEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
* This method is invoked when key has been pressed
- *
- * @param e A {@link MenuKeyEvent}.
+ *
+ * @param e
+ * A {@link MenuKeyEvent}.
*/
public void menuKeyReleased(MenuKeyEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
- * This method is invoked when key has been typed
- * It handles the mnemonic key for the menu item.
- *
- * @param e A {@link MenuKeyEvent}.
+ * This method is invoked when key has been typed It handles the mnemonic
+ * key for the menu item.
+ *
+ * @param e
+ * A {@link MenuKeyEvent}.
*/
public void menuKeyTyped(MenuKeyEvent e)
{
+ // TODO: What should be done here, if anything?
}
}
-
+
/**
- * Helper class that listens for changes to the properties of the {@link
+ * Helper class that listens for item changes to the properties of the {@link
* JMenuItem}.
*/
- protected class PropertyChangeHandler implements PropertyChangeListener
+ private class ItemHandler implements ItemListener
{
/**
- * This method is called when one of the menu item's properties change.
+ * This method is called when one of the menu item changes.
*
- * @param evt A {@link PropertyChangeEvent}.
+ * @param evt A {@link ItemEvent}.
*/
- public void propertyChange(PropertyChangeEvent evt)
+ public void itemStateChanged(ItemEvent evt)
{
+ boolean state = false;
+ if (menuItem instanceof JCheckBoxMenuItem)
+ {
+ if (evt.getStateChange() == ItemEvent.SELECTED)
+ state = true;
+ ((JCheckBoxMenuItem) menuItem).setState(state);
+ }
menuItem.revalidate();
menuItem.repaint();
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java
index 30be592ee79..827cbb0f50d 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.swing.plaf.basic;
+import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
@@ -46,8 +47,8 @@ import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
-import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
+import javax.swing.LookAndFeel;
import javax.swing.MenuSelectionManager;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
@@ -92,7 +93,7 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
protected ChangeListener createChangeListener(JComponent c)
{
- return new ChangeHandler();
+ return new ChangeHandler((JMenu) c, this);
}
/**
@@ -180,12 +181,6 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
public Dimension getMaximumSize(JComponent c)
{
- // If this menu is in a popup menu, treat it like a regular JMenuItem
- if (!((JMenu)c).isTopLevelMenu())
- {
- JMenuItem menuItem = new JMenuItem(((JMenu)c).getText(), ((JMenu)c).getIcon());
- return menuItem.getMaximumSize();
- }
return c.getPreferredSize();
}
@@ -205,20 +200,17 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
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");
- selectionBackground = defaults.getColor("Menu.selectionBackground");
- selectionForeground = defaults.getColor("Menu.selectionForeground");
- arrowIcon = defaults.getIcon("Menu.arrowIcon");
- oldBorderPainted = defaults.getBoolean("Menu.borderPainted");
+ LookAndFeel.installBorder(menuItem, "Menu.border");
+ LookAndFeel.installColorsAndFont(menuItem, "Menu.background",
+ "Menu.foreground", "Menu.font");
+ menuItem.setMargin(UIManager.getInsets("Menu.margin"));
+ acceleratorFont = UIManager.getFont("Menu.acceleratorFont");
+ acceleratorForeground = UIManager.getColor("Menu.acceleratorForeground");
+ acceleratorSelectionForeground = UIManager.getColor("Menu.acceleratorSelectionForeground");
+ selectionBackground = UIManager.getColor("Menu.selectionBackground");
+ selectionForeground = UIManager.getColor("Menu.selectionForeground");
+ arrowIcon = UIManager.getIcon("Menu.arrowIcon");
+ oldBorderPainted = UIManager.getBoolean("Menu.borderPainted");
menuItem.setOpaque(true);
}
@@ -245,6 +237,7 @@ public class BasicMenuUI extends BasicMenuItemUI
protected void setupPostTimer(JMenu menu)
{
+ // TODO: Implement this properly.
}
/**
@@ -356,6 +349,7 @@ public class BasicMenuUI extends BasicMenuItemUI
public void mouseMoved(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
public void mousePressed(MouseEvent e)
@@ -421,10 +415,13 @@ public class BasicMenuUI extends BasicMenuItemUI
public void menuDeselected(MenuEvent e)
{
JMenu menu = (JMenu) menuItem;
- if (menu.isTopLevelMenu())
- ((JMenuBar) menu.getParent()).getSelectionModel().clearSelection();
- else
- ((JPopupMenu) menu.getParent()).getSelectionModel().clearSelection();
+ if (menu.getParent() != null)
+ {
+ if (menu.isTopLevelMenu())
+ ((JMenuBar) menu.getParent()).getSelectionModel().clearSelection();
+ else
+ ((JPopupMenu) menu.getParent()).getSelectionModel().clearSelection();
+ }
}
/**
@@ -456,6 +453,7 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
public void propertyChange(PropertyChangeEvent e)
{
+ // TODO: Implement this properly.
}
}
@@ -464,9 +462,40 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
public class ChangeHandler implements ChangeListener
{
+ /**
+ * Not used.
+ */
+ public boolean isSelected;
+
+ /**
+ * Not used.
+ */
+ public JMenu menu;
+
+ /**
+ * Not used.
+ */
+ public BasicMenuUI ui;
+
+ /**
+ * Not used.
+ */
+ public Component wasFocused;
+
+ /**
+ * Not used.
+ */
+ public ChangeHandler(JMenu m, BasicMenuUI ui)
+ {
+ // Not used.
+ }
+
+ /**
+ * Not used.
+ */
public void stateChanged(ChangeEvent e)
{
- // FIXME: It seems that this class is not used anywhere
+ // Not used.
}
}
@@ -506,6 +535,7 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
public void menuDragMouseExited(MenuDragMouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -516,6 +546,7 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
public void menuDragMouseReleased(MenuDragMouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
}
@@ -532,6 +563,7 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
public void menuKeyPressed(MenuKeyEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -541,6 +573,7 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
public void menuKeyReleased(MenuKeyEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -551,6 +584,7 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
public void menuKeyTyped(MenuKeyEvent e)
{
+ // TODO: What should be done here, if anything?
}
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java
index c9f623259ba..6b37d315fa8 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java
@@ -70,8 +70,8 @@ import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
+import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
-import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;
@@ -141,13 +141,14 @@ public class BasicOptionPaneUI extends OptionPaneUI
optionPane);
if (inf != null)
{
- try
- {
- inf.setClosed(true);
- }
- catch (PropertyVetoException pve)
- {
- }
+ try
+ {
+ inf.setClosed(true);
+ }
+ catch (PropertyVetoException pve)
+ {
+ // We do nothing if attempt has been vetoed.
+ }
}
}
}
@@ -405,16 +406,30 @@ public class BasicOptionPaneUI extends OptionPaneUI
|| 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.remove(messageAreaContainer);
+ messageAreaContainer = createMessageArea();
+ optionPane.add(messageAreaContainer);
+ Container newButtons = createButtonArea();
+ optionPane.remove(buttonContainer);
+ optionPane.add(newButtons);
+ buttonContainer = newButtons;
+ optionPane.add(buttonContainer);
}
optionPane.invalidate();
optionPane.repaint();
}
}
+ /**
+ * The minimum width for JOptionPanes.
+ */
+ public static final int MinimumWidth = 262;
+
+ /**
+ * The minimum height for JOptionPanes.
+ */
+ public static final int MinimumHeight = 90;
+
/** Whether the JOptionPane contains custom components. */
protected boolean hasCustomComponents = false;
@@ -433,12 +448,6 @@ public class BasicOptionPaneUI extends OptionPaneUI
/** 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;
@@ -518,6 +527,7 @@ public class BasicOptionPaneUI extends OptionPaneUI
*/
public void paintIcon(Component c, Graphics g, int x, int y)
{
+ // Nothing to do here.
}
}
@@ -637,6 +647,7 @@ public class BasicOptionPaneUI extends OptionPaneUI
*/
public BasicOptionPaneUI()
{
+ // Nothing to do here.
}
/**
@@ -860,10 +871,10 @@ public class BasicOptionPaneUI extends OptionPaneUI
addIcon(messageArea);
JPanel rightSide = new JPanel();
- rightSide.setBorder(BorderFactory.createEmptyBorder(0, 11, 17, 0));
+ rightSide.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
rightSide.setLayout(new GridBagLayout());
GridBagConstraints con = createConstraints();
-
+
addMessageComponents(rightSide, con, getMessage(),
getMaxCharactersPerLineCount(), false);
@@ -886,7 +897,7 @@ public class BasicOptionPaneUI extends OptionPaneUI
}
}
- messageArea.add(rightSide, BorderLayout.EAST);
+ messageArea.add(rightSide, BorderLayout.CENTER);
return messageArea;
}
@@ -944,8 +955,14 @@ public class BasicOptionPaneUI extends OptionPaneUI
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 };
+ case JOptionPane.DEFAULT_OPTION:
+ return (optionPane.getWantsInput() ) ?
+ new Object[] { OK_STRING, CANCEL_STRING } :
+ ( optionPane.getMessageType() == JOptionPane.QUESTION_MESSAGE ) ?
+ new Object[] { YES_STRING, NO_STRING, CANCEL_STRING } :
+ // ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, PLAIN_MESSAGE
+ new Object[] { OK_STRING };
}
return null;
}
@@ -1142,21 +1159,17 @@ public class BasicOptionPaneUI extends OptionPaneUI
*/
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"));
+ LookAndFeel.installColorsAndFont(optionPane, "OptionPane.background",
+ "OptionPane.foreground",
+ "OptionPane.font");
+ LookAndFeel.installBorder(optionPane, "OptionPane.border");
optionPane.setOpaque(true);
- messageBorder = defaults.getBorder("OptionPane.messageAreaBorder");
- messageForeground = defaults.getColor("OptionPane.messageForeground");
- buttonBorder = defaults.getBorder("OptionPane.buttonAreaBorder");
+ messageBorder = UIManager.getBorder("OptionPane.messageAreaBorder");
+ messageForeground = UIManager.getColor("OptionPane.messageForeground");
+ buttonBorder = UIManager.getBorder("OptionPane.buttonAreaBorder");
- minimumSize = defaults.getDimension("OptionPane.minimumSize");
- minimumWidth = minimumSize.width;
- minimumHeight = minimumSize.height;
+ minimumSize = UIManager.getDimension("OptionPane.minimumSize");
// FIXME: Image icons don't seem to work properly right now.
// Once they do, replace the synthetic icons with these ones.
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java
index b715c57b360..783cec473bc 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java
@@ -40,8 +40,7 @@ package javax.swing.plaf.basic;
import javax.swing.JComponent;
import javax.swing.JPanel;
-import javax.swing.UIDefaults;
-import javax.swing.UIManager;
+import javax.swing.LookAndFeel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.PanelUI;
@@ -64,8 +63,29 @@ public class BasicPanelUI extends PanelUI
public void installDefaults(JPanel p)
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- p.setBackground(defaults.getColor("Panel.background"));
+ LookAndFeel.installColorsAndFont(p, "Panel.background", "Panel.foreground",
+ "Panel.font");
p.setOpaque(true);
}
+
+ /**
+ * Uninstalls this UI from the JPanel.
+ *
+ * @param c the JPanel from which to uninstall this UI
+ */
+ public void uninstallUI(JComponent c)
+ {
+ uninstallDefaults((JPanel) c);
+ }
+
+ /**
+ * Uninstalls the UI defaults that have been install through
+ * {@link #installDefaults}.
+ *
+ * @param p the panel from which to uninstall the UI defaults
+ */
+ protected void uninstallDefaults(JPanel p)
+ {
+ // Nothing to do here.
+ }
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java
index 044027b0b4a..76dcfc43559 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package javax.swing.plaf.basic;
import javax.swing.JComponent;
+import javax.swing.UIDefaults;
import javax.swing.plaf.ComponentUI;
import javax.swing.text.Element;
import javax.swing.text.PasswordView;
@@ -48,6 +49,7 @@ public class BasicPasswordFieldUI extends BasicTextFieldUI
{
public BasicPasswordFieldUI()
{
+ // Nothing to do here.
}
public View create(Element elem)
@@ -60,6 +62,11 @@ public class BasicPasswordFieldUI extends BasicTextFieldUI
return new BasicPasswordFieldUI();
}
+ /**
+ * Returns the prefix for entries in the {@link UIDefaults} table.
+ *
+ * @return "PasswordField"
+ */
protected String getPropertyPrefix()
{
return "PasswordField";
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java
index 247117bc983..e15a17bab28 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java
@@ -53,12 +53,11 @@ import javax.swing.JLayeredPane;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
+import javax.swing.LookAndFeel;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
-import javax.swing.UIDefaults;
-import javax.swing.UIManager;
import javax.swing.event.MouseInputListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
@@ -131,12 +130,9 @@ public class BasicPopupMenuUI extends PopupMenuUI
*/
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"));
+ LookAndFeel.installColorsAndFont(popupMenu, "PopupMenu.background",
+ "PopupMenu.foreground", "PopupMenu.font");
+ LookAndFeel.installBorder(popupMenu, "PopupMenu.border");
popupMenu.setOpaque(true);
}
@@ -277,23 +273,26 @@ public class BasicPopupMenuUI extends PopupMenuUI
RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities
.getRoot(invoker);
- ((Container) rootContainer).removeComponentListener(topWindowListener);
-
- // If this popup menu is the last popup menu visible on the screen, then
- // stop interrupting mouse events in the glass pane before hiding this
- // last popup menu.
- boolean topLevelMenu = (popupMenu.getInvoker() instanceof JMenu)
- && ((JMenu) popupMenu.getInvoker())
- .isTopLevelMenu();
-
- if (topLevelMenu || ! (popupMenu.getInvoker() instanceof MenuElement))
+ if (rootContainer != null)
{
- // set glass pane not to interrupt mouse events and remove
- // mouseInputListener
- Container glassPane = (Container) rootContainer.getGlassPane();
- glassPane.setVisible(false);
- glassPane.removeMouseListener(mouseInputListener);
- mouseInputListener = null;
+ ((Container) rootContainer).removeComponentListener(topWindowListener);
+
+ // If this popup menu is the last popup menu visible on the screen,
+ // then
+ // stop interrupting mouse events in the glass pane before hiding this
+ // last popup menu.
+ boolean topLevelMenu = (popupMenu.getInvoker() instanceof JMenu)
+ && ((JMenu) popupMenu.getInvoker()).isTopLevelMenu();
+
+ if (topLevelMenu || !(popupMenu.getInvoker() instanceof MenuElement))
+ {
+ // set glass pane not to interrupt mouse events and remove
+ // mouseInputListener
+ Container glassPane = (Container) rootContainer.getGlassPane();
+ glassPane.setVisible(false);
+ glassPane.removeMouseListener(mouseInputListener);
+ mouseInputListener = null;
+ }
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java
index d00628f53d4..88d949b1caf 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java
@@ -46,21 +46,24 @@ import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
+import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.awt.font.FontRenderContext;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JProgressBar;
+import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
-import javax.swing.UIDefaults;
import javax.swing.UIManager;
+import javax.swing.event.AncestorEvent;
+import javax.swing.event.AncestorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ComponentUI;
@@ -110,14 +113,56 @@ public class BasicProgressBarUI extends ProgressBarUI
{
// Only need to listen for indeterminate changes.
// All other things are done on a repaint.
- if (e.getPropertyName().equals("inderterminate"))
- if (((Boolean) e.getNewValue()).booleanValue())
- startAnimationTimer();
- else
- stopAnimationTimer();
- else
- progressBar.repaint();
+ if (e.getPropertyName().equals("indeterminate"))
+ if (((Boolean) e.getNewValue()).booleanValue()
+ && progressBar.isShowing())
+ startAnimationTimer();
+ else
+ stopAnimationTimer();
+ }
+ }
+
+ /**
+ * Receives notification when the progressbar is becoming visible or
+ * invisible and starts/stops the animation timer accordingly.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class AncestorHandler implements AncestorListener
+ {
+
+ /**
+ * Receives notification when the progressbar is becoming visible. This
+ * starts the animation timer if the progressbar is indeterminate.
+ *
+ * @param event the ancestor event
+ */
+ public void ancestorAdded(AncestorEvent event)
+ {
+ if (progressBar.isIndeterminate())
+ startAnimationTimer();
+ }
+
+ /**
+ * Receives notification when the progressbar is becoming invisible. This
+ * stops the animation timer if the progressbar is indeterminate.
+ *
+ * @param event the ancestor event
+ */
+ public void ancestorRemoved(AncestorEvent event)
+ {
+ stopAnimationTimer();
+ }
+
+ /**
+ * Receives notification when an ancestor has been moved. We don't need to
+ * do anything here.
+ */
+ public void ancestorMoved(AncestorEvent event)
+ {
+ // Nothing to do here.
}
+
}
/**
@@ -141,6 +186,35 @@ public class BasicProgressBarUI extends ProgressBarUI
}
}
+ /**
+ * Receives notification when the size of the progress bar changes and
+ * invalidates the layout information for the box calculation in
+ * {@link BasicProgressBarUI#getBox(Rectangle)}.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class ComponentHandler extends ComponentAdapter
+ {
+ /**
+ * Receives notification when the size of the progress bar changes and
+ * invalidates the layout information for the box calculation in
+ * {@link BasicProgressBarUI#getBox}.
+ *
+ * @param e the component event
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ boxDependent = -1;
+ boxIndependent = -1;
+ incr = -1;
+ }
+ }
+
+ /**
+ * Holds the value of the bouncing box that is returned by {@link #getBox}.
+ */
+ protected Rectangle boxRect;
+
/** The timer used to move the bouncing box. */
private transient Timer animationTimer;
@@ -172,6 +246,27 @@ public class BasicProgressBarUI extends ProgressBarUI
/** The progressBar for this UI. */
protected JProgressBar progressBar;
+
+ /**
+ * The size of the box returned by {@link #getBox} in the orientation
+ * direction of the progress bar. This is package private to avoid accessor
+ * method.
+ */
+ transient double boxDependent = - 1;
+
+ /**
+ * The size of the box returned by {@link #getBox} against the orientation
+ * direction of the progress bar. This is package private to avoid accessor
+ * method.
+ */
+ transient int boxIndependent = - 1;
+
+ /**
+ * The increment for box animation. This is package private to avoid accessor
+ * method.
+ */
+ transient double incr = -1;
+
/** The length of the cell. The cell is the painted part. */
private transient int cellLength;
@@ -185,6 +280,18 @@ public class BasicProgressBarUI extends ProgressBarUI
private transient Color selectionForeground;
/**
+ * Listens for notification when the component becomes showing and
+ * starts/stops the animation timer.
+ */
+ private AncestorListener ancestorListener;
+
+ /**
+ * Listens for resize events on the progress bar and invalidates some
+ * layout info.
+ */
+ private ComponentListener componentListener;
+
+ /**
* Creates a new BasicProgressBarUI object.
*/
public BasicProgressBarUI()
@@ -248,48 +355,49 @@ public class BasicProgressBarUI extends ProgressBarUI
{
if (!progressBar.isIndeterminate())
return null;
- //numFrames has to be an even number as defined by spec.
- int iterations = numFrames / 2 + 1;
+ if (r == null)
+ r = new Rectangle();
- double boxDependent;
- double boxIndependent;
+ Rectangle vr = new Rectangle();
+ SwingUtilities.calculateInnerArea(progressBar, vr);
- if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
+ // Recalculate the metrics only when size of the progressbar has changed.
+ if (incr == -1 || boxDependent == -1 || boxIndependent == -1)
{
- Dimension dims = getPreferredInnerHorizontal();
- boxDependent = (double) dims.width / iterations;
- boxIndependent = dims.height;
- }
- else
- {
- Dimension dims = getPreferredInnerVertical();
- boxDependent = (double) dims.height / iterations;
- boxIndependent = dims.width;
+ //numFrames has to be an even number as defined by spec.
+ int iterations = numFrames / 2;
+ if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
+ {
+ boxDependent = vr.width / 6.;
+ incr = ((double) (vr.width - boxDependent)) / (double) iterations;
+ boxIndependent = vr.height;
+ }
+ else
+ {
+ boxDependent = vr.height / 6.;
+ incr = ((double) (vr.height - boxDependent)) / (double) iterations;
+ boxIndependent = vr.width;
+ }
}
- Rectangle vr = new Rectangle();
- SwingUtilities.calculateInnerArea(progressBar, vr);
-
int index = getAnimationIndex();
- if (animationIndex > (numFrames + 1) / 2)
+ if (animationIndex > (numFrames) / 2)
index = numFrames - getAnimationIndex();
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
{
- r.x = vr.x + (int) (index * boxDependent);
- r.y = vr.y;
- r.width = (int) boxDependent;
- r.height = (int) boxIndependent;
+ r.x = vr.x + (int) (incr * index);
+ r.y = vr.y;
+ r.width = (int) boxDependent;
+ r.height = (int) boxIndependent;
}
else
{
- index++;
- r.x = vr.x;
- r.y = vr.height - (int) (index * boxDependent) + vr.y;
- r.width = (int) boxIndependent;
- r.height = (int) boxDependent;
+ r.x = vr.x;
+ r.y = vr.height - (int) (incr * index) + vr.y - (int) boxDependent;
+ r.width = (int) boxIndependent;
+ r.height = (int) boxDependent;
}
-
return r;
}
@@ -324,7 +432,22 @@ public class BasicProgressBarUI extends ProgressBarUI
*/
public Dimension getMaximumSize(JComponent c)
{
- return getPreferredSize(c);
+ Insets insets = c.getInsets();
+ Dimension ret;
+ int orientation = progressBar.getOrientation();
+ if (orientation == JProgressBar.VERTICAL)
+ {
+ ret = getPreferredInnerVertical();
+ ret.height = Short.MAX_VALUE;
+ ret.width += insets.left + insets.right;
+ }
+ else
+ {
+ ret = getPreferredInnerHorizontal();
+ ret.width = Short.MAX_VALUE;
+ ret.height += insets.top + insets.bottom;
+ }
+ return ret;
}
/**
@@ -338,7 +461,22 @@ public class BasicProgressBarUI extends ProgressBarUI
*/
public Dimension getMinimumSize(JComponent c)
{
- return getPreferredSize(c);
+ Insets insets = c.getInsets();
+ Dimension ret;
+ int orientation = progressBar.getOrientation();
+ if (orientation == JProgressBar.VERTICAL)
+ {
+ ret = getPreferredInnerVertical();
+ ret.height = 10;
+ ret.width += insets.left + insets.right;
+ }
+ else
+ {
+ ret = getPreferredInnerHorizontal();
+ ret.width = 10;
+ ret.height += insets.top + insets.bottom;
+ }
+ return ret;
}
/**
@@ -351,11 +489,22 @@ public class BasicProgressBarUI extends ProgressBarUI
*/
protected Dimension getPreferredInnerHorizontal()
{
- Rectangle vr = new Rectangle();
+ Font font = progressBar.getFont();
+ FontMetrics fm = progressBar.getFontMetrics(font);
- SwingUtilities.calculateInnerArea(progressBar, vr);
+ int stringWidth = 0;
+ String str = progressBar.getString();
+ if (str != null)
+ stringWidth = fm.stringWidth(progressBar.getString());
+ Insets i = progressBar.getInsets();
+ int prefWidth = Math.max(200 - i.left - i.right, stringWidth);
- return new Dimension(vr.width, vr.height);
+ int stringHeight = 0;
+ if (str != null)
+ stringHeight = fm.getHeight();
+ int prefHeight = Math.max(16 - i.top - i.bottom, stringHeight);
+
+ return new Dimension(prefWidth, prefHeight);
}
/**
@@ -368,11 +517,22 @@ public class BasicProgressBarUI extends ProgressBarUI
*/
protected Dimension getPreferredInnerVertical()
{
- Rectangle vr = new Rectangle();
+ Font font = progressBar.getFont();
+ FontMetrics fm = progressBar.getFontMetrics(font);
- SwingUtilities.calculateInnerArea(progressBar, vr);
+ int stringWidth = 0;
+ String str = progressBar.getString();
+ if (str != null)
+ stringWidth = fm.stringWidth(progressBar.getString());
+ Insets i = progressBar.getInsets();
+ int prefHeight = Math.max(200 - i.left - i.right, stringWidth);
+
+ int stringHeight = 0;
+ if (str != null)
+ stringHeight = fm.getHeight();
+ int prefWidth = Math.max(16 - i.top - i.bottom, stringHeight);
- return new Dimension(vr.width, vr.height);
+ return new Dimension(prefWidth, prefHeight);
}
/**
@@ -386,36 +546,16 @@ public class BasicProgressBarUI extends ProgressBarUI
*/
public Dimension getPreferredSize(JComponent c)
{
- // The only thing we need to worry about is
- // the text size.
Insets insets = c.getInsets();
-
- // make a fontrenderer context so that we can make assumptions about
- // the string bounds
- FontRenderContext ctx = new FontRenderContext(new AffineTransform(),
- false, false);
- Rectangle2D bounds = c.getFont().getStringBounds(progressBar.getString(),
- ctx);
- int textW = (int) bounds.getWidth();
- int textH = (int) bounds.getHeight();
-
- if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
- {
- if (textH < 20)
- textH = 20;
- if (textW < 200)
- textW = 200;
- }
+ Dimension ret;
+ int orientation = progressBar.getOrientation();
+ if (orientation == JProgressBar.VERTICAL)
+ ret = getPreferredInnerVertical();
else
- {
- if (textH < 200)
- textH = 200;
- if (textW < 20)
- textW = 20;
- }
- textW += insets.left + insets.right;
- textH += insets.top + insets.bottom;
- return new Dimension(textW, textH);
+ ret = getPreferredInnerHorizontal();
+ ret.width += insets.left + insets.right;
+ ret.height += insets.top + insets.bottom;
+ return ret;
}
/**
@@ -514,66 +654,22 @@ public class BasicProgressBarUI extends ProgressBarUI
int min = progressBar.getMinimum();
int value = progressBar.getValue();
- Rectangle vr = new Rectangle();
- SwingUtilities.calculateInnerArea(c, vr);
-
- Rectangle or = c.getBounds();
-
+ Rectangle vr = SwingUtilities.calculateInnerArea(c, new Rectangle());
+ Rectangle or = progressBar.getBounds();
Insets insets = c.getInsets();
int amountFull = getAmountFull(insets, or.width, or.height);
- g.setColor(c.getBackground());
- g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false);
-
- if (max != min && len != 0 && value > min)
- {
- int iterations = value / (space + len);
-
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
{
- double spaceInUnits = space * (double) vr.width / (max - min);
- double lenInUnits = len * (double) vr.width / (max - min);
- double currX = vr.x;
-
g.setColor(c.getForeground());
- g.fill3DRect(vr.x, vr.y, amountFull, vr.height, true);
-
- g.setColor(c.getBackground());
- if (spaceInUnits != 0)
- {
- for (int i = 0; i < iterations; i++)
- {
- currX += lenInUnits;
- g.fill3DRect((int) currX, vr.y, (int) spaceInUnits,
- vr.height, true);
- currX += spaceInUnits;
- }
- }
+ g.fillRect(vr.x, vr.y, amountFull, vr.height);
}
else
{
- double currY = vr.y;
- double spaceInUnits = space * (double) vr.height / (max - min);
- double lenInUnits = len * (double) vr.height / (max - min);
-
g.setColor(c.getForeground());
- g.fill3DRect(vr.x, vr.y + vr.height - amountFull, vr.width,
- amountFull, true);
-
- g.setColor(c.getBackground());
-
- if (spaceInUnits != 0)
- {
- for (int i = 0; i < iterations; i++)
- {
- currY -= lenInUnits + spaceInUnits;
- g.fill3DRect(vr.x, (int) currY, vr.width,
- (int) spaceInUnits, true);
- }
- }
+ g.fillRect(vr.x, vr.y + vr.height - amountFull, vr.width, amountFull);
}
- }
if (progressBar.isStringPainted() && !progressBar.getString().equals(""))
paintString(g, 0, 0, or.width, or.height, amountFull, insets);
@@ -599,13 +695,12 @@ public class BasicProgressBarUI extends ProgressBarUI
SwingUtilities.calculateInnerArea(c, vr);
g.setColor(c.getBackground());
- g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false);
+ g.fillRect(vr.x, vr.y, vr.width, vr.height);
- Rectangle box = new Rectangle();
- getBox(box);
+ boxRect = getBox(boxRect);
g.setColor(c.getForeground());
- g.fill3DRect(box.x, box.y, box.width, box.height, true);
+ g.fillRect(boxRect.x, boxRect.y, boxRect.width, boxRect.height);
if (progressBar.isStringPainted() && !progressBar.getString().equals(""))
paintString(g, 0, 0, or.width, or.height,
@@ -628,23 +723,34 @@ public class BasicProgressBarUI extends ProgressBarUI
protected void paintString(Graphics g, int x, int y, int width, int height,
int amountFull, Insets b)
{
+ // FIXME: We do not support vertical text painting because Java2D is needed
+ // for this.
+ if (progressBar.getOrientation() == JProgressBar.VERTICAL)
+ return;
+
// We want to place in the exact center of the bar.
Point placement = getStringPlacement(g, progressBar.getString(),
x + b.left, y + b.top,
width - b.left - b.right,
height - b.top - b.bottom);
- Color saved = g.getColor();
-
- // FIXME: The Color of the text should use selectionForeground and selectionBackground
- // but that can't be done right now, so we'll use white in the mean time.
- g.setColor(Color.WHITE);
+ Color savedColor = g.getColor();
+ Shape savedClip = g.getClip();
FontMetrics fm = g.getFontMetrics(progressBar.getFont());
+ int full = getAmountFull(b, width, height);
+ String str = progressBar.getString();
- g.drawString(progressBar.getString(), placement.x,
- placement.y + fm.getAscent());
-
- g.setColor(saved);
+ // We draw this string two times with different clips so that the text
+ // over the filled area is painted with selectionForeground and over
+ // the clear area with selectionBackground.
+ g.setColor(getSelectionForeground());
+ g.setClip(0, 0, full + b.left, height);
+ g.drawString(str, placement.x, placement.y + fm.getAscent());
+ g.setColor(getSelectionBackground());
+ g.setClip(full + b.left, 0, width - full, height);
+ g.drawString(str, placement.x, placement.y + fm.getAscent());
+ g.setClip(savedClip);
+ g.setColor(savedColor);
}
/**
@@ -712,21 +818,19 @@ public class BasicProgressBarUI extends ProgressBarUI
*/
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- progressBar.setFont(defaults.getFont("ProgressBar.font"));
- progressBar.setForeground(defaults.getColor("ProgressBar.foreground"));
- progressBar.setBackground(defaults.getColor("ProgressBar.background"));
- progressBar.setBorder(defaults.getBorder("ProgressBar.border"));
+ LookAndFeel.installColorsAndFont(progressBar, "ProgressBar.background",
+ "ProgressBar.foreground",
+ "ProgressBar.font");
+ LookAndFeel.installBorder(progressBar, "ProgressBar.border");
progressBar.setOpaque(true);
- selectionForeground = defaults.getColor("ProgressBar.selectionForeground");
- selectionBackground = defaults.getColor("ProgressBar.selectionBackground");
- cellLength = defaults.getInt("ProgressBar.cellLength");
- cellSpacing = defaults.getInt("ProgressBar.cellSpacing");
+ selectionForeground = UIManager.getColor("ProgressBar.selectionForeground");
+ selectionBackground = UIManager.getColor("ProgressBar.selectionBackground");
+ cellLength = UIManager.getInt("ProgressBar.cellLength");
+ cellSpacing = UIManager.getInt("ProgressBar.cellSpacing");
- int repaintInterval = defaults.getInt("ProgressBar.repaintInterval");
- int cycleTime = defaults.getInt("ProgressBar.cycleTime");
+ int repaintInterval = UIManager.getInt("ProgressBar.repaintInterval");
+ int cycleTime = UIManager.getInt("ProgressBar.cycleTime");
if (cycleTime % repaintInterval != 0
&& (cycleTime / repaintInterval) % 2 != 0)
@@ -768,6 +872,12 @@ public class BasicProgressBarUI extends ProgressBarUI
progressBar.addChangeListener(changeListener);
progressBar.addPropertyChangeListener(propertyListener);
animationTimer.addActionListener(animation);
+
+ ancestorListener = new AncestorHandler();
+ progressBar.addAncestorListener(ancestorListener);
+
+ componentListener = new ComponentHandler();
+ progressBar.addComponentListener(componentListener);
}
/**
@@ -783,6 +893,14 @@ public class BasicProgressBarUI extends ProgressBarUI
changeListener = null;
propertyListener = null;
animation = null;
+
+ if (ancestorListener != null)
+ progressBar.removeAncestorListener(ancestorListener);
+ ancestorListener = null;
+
+ if (componentListener != null)
+ progressBar.removeComponentListener(componentListener);
+ componentListener = null;
}
/**
@@ -806,6 +924,8 @@ public class BasicProgressBarUI extends ProgressBarUI
installDefaults();
installListeners();
}
+ if (progressBar.isIndeterminate())
+ startAnimationTimer();
}
/**
@@ -824,4 +944,5 @@ public class BasicProgressBarUI extends ProgressBarUI
animationTimer = null;
progressBar = null;
}
+
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java
index fa74a008bae..8af5ff7f95c 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java
@@ -59,8 +59,6 @@ public class BasicRadioButtonMenuItemUI extends BasicMenuItemUI
public BasicRadioButtonMenuItemUI()
{
super();
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- checkIcon = defaults.getIcon("RadioButtonMenuItem.checkIcon");
}
/**
@@ -98,5 +96,7 @@ public class BasicRadioButtonMenuItemUI extends BasicMenuItemUI
MenuElement[] path,
MenuSelectionManager manager)
{
+ // TODO: May not be implemented properly.
+ item.processMouseEvent(e, path, manager);
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java
index fbd21241a0d..f3698e85908 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package javax.swing.plaf.basic;
+import java.awt.Color;
+import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
@@ -93,6 +95,10 @@ public class BasicRadioButtonUI extends BasicToggleButtonUI
b.setIcon(icon);
if (b.getSelectedIcon() == null)
b.setSelectedIcon(icon);
+ if (b.getDisabledIcon() == null)
+ b.setDisabledIcon(icon);
+ if (b.getDisabledSelectedIcon() == null)
+ b.setDisabledSelectedIcon(icon);
}
/**
@@ -139,10 +145,14 @@ public class BasicRadioButtonUI extends BasicToggleButtonUI
g.setFont(f);
Icon currentIcon = null;
- if (b.isSelected())
+ if (b.isSelected() && b.isEnabled())
currentIcon = b.getSelectedIcon();
- else
+ else if (!b.isSelected() && b.isEnabled())
currentIcon = b.getIcon();
+ else if (b.isSelected() && !b.isEnabled())
+ currentIcon = b.getDisabledSelectedIcon();
+ else // (!b.isSelected() && !b.isEnabled())
+ currentIcon = b.getDisabledIcon();
SwingUtilities.calculateInnerArea(b, vr);
String text = SwingUtilities.layoutCompoundLabel
@@ -157,6 +167,25 @@ public class BasicRadioButtonUI extends BasicToggleButtonUI
}
if (text != null)
paintText(g, b, tr, text);
- paintFocus(g, b, vr, tr, ir);
+ // TODO: Figure out what is the size parameter?
+ if (b.hasFocus() && b.isFocusPainted() && b.isEnabled())
+ paintFocus(g, tr, null);
+ }
+
+ /**
+ * Paints the focus indicator for JRadioButtons.
+ *
+ * @param g the graphics context
+ * @param tr the rectangle for the text label
+ * @param size the size (??)
+ */
+ // TODO: Figure out what for is the size parameter.
+ protected void paintFocus(Graphics g, Rectangle tr, Dimension size)
+ {
+ Color focusColor = UIManager.getColor(getPropertyPrefix() + ".focus");
+ Color saved = g.getColor();
+ g.setColor(focusColor);
+ g.drawRect(tr.x, tr.y, tr.width, tr.height);
+ g.setColor(saved);
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java
index d97f7baea67..2a698e8a162 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java
@@ -42,6 +42,7 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
+import javax.swing.JRootPane;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.RootPaneUI;
@@ -56,11 +57,127 @@ public class BasicRootPaneUI extends RootPaneUI
public void installUI(JComponent c)
{
- c.setBackground(UIManager.getColor("control"));
super.installUI(c);
+ if (c instanceof JRootPane)
+ {
+ JRootPane rp = (JRootPane) c;
+ installDefaults(rp);
+ installComponents(rp);
+ installListeners(rp);
+ installKeyboardActions(rp);
+ }
+ }
+
+ /**
+ * Installs the look and feel defaults for JRootPane.
+ *
+ * @param rp the root pane to install the defaults to
+ */
+ protected void installDefaults(JRootPane rp)
+ {
+ // Is this ok?
+ rp.setBackground(UIManager.getColor("control"));
+ }
+
+ /**
+ * Installs additional look and feel components to the root pane.
+ *
+ * @param rp the root pane to install the components to
+ */
+ protected void installComponents(JRootPane rp)
+ {
+ // All components are initialized in the JRootPane constructor, and since
+ // the createXXXPane methods are protected, I see no reasonable way,
+ // and no need to initialize them here. This method is here anyway
+ // for compatibility and to provide the necessary hooks to subclasses.
+ }
+
+ /**
+ * Installs any look and feel specific listeners on the root pane.
+ *
+ * @param rp the root pane to install the listeners to
+ */
+ protected void installListeners(JRootPane rp)
+ {
+ rp.addPropertyChangeListener(this);
+ }
+
+ /**
+ * Installs look and feel keyboard actions on the root pane.
+ *
+ * @param rp the root pane to install the keyboard actions to
+ */
+ protected void installKeyboardActions(JRootPane rp)
+ {
+ // We currently do not install any keyboard actions here.
+ // This method is here anyway for compatibility and to provide
+ // the necessary hooks to subclasses.
}
public void propertyChange(PropertyChangeEvent event)
{
+ // TODO: Implement this properly.
+ }
+
+ /**
+ * Uninstalls this UI from the root pane. This calls
+ * {@link #uninstallDefaults}, {@link #uninstallComponents},
+ * {@link #uninstallListeners}, {@link #uninstallKeyboardActions}
+ * in this order.
+ *
+ * @param c the root pane to uninstall the UI from
+ */
+ public void uninstallUI(JComponent c)
+ {
+ super.uninstallUI(c);
+ if (c instanceof JRootPane)
+ {
+ JRootPane rp = (JRootPane) c;
+ uninstallDefaults(rp);
+ uninstallComponents(rp);
+ uninstallListeners(rp);
+ uninstallKeyboardActions(rp);
+ }
+ }
+
+ /**
+ * Uninstalls the look and feel defaults that have been installed in
+ * {@link #installDefaults}.
+ *
+ * @param rp the root pane to uninstall the defaults from
+ */
+ protected void uninstallDefaults(JRootPane rp)
+ {
+ // We do nothing here.
+ }
+
+ /**
+ * Uninstalls look and feel components from the root pane.
+ *
+ * @param rp the root pane to uninstall the components from
+ */
+ protected void uninstallComponents(JRootPane rp)
+ {
+ // We do nothing here.
+ }
+
+ /**
+ * Uninstalls any look and feel specific listeners from the root pane.
+ *
+ * @param rp the root pane to uninstall the listeners from
+ */
+ protected void uninstallListeners(JRootPane rp)
+ {
+ rp.removePropertyChangeListener(this);
+ }
+
+ /**
+ * Uninstalls look and feel keyboard actions from the root pane.
+ *
+ * @param rp the root pane to uninstall the keyboard actions from
+ */
+ protected void uninstallKeyboardActions(JRootPane rp)
+ {
+ // We do nothing here.
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java
index 22242afcd8a..2f5eaf391e1 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java
@@ -58,6 +58,7 @@ import javax.swing.BoundedRangeModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JScrollBar;
+import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
@@ -80,6 +81,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
protected class ArrowButtonListener extends MouseAdapter
{
+
/**
* Move the thumb in the direction specified by the button's arrow. If
* this button is held down, then it should keep moving the thumb.
@@ -91,9 +93,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
scrollTimer.stop();
scrollListener.setScrollByBlock(false);
if (e.getSource() == incrButton)
- scrollListener.setDirection(POSITIVE_SCROLL);
- else
- scrollListener.setDirection(NEGATIVE_SCROLL);
+ scrollListener.setDirection(POSITIVE_SCROLL);
+ else if (e.getSource() == decrButton)
+ scrollListener.setDirection(NEGATIVE_SCROLL);
+ scrollTimer.setDelay(100);
scrollTimer.start();
}
@@ -105,6 +108,11 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
public void mouseReleased(MouseEvent e)
{
scrollTimer.stop();
+ scrollTimer.setDelay(300);
+ if (e.getSource() == incrButton)
+ scrollByUnit(POSITIVE_SCROLL);
+ else if (e.getSource() == decrButton)
+ scrollByUnit(NEGATIVE_SCROLL);
}
}
@@ -120,9 +128,8 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
public void stateChanged(ChangeEvent e)
{
- // System.err.println(this + ".stateChanged()");
calculatePreferredSize();
- getThumbBounds();
+ updateThumbRect();
scrollbar.repaint();
}
}
@@ -141,31 +148,27 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
{
if (e.getPropertyName().equals("model"))
{
- ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener);
- scrollbar.getModel().addChangeListener(modelListener);
- getThumbBounds();
+ ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener);
+ scrollbar.getModel().addChangeListener(modelListener);
+ updateThumbRect();
}
else if (e.getPropertyName().equals("orientation"))
{
- incrButton.removeMouseListener(buttonListener);
- decrButton.removeMouseListener(buttonListener);
- int orientation = scrollbar.getOrientation();
- switch (orientation)
- {
- case (JScrollBar.HORIZONTAL):
- incrButton = createIncreaseButton(EAST);
- decrButton = createDecreaseButton(WEST);
- break;
- default:
- incrButton = createIncreaseButton(SOUTH);
- decrButton = createDecreaseButton(NORTH);
- break;
- }
- incrButton.addMouseListener(buttonListener);
- decrButton.addMouseListener(buttonListener);
- calculatePreferredSize();
+ uninstallListeners();
+ uninstallComponents();
+ uninstallDefaults();
+ installDefaults();
+ installComponents();
+ installListeners();
+ }
+ else if (e.getPropertyName().equals("enabled"))
+ {
+ Boolean b = (Boolean) e.getNewValue();
+ if (incrButton != null)
+ incrButton.setEnabled(b.booleanValue());
+ if (decrButton != null)
+ decrButton.setEnabled(b.booleanValue());
}
- scrollbar.repaint();
}
}
@@ -233,19 +236,19 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
{
if (block)
{
- // Only need to check it if it's block scrolling
- // We only block scroll if the click occurs
- // in the track.
- if (! trackListener.shouldScroll(direction))
- {
- trackHighlight = NO_HIGHLIGHT;
- scrollbar.repaint();
- return;
- }
- scrollByBlock(direction);
+ // Only need to check it if it's block scrolling
+ // We only block scroll if the click occurs
+ // in the track.
+ if (!trackListener.shouldScroll(direction))
+ {
+ trackHighlight = NO_HIGHLIGHT;
+ scrollbar.repaint();
+ return;
+ }
+ scrollByBlock(direction);
}
else
- scrollByUnit(direction);
+ scrollByUnit(direction);
}
}
@@ -316,9 +319,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
else
value = valueForYPosition(currentMouseY);
- if (value == scrollbar.getValue())
- return;
-
if (! thumbRect.contains(e.getPoint()))
{
scrollTimer.stop();
@@ -333,6 +333,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
trackHighlight = DECREASE_HIGHLIGHT;
scrollListener.setDirection(NEGATIVE_SCROLL);
}
+ scrollTimer.setDelay(100);
scrollTimer.start();
}
else
@@ -343,8 +344,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
// "lower" edge of the thumb. The value at which
// the cursor is at must be greater or equal
// to that value.
+
+ scrollListener.setScrollByBlock(false);
scrollbar.setValueIsAdjusting(true);
- offset = value - scrollbar.getValue();
+ offset = value - scrollbar.getValue();
}
scrollbar.repaint();
}
@@ -357,11 +360,19 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
public void mouseReleased(MouseEvent e)
{
- trackHighlight = NO_HIGHLIGHT;
scrollTimer.stop();
+ scrollTimer.setDelay(300);
+ currentMouseX = e.getX();
+ currentMouseY = e.getY();
- if (scrollbar.getValueIsAdjusting())
- scrollbar.setValueIsAdjusting(false);
+ if (shouldScroll(POSITIVE_SCROLL))
+ scrollByBlock(POSITIVE_SCROLL);
+ else if (shouldScroll(NEGATIVE_SCROLL))
+ scrollByBlock(NEGATIVE_SCROLL);
+
+ trackHighlight = NO_HIGHLIGHT;
+ scrollListener.setScrollByBlock(false);
+ scrollbar.setValueIsAdjusting(true);
scrollbar.repaint();
}
@@ -381,6 +392,9 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
else
value = valueForYPosition(currentMouseY);
+ if (thumbRect.contains(currentMouseX, currentMouseY))
+ return false;
+
if (direction == POSITIVE_SCROLL)
return (value > scrollbar.getValue());
else
@@ -517,11 +531,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
protected JButton createIncreaseButton(int orientation)
{
- if (incrButton == null)
- incrButton = new BasicArrowButton(orientation);
- else
- ((BasicArrowButton) incrButton).setDirection(orientation);
- return incrButton;
+ return new BasicArrowButton(orientation);
}
/**
@@ -534,11 +544,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
protected JButton createDecreaseButton(int orientation)
{
- if (decrButton == null)
- decrButton = new BasicArrowButton(orientation);
- else
- ((BasicArrowButton) decrButton).setDirection(orientation);
- return decrButton;
+ return new BasicArrowButton(orientation);
}
/**
@@ -602,7 +608,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
public Dimension getMaximumSize(JComponent c)
{
- return getPreferredSize(c);
+ return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
/**
@@ -644,7 +650,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
void calculatePreferredSize()
{
- // System.err.println(this + ".calculatePreferredSize()");
int height;
int width;
height = width = 0;
@@ -707,48 +712,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
protected Rectangle getThumbBounds()
{
- int max = scrollbar.getMaximum();
- int min = scrollbar.getMinimum();
- int value = scrollbar.getValue();
- int extent = scrollbar.getVisibleAmount();
-
- // System.err.println(this + ".getThumbBounds()");
- if (max == min)
- {
- thumbRect.x = trackRect.x;
- thumbRect.y = trackRect.y;
- if (scrollbar.getOrientation() == HORIZONTAL)
- {
- thumbRect.width = getMinimumThumbSize().width;
- thumbRect.height = trackRect.height;
- }
- else
- {
- thumbRect.width = trackRect.width;
- thumbRect.height = getMinimumThumbSize().height;
- }
- return thumbRect;
- }
-
- if (scrollbar.getOrientation() == HORIZONTAL)
- {
- thumbRect.x = trackRect.x;
- thumbRect.x += (value - min) * trackRect.width / (max - min);
- thumbRect.y = trackRect.y;
-
- thumbRect.width = Math.max(extent * trackRect.width / (max - min),
- getMinimumThumbSize().width);
- thumbRect.height = trackRect.height;
- }
- else
- {
- thumbRect.x = trackRect.x;
- thumbRect.y = trackRect.y + value * trackRect.height / (max - min);
-
- thumbRect.width = trackRect.width;
- thumbRect.height = Math.max(extent * trackRect.height / (max - min),
- getMinimumThumbSize().height);
- }
return thumbRect;
}
@@ -760,22 +723,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
protected Rectangle getTrackBounds()
{
- SwingUtilities.calculateInnerArea(scrollbar, trackRect);
-
- if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
- {
- trackRect.width -= incrButton.getPreferredSize().getWidth();
- trackRect.width -= decrButton.getPreferredSize().getWidth();
-
- trackRect.x += decrButton.getPreferredSize().getWidth();
- }
- else
- {
- trackRect.height -= incrButton.getPreferredSize().getHeight();
- trackRect.height -= decrButton.getPreferredSize().getHeight();
-
- trackRect.y += incrButton.getPreferredSize().getHeight();
- }
return trackRect;
}
@@ -785,6 +732,18 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
protected void installComponents()
{
+ if (incrButton != null)
+ scrollbar.add(incrButton);
+ if (decrButton != null)
+ scrollbar.add(decrButton);
+ }
+
+ /**
+ * This method installs the defaults for the scrollbar specified by the
+ * Basic Look and Feel.
+ */
+ protected void installDefaults()
+ {
int orientation = scrollbar.getOrientation();
switch (orientation)
{
@@ -797,31 +756,20 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
decrButton = createDecreaseButton(NORTH);
break;
}
- scrollbar.add(incrButton);
- scrollbar.add(decrButton);
- }
-
- /**
- * This method installs the defaults for the scrollbar specified by the
- * Basic Look and Feel.
- */
- protected void installDefaults()
- {
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- scrollbar.setForeground(defaults.getColor("ScrollBar.foreground"));
- scrollbar.setBackground(defaults.getColor("ScrollBar.background"));
- scrollbar.setBorder(defaults.getBorder("ScrollBar.border"));
+ LookAndFeel.installColors(scrollbar, "ScrollBar.background",
+ "ScrollBar.foreground");
+ LookAndFeel.installBorder(scrollbar, "ScrollBar.border");
scrollbar.setOpaque(true);
scrollbar.setLayout(this);
- thumbColor = defaults.getColor("ScrollBar.thumb");
- thumbDarkShadowColor = defaults.getColor("ScrollBar.thumbDarkShadow");
- thumbHighlightColor = defaults.getColor("ScrollBar.thumbHighlight");
- thumbLightShadowColor = defaults.getColor("ScrollBar.thumbShadow");
+ thumbColor = UIManager.getColor("ScrollBar.thumb");
+ thumbDarkShadowColor = UIManager.getColor("ScrollBar.thumbDarkShadow");
+ thumbHighlightColor = UIManager.getColor("ScrollBar.thumbHighlight");
+ thumbLightShadowColor = UIManager.getColor("ScrollBar.thumbShadow");
- maximumThumbSize = defaults.getDimension("ScrollBar.maximumThumbSize");
- minimumThumbSize = defaults.getDimension("ScrollBar.minimumThumbSize");
+ maximumThumbSize = UIManager.getDimension("ScrollBar.maximumThumbSize");
+ minimumThumbSize = UIManager.getDimension("ScrollBar.minimumThumbSize");
}
/**
@@ -873,11 +821,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
trackRect = new Rectangle();
thumbRect = new Rectangle();
- scrollTimer = new Timer(200, null);
- scrollTimer.setRepeats(true);
+ scrollTimer = new Timer(300, null);
+ installDefaults();
installComponents();
- installDefaults();
configureScrollBarColors();
installListeners();
@@ -908,17 +855,20 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
protected void layoutHScrollbar(JScrollBar sb)
{
- // All we have to do is layout the 2 buttons?
Rectangle vr = new Rectangle();
SwingUtilities.calculateInnerArea(scrollbar, vr);
- // Update the rectangles.
- getTrackBounds();
- getThumbBounds();
-
Dimension incrDims = incrButton.getPreferredSize();
Dimension decrDims = decrButton.getPreferredSize();
+
+ // calculate and update the track bounds
+ SwingUtilities.calculateInnerArea(scrollbar, trackRect);
+ trackRect.width -= incrDims.getWidth();
+ trackRect.width -= decrDims.getWidth();
+ trackRect.x += decrDims.getWidth();
+ updateThumbRect();
+
decrButton.setBounds(vr.x, vr.y, decrDims.width, trackRect.height);
incrButton.setBounds(trackRect.x + trackRect.width, vr.y, incrDims.width,
trackRect.height);
@@ -934,12 +884,16 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
Rectangle vr = new Rectangle();
SwingUtilities.calculateInnerArea(scrollbar, vr);
- // Update rectangles
- getTrackBounds();
- getThumbBounds();
-
Dimension incrDims = incrButton.getPreferredSize();
Dimension decrDims = decrButton.getPreferredSize();
+
+ // Update rectangles
+ SwingUtilities.calculateInnerArea(scrollbar, trackRect);
+ trackRect.height -= incrDims.getHeight();
+ trackRect.height -= decrDims.getHeight();
+ trackRect.y += decrDims.getHeight();
+
+ updateThumbRect();
decrButton.setBounds(vr.x, vr.y, trackRect.width, decrDims.height);
incrButton.setBounds(vr.x, trackRect.y + trackRect.height,
@@ -947,6 +901,58 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
}
/**
+ * Updates the thumb rect.
+ */
+ void updateThumbRect()
+ {
+ int max = scrollbar.getMaximum();
+ int min = scrollbar.getMinimum();
+ int value = scrollbar.getValue();
+ int extent = scrollbar.getVisibleAmount();
+ if (max - extent <= min)
+ {
+ if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL)
+ {
+ thumbRect.x = trackRect.x;
+ thumbRect.y = trackRect.y;
+ thumbRect.width = getMinimumThumbSize().width;
+ thumbRect.height = trackRect.height;
+ }
+ else
+ {
+ thumbRect.x = trackRect.x;
+ thumbRect.y = trackRect.y;
+ thumbRect.width = trackRect.width;
+ thumbRect.height = getMinimumThumbSize().height;
+ }
+ }
+ else
+ {
+ if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL)
+ {
+ thumbRect.x = trackRect.x;
+ thumbRect.width = Math.max(extent * trackRect.width / (max - min),
+ getMinimumThumbSize().width);
+ int availableWidth = trackRect.width - thumbRect.width;
+ thumbRect.x += (value - min) * availableWidth / (max - min - extent);
+ thumbRect.y = trackRect.y;
+ thumbRect.height = trackRect.height;
+ }
+ else
+ {
+ thumbRect.x = trackRect.x;
+ thumbRect.height = Math.max(extent * trackRect.height / (max - min),
+ getMinimumThumbSize().height);
+ int availableHeight = trackRect.height - thumbRect.height;
+ thumbRect.y = trackRect.y
+ + (value - min) * availableHeight / (max - min - extent);
+ thumbRect.width = trackRect.width;
+ }
+ }
+
+ }
+
+ /**
* This method returns the minimum size required for the layout.
*
* @param scrollbarContainer The Container that is laid out.
@@ -1124,10 +1130,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
protected void uninstallComponents()
{
- scrollbar.remove(incrButton);
- scrollbar.remove(decrButton);
- incrButton = null;
- decrButton = null;
+ if (incrButton != null)
+ scrollbar.remove(incrButton);
+ if (decrButton != null)
+ scrollbar.remove(decrButton);
}
/**
@@ -1138,7 +1144,9 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
{
scrollbar.setForeground(null);
scrollbar.setBackground(null);
- scrollbar.setBorder(null);
+ LookAndFeel.uninstallBorder(scrollbar);
+ incrButton = null;
+ decrButton = null;
}
/**
@@ -1155,17 +1163,22 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
protected void uninstallListeners()
{
- scrollTimer.removeActionListener(scrollListener);
+ if (scrollTimer != null)
+ scrollTimer.removeActionListener(scrollListener);
- scrollbar.getModel().removeChangeListener(modelListener);
- scrollbar.removePropertyChangeListener(propertyChangeListener);
-
- decrButton.removeMouseListener(buttonListener);
- incrButton.removeMouseListener(buttonListener);
-
- scrollbar.removeMouseListener(trackListener);
- scrollbar.removeMouseMotionListener(trackListener);
+ if (scrollbar != null)
+ {
+ scrollbar.getModel().removeChangeListener(modelListener);
+ scrollbar.removePropertyChangeListener(propertyChangeListener);
+ scrollbar.removeMouseListener(trackListener);
+ scrollbar.removeMouseMotionListener(trackListener);
+ }
+ if (decrButton != null)
+ decrButton.removeMouseListener(buttonListener);
+ if (incrButton != null)
+ incrButton.removeMouseListener(buttonListener);
+
propertyChangeListener = null;
modelListener = null;
buttonListener = null;
@@ -1182,8 +1195,8 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
public void uninstallUI(JComponent c)
{
- uninstallDefaults();
uninstallListeners();
+ uninstallDefaults();
uninstallComponents();
scrollTimer = null;
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java
index bd1576f37a5..808ed2763e9 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java
@@ -40,13 +40,21 @@ package javax.swing.plaf.basic;
import java.awt.Dimension;
import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
+import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
+import javax.swing.JViewport;
+import javax.swing.LookAndFeel;
import javax.swing.ScrollPaneConstants;
import javax.swing.ScrollPaneLayout;
-import javax.swing.UIDefaults;
-import javax.swing.UIManager;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ScrollPaneUI;
@@ -54,9 +62,207 @@ public class BasicScrollPaneUI extends ScrollPaneUI
implements ScrollPaneConstants
{
+ /**
+ * Listens for changes in the state of the horizontal scrollbar's model and
+ * updates the scrollpane accordingly.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ public class HSBChangeListener implements ChangeListener
+ {
+
+ /**
+ * Receives notification when the state of the horizontal scrollbar
+ * model has changed.
+ *
+ * @param event the change event
+ */
+ public void stateChanged(ChangeEvent event)
+ {
+ JScrollBar hsb = scrollpane.getHorizontalScrollBar();
+ JViewport vp = scrollpane.getViewport();
+ Point viewPosition = vp.getViewPosition();
+ int xpos = hsb.getValue();
+
+ if (xpos != viewPosition.x)
+ {
+ viewPosition.x = xpos;
+ vp.setViewPosition(viewPosition);
+ }
+
+ viewPosition.y = 0;
+ JViewport columnHeader = scrollpane.getColumnHeader();
+ if (columnHeader != null
+ && !columnHeader.getViewPosition().equals(viewPosition))
+ columnHeader.setViewPosition(viewPosition);
+ }
+
+ }
+
+ /**
+ * Listens for changes in the state of the vertical scrollbar's model and
+ * updates the scrollpane accordingly.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ public class VSBChangeListener implements ChangeListener
+ {
+
+ /**
+ * Receives notification when the state of the vertical scrollbar
+ * model has changed.
+ *
+ * @param event the change event
+ */
+ public void stateChanged(ChangeEvent event)
+ {
+ JScrollBar vsb = scrollpane.getVerticalScrollBar();
+ JViewport vp = scrollpane.getViewport();
+ Point viewPosition = vp.getViewPosition();
+ int ypos = vsb.getValue();
+ if (ypos != viewPosition.y)
+ {
+ viewPosition.y = ypos;
+ vp.setViewPosition(viewPosition);
+ }
+
+ viewPosition.x = 0;
+ JViewport rowHeader = scrollpane.getRowHeader();
+ if (rowHeader != null
+ && !rowHeader.getViewPosition().equals(viewPosition))
+ rowHeader.setViewPosition(viewPosition);
+ }
+
+ }
+
+ /**
+ * Listens for changes of the viewport's extent size and updates the
+ * scrollpane accordingly.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ public class ViewportChangeHandler implements ChangeListener
+ {
+
+ /**
+ * Receives notification when the view's size, position or extent size
+ * changes. When the extents size has changed, this method calls
+ * {@link BasicScrollPaneUI#syncScrollPaneWithViewport()} to adjust the
+ * scrollbars extents as well.
+ *
+ * @param event the change event
+ */
+ public void stateChanged(ChangeEvent event)
+ {
+ JViewport vp = scrollpane.getViewport();
+ JScrollBar hsb = scrollpane.getHorizontalScrollBar();
+ JScrollBar vsb = scrollpane.getVerticalScrollBar();
+ syncScrollPaneWithViewport();
+ }
+
+ }
+
+ /**
+ * Listens for property changes on the scrollpane and update the view
+ * accordingly.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ public class PropertyChangeHandler implements PropertyChangeListener
+ {
+
+ /**
+ * Receives notification when any of the scrollpane's bound property
+ * changes. This method calls the appropriate update method on the
+ * <code>ScrollBarUI</code>.
+ *
+ * @param e the property change event
+ *
+ * @see BasicScrollPaneUI#updateColumnHeader(PropertyChangeEvent)
+ * @see BasicScrollPaneUI#updateRowHeader(PropertyChangeEvent)
+ * @see BasicScrollPaneUI#updateScrollBarDisplayPolicy(PropertyChangeEvent)
+ * @see BasicScrollPaneUI#updateViewport(PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ String propName = e.getPropertyName();
+ if (propName.equals("viewport"))
+ updateViewport(e);
+ else if (propName.equals("rowHeader"))
+ updateRowHeader(e);
+ else if (propName.equals("columnHeader"))
+ updateColumnHeader(e);
+ else if (propName.equals("horizontalScrollBarPolicy")
+ || e.getPropertyName().equals("verticalScrollBarPolicy"))
+ updateScrollBarDisplayPolicy(e);
+ else if (propName.equals("verticalScrollBar"))
+ {
+ JScrollBar oldSb = (JScrollBar) e.getOldValue();
+ oldSb.getModel().removeChangeListener(vsbChangeListener);
+ JScrollBar newSb = (JScrollBar) e.getNewValue();
+ newSb.getModel().addChangeListener(vsbChangeListener);
+ }
+ else if (propName.equals("horizontalScrollBar"))
+ {
+ JScrollBar oldSb = (JScrollBar) e.getOldValue();
+ oldSb.getModel().removeChangeListener(hsbChangeListener);
+ JScrollBar newSb = (JScrollBar) e.getNewValue();
+ newSb.getModel().addChangeListener(hsbChangeListener);
+ }
+ }
+
+ }
+
+ /**
+ * Listens for mouse wheel events and update the scrollpane accordingly.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ *
+ * @since 1.4
+ */
+ protected class MouseWheelHandler implements MouseWheelListener
+ {
+
+ /**
+ * Receives notification whenever the mouse wheel is moved.
+ *
+ * @param event the mouse wheel event
+ */
+ public void mouseWheelMoved(MouseWheelEvent event)
+ {
+ // TODO: Implement this properly.
+ }
+
+ }
+
/** The Scrollpane for which the UI is provided by this class. */
protected JScrollPane scrollpane;
+ /**
+ * The horizontal scrollbar listener.
+ */
+ protected ChangeListener hsbChangeListener;
+
+ /**
+ * The vertical scrollbar listener.
+ */
+ protected ChangeListener vsbChangeListener;
+
+ /**
+ * The viewport listener.
+ */
+ protected ChangeListener viewportChangeListener;
+
+ /**
+ * The scrollpane property change listener.
+ */
+ protected PropertyChangeListener spPropertyChangeListener;
+
+ /**
+ * The mousewheel listener for the scrollpane.
+ */
+ MouseWheelListener mouseWheelListener;
+
public static ComponentUI createUI(final JComponent c)
{
return new BasicScrollPaneUI();
@@ -65,11 +271,10 @@ public class BasicScrollPaneUI extends ScrollPaneUI
protected void installDefaults(JScrollPane p)
{
scrollpane = p;
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- p.setForeground(defaults.getColor("ScrollPane.foreground"));
- p.setBackground(defaults.getColor("ScrollPane.background"));
- p.setFont(defaults.getFont("ScrollPane.font"));
- p.setBorder(defaults.getBorder("ScrollPane.border"));
+ LookAndFeel.installColorsAndFont(p, "ScrollPane.background",
+ "ScrollPane.foreground",
+ "ScrollPane.font");
+ LookAndFeel.installBorder(p, "ScrollPane.border");
p.setOpaque(true);
}
@@ -85,16 +290,141 @@ public class BasicScrollPaneUI extends ScrollPaneUI
public void installUI(final JComponent c)
{
super.installUI(c);
- this.installDefaults((JScrollPane)c);
+ installDefaults((JScrollPane) c);
+ installListeners((JScrollPane) c);
+ installKeyboardActions((JScrollPane) c);
+ }
+
+ /**
+ * Installs the listeners on the scrollbars, the viewport and the scrollpane.
+ *
+ * @param sp the scrollpane on which to install the listeners
+ */
+ protected void installListeners(JScrollPane sp)
+ {
+ if (spPropertyChangeListener == null)
+ spPropertyChangeListener = createPropertyChangeListener();
+ sp.addPropertyChangeListener(spPropertyChangeListener);
+
+ if (hsbChangeListener == null)
+ hsbChangeListener = createHSBChangeListener();
+ sp.getHorizontalScrollBar().getModel().addChangeListener(hsbChangeListener);
+
+ if (vsbChangeListener == null)
+ vsbChangeListener = createVSBChangeListener();
+ sp.getVerticalScrollBar().getModel().addChangeListener(vsbChangeListener);
+
+ if (viewportChangeListener == null)
+ viewportChangeListener = createViewportChangeListener();
+ sp.getViewport().addChangeListener(viewportChangeListener);
+
+ if (mouseWheelListener == null)
+ mouseWheelListener = createMouseWheelListener();
+ sp.addMouseWheelListener(mouseWheelListener);
+ }
+
+ /**
+ * Installs additional keyboard actions on the scrollpane. This is a hook
+ * method provided to subclasses in order to install their own keyboard
+ * actions.
+ *
+ * @param sp the scrollpane to install keyboard actions on
+ */
+ protected void installKeyboardActions(JScrollPane sp)
+ {
+ // TODO: Is this only a hook method or should we actually do something
+ // here? If the latter, than figure out what and implement this.
+ }
+
+ /**
+ * Creates and returns the change listener for the horizontal scrollbar.
+ *
+ * @return the change listener for the horizontal scrollbar
+ */
+ protected ChangeListener createHSBChangeListener()
+ {
+ return new HSBChangeListener();
+ }
+
+ /**
+ * Creates and returns the change listener for the vertical scrollbar.
+ *
+ * @return the change listener for the vertical scrollbar
+ */
+ protected ChangeListener createVSBChangeListener()
+ {
+ return new VSBChangeListener();
+ }
+
+ /**
+ * Creates and returns the change listener for the viewport.
+ *
+ * @return the change listener for the viewport
+ */
+ protected ChangeListener createViewportChangeListener()
+ {
+ return new ViewportChangeHandler();
+ }
+
+ /**
+ * Creates and returns the property change listener for the scrollpane.
+ *
+ * @return the property change listener for the scrollpane
+ */
+ protected PropertyChangeListener createPropertyChangeListener()
+ {
+ return new PropertyChangeHandler();
+ }
+
+ /**
+ * Creates and returns the mouse wheel listener for the scrollpane.
+ *
+ * @return the mouse wheel listener for the scrollpane
+ */
+ protected MouseWheelListener createMouseWheelListener()
+ {
+ return new MouseWheelHandler();
}
public void uninstallUI(final JComponent c)
{
super.uninstallUI(c);
this.uninstallDefaults((JScrollPane)c);
+ uninstallListeners((JScrollPane) c);
+ installKeyboardActions((JScrollPane) c);
+ }
+
+ /**
+ * Uninstalls all the listeners that have been installed in
+ * {@link #installListeners(JScrollPane)}.
+ *
+ * @param c the scrollpane from which to uninstall the listeners
+ */
+ protected void uninstallListeners(JComponent c)
+ {
+ JScrollPane sp = (JScrollPane) c;
+ sp.removePropertyChangeListener(spPropertyChangeListener);
+ sp.getHorizontalScrollBar().getModel()
+ .removeChangeListener(hsbChangeListener);
+ sp.getVerticalScrollBar().getModel()
+ .removeChangeListener(vsbChangeListener);
+ sp.getViewport().removeChangeListener(viewportChangeListener);
+ sp.removeMouseWheelListener(mouseWheelListener);
+ }
+
+ /**
+ * Uninstalls all keyboard actions from the JScrollPane that have been
+ * installed by {@link #installKeyboardActions}. This is a hook method
+ * provided to subclasses to add their own keyboard actions.
+ *
+ * @param sp the scrollpane to uninstall keyboard actions from
+ */
+ protected void uninstallKeyboardActions(JScrollPane sp)
+ {
+ // TODO: Is this only a hook method or should we actually do something
+ // here? If the latter, than figure out what and implement this.
}
-
public Dimension getMinimumSize(JComponent c)
{
JScrollPane p = (JScrollPane ) c;
@@ -107,6 +437,76 @@ public class BasicScrollPaneUI extends ScrollPaneUI
// do nothing; the normal painting-of-children algorithm, along with
// ScrollPaneLayout, does all the relevant work.
}
+
+ /**
+ * Synchronizes the scrollbars with the viewport's extents.
+ */
+ protected void syncScrollPaneWithViewport()
+ {
+ JViewport vp = scrollpane.getViewport();
+
+ // Update the horizontal scrollbar.
+ JScrollBar hsb = scrollpane.getHorizontalScrollBar();
+ hsb.setMaximum(vp.getViewSize().width);
+ hsb.setValue(vp.getViewPosition().x);
+ hsb.setVisibleAmount(vp.getExtentSize().width);
+
+ // Update the vertical scrollbar.
+ JScrollBar vsb = scrollpane.getVerticalScrollBar();
+ vsb.setMaximum(vp.getViewSize().height);
+ vsb.setValue(vp.getViewPosition().y);
+ vsb.setVisibleAmount(vp.getExtentSize().height);
+ }
+
+ /**
+ * Receives notification when the <code>columnHeader</code> property has
+ * changed on the scrollpane.
+ *
+ * @param ev the property change event
+ */
+ protected void updateColumnHeader(PropertyChangeEvent ev)
+ {
+ // TODO: Find out what should be done here. Or is this only a hook?
+ }
+
+ /**
+ * Receives notification when the <code>rowHeader</code> property has changed
+ * on the scrollpane.
+ *
+ * @param ev the property change event
+ */
+ protected void updateRowHeader(PropertyChangeEvent ev)
+ {
+ // TODO: Find out what should be done here. Or is this only a hook?
+ }
+
+ /**
+ * Receives notification when the <code>scrollBarDisplayPolicy</code>
+ * property has changed on the scrollpane.
+ *
+ * @param ev the property change event
+ */
+ protected void updateScrollBarDisplayPolicy(PropertyChangeEvent ev)
+ {
+ // TODO: Find out what should be done here. Or is this only a hook?
+ }
+
+ /**
+ * Receives notification when the <code>viewport</code> property has changed
+ * on the scrollpane.
+ *
+ * This method sets removes the viewportChangeListener from the old viewport
+ * and adds it to the new viewport.
+ *
+ * @param ev the property change event
+ */
+ protected void updateViewport(PropertyChangeEvent ev)
+ {
+ JViewport oldViewport = (JViewport) ev.getOldValue();
+ oldViewport.removeChangeListener(viewportChangeListener);
+ JViewport newViewport = (JViewport) ev.getNewValue();
+ oldViewport.addChangeListener(viewportChangeListener);
+ }
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java
index 38c9c7a2820..97caa3af7bd 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java
@@ -41,13 +41,11 @@ package javax.swing.plaf.basic;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
-import java.awt.Insets;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
-import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.SeparatorUI;
@@ -121,10 +119,8 @@ public class BasicSeparatorUI extends SeparatorUI
*/
protected void installDefaults(JSeparator s)
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- shadow = defaults.getColor("Separator.shadow");
- highlight = defaults.getColor("Separator.highlight");
+ shadow = UIManager.getColor("Separator.shadow");
+ highlight = UIManager.getColor("Separator.highlight");
s.setOpaque(false);
}
@@ -165,8 +161,8 @@ public class BasicSeparatorUI extends SeparatorUI
/**
* The separator is made of two lines. The top line will be
- * the highlight color (or left line if it's vertical). The bottom
- * or right line will be the shadow color. The two lines will
+ * the shadow color (or left line if it's vertical). The bottom
+ * or right line will be the highlight color. The two lines will
* be centered inside the bounds box. If the separator is horizontal,
* then it will be vertically centered, or if it's vertical, it will
* be horizontally centered.
@@ -180,9 +176,6 @@ public class BasicSeparatorUI extends SeparatorUI
SwingUtilities.calculateInnerArea(c, r);
Color saved = g.getColor();
- int midAB = r.width / 2 + r.x;
- int midAD = r.height / 2 + r.y;
-
JSeparator s;
if (c instanceof JSeparator)
s = (JSeparator) c;
@@ -190,21 +183,24 @@ public class BasicSeparatorUI extends SeparatorUI
return;
if (s.getOrientation() == JSeparator.HORIZONTAL)
- {
- g.setColor(highlight);
- g.drawLine(r.x, midAD, r.x + r.width, midAD);
-
- g.setColor(shadow);
- g.drawLine(r.x, midAD + 1, r.x + r.width, midAD + 1);
- }
- else
- {
- g.setColor(highlight);
- g.drawLine(midAB, r.y, midAB, r.y + r.height);
-
- g.setColor(shadow);
- g.drawLine(midAB + 1, r.y, midAB + 1, r.y + r.height);
- }
+ {
+ int midAB = r.height / 2;
+ g.setColor(shadow);
+ g.drawLine(r.x, r.y + midAB - 1, r.x + r.width, r.y + midAB - 1);
+
+ g.setColor(highlight);
+ g.fillRect(r.x, r.y + midAB, r.x + r.width, r.y + midAB);
+ }
+ else
+ {
+ int midAD = r.height / 2 + r.y;
+ g.setColor(shadow);
+ g.drawLine(r.x, r.y, r.x, r.y + r.height);
+
+ g.setColor(highlight);
+ g.fillRect(r.x + midAD, r.y + r.height, r.x + midAD, r.y + r.height);
+ }
+ g.setColor(saved);
}
/**
@@ -217,28 +213,14 @@ public class BasicSeparatorUI extends SeparatorUI
*/
public Dimension getPreferredSize(JComponent c)
{
- Dimension dims = new Dimension(0, 0);
- Insets insets = c.getInsets();
-
+ Dimension pref = new Dimension(2, 0);
if (c instanceof JSeparator)
{
JSeparator s = (JSeparator) c;
-
if (s.getOrientation() == JSeparator.HORIZONTAL)
- {
- dims.height = 2;
- dims.width = 40;
- }
- else
- {
- dims.width = 2;
- dims.height = 40;
- }
+ pref = new Dimension(0, 2);
}
- dims.width += insets.left + insets.right;
- dims.height += insets.top + insets.bottom;
-
- return dims;
+ return pref;
}
/**
@@ -251,7 +233,7 @@ public class BasicSeparatorUI extends SeparatorUI
*/
public Dimension getMinimumSize(JComponent c)
{
- return getPreferredSize(c);
+ return new Dimension(0, 0);
}
/**
@@ -264,6 +246,7 @@ public class BasicSeparatorUI extends SeparatorUI
*/
public Dimension getMaximumSize(JComponent c)
{
- return getPreferredSize(c);
+ return new Dimension(Short.MAX_VALUE,
+ Short.MAX_VALUE);
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java
index 0b4058429c5..26f58051902 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java
@@ -60,13 +60,14 @@ import java.beans.PropertyChangeListener;
import java.util.Dictionary;
import java.util.Enumeration;
+import javax.swing.AbstractAction;
import javax.swing.BoundedRangeModel;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JSlider;
+import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
-import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@@ -470,6 +471,34 @@ public class BasicSliderUI extends SliderUI
}
}
+ /**
+ * This class is no longer used as of JDK1.3.
+ */
+ public class ActionScroller extends AbstractAction
+ {
+ /**
+ * Not used.
+ *
+ * @param slider not used
+ * @param dir not used
+ * @param block not used
+ */
+ public ActionScroller(JSlider slider, int dir, boolean block)
+ {
+ // Not used.
+ }
+
+ /**
+ * Not used.
+ *
+ * @param event not used
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ // Not used.
+ }
+ }
+
/** Listener for changes from the model. */
protected ChangeListener changeListener;
@@ -680,16 +709,14 @@ public class BasicSliderUI extends SliderUI
*/
protected void installDefaults(JSlider slider)
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- slider.setForeground(defaults.getColor("Slider.foreground"));
- slider.setBackground(defaults.getColor("Slider.background"));
- shadowColor = defaults.getColor("Slider.shadow");
- highlightColor = defaults.getColor("Slider.highlight");
- focusColor = defaults.getColor("Slider.focus");
- slider.setBorder(defaults.getBorder("Slider.border"));
+ LookAndFeel.installColors(slider, "Slider.background",
+ "Slider.foreground");
+ LookAndFeel.installBorder(slider, "Slider.border");
+ shadowColor = UIManager.getColor("Slider.shadow");
+ highlightColor = UIManager.getColor("Slider.highlight");
+ focusColor = UIManager.getColor("Slider.focus");
+ focusInsets = UIManager.getInsets("Slider.focusInsets");
slider.setOpaque(true);
- focusInsets = defaults.getInsets("Slider.focusInsets");
}
/**
@@ -1465,7 +1492,7 @@ public class BasicSliderUI extends SliderUI
// FIXME: Move this to propertyChangeEvent handler, when we get those.
leftToRightCache = slider.getComponentOrientation() != ComponentOrientation.RIGHT_TO_LEFT;
// FIXME: This next line is only here because the above line is here.
- calculateThumbLocation();
+ calculateGeometry();
if (slider.getPaintTrack())
paintTrack(g);
@@ -1958,7 +1985,7 @@ public class BasicSliderUI extends SliderUI
public void paintThumb(Graphics g)
{
Color saved_color = g.getColor();
-
+
Point a = new Point(thumbRect.x, thumbRect.y);
Point b = new Point(a);
Point c = new Point(a);
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java
index 97ab97b8972..3b7399eafaa 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java
@@ -53,9 +53,8 @@ import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JSpinner;
+import javax.swing.LookAndFeel;
import javax.swing.Timer;
-import javax.swing.UIDefaults;
-import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.SpinnerUI;
@@ -167,16 +166,9 @@ public class BasicSpinnerUI extends SpinnerUI
*/
protected void installDefaults()
{
- /* most of it copied from BasicLabelUI, I don't know what keys are
- available, so someone may want to update this. Hence: TODO
- */
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- /*
- spinner.setForeground(defaults.getColor("Spinner.foreground"));
- spinner.setBackground(defaults.getColor("Spinner.background"));
- spinner.setFont(defaults.getFont("Spinner.font"));
- spinner.setBorder(defaults.getBorder("Spinner.border"));
- */
+ LookAndFeel.installColorsAndFont(spinner, "Spinner.background",
+ "Spinner.foreground", "Spinner.font");
+ LookAndFeel.installBorder(spinner, "Spinner.border");
spinner.setLayout(createLayout());
spinner.setOpaque(true);
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java
index b8674ed2f08..69ed2be7c61 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java
@@ -802,6 +802,7 @@ public class BasicSplitPaneDivider extends Container
*/
protected DividerLayout()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java
index ef8e2282349..746f628df6f 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java
@@ -58,7 +58,7 @@ import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JSplitPane;
import javax.swing.KeyStroke;
-import javax.swing.UIDefaults;
+import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.SplitPaneUI;
@@ -404,7 +404,7 @@ public class BasicSplitPaneUI extends SplitPaneUI
*/
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;
@@ -637,7 +637,6 @@ public class BasicSplitPaneUI extends SplitPaneUI
int x = insets.left;
int h = size;
int w = containerSize.width - insets.left - insets.right;
-
c.setBounds(x, y, w, h);
}
@@ -817,15 +816,12 @@ public class BasicSplitPaneUI extends SplitPaneUI
int newSize = splitPane.getDividerSize();
int[] tmpSizes = layoutManager.getSizes();
dividerSize = tmpSizes[2];
- Component left = splitPane.getLeftComponent();
- Component right = splitPane.getRightComponent();
- int newSpace = newSize - tmpSizes[2];
-
+ 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))
@@ -942,6 +938,7 @@ public class BasicSplitPaneUI extends SplitPaneUI
*/
public BasicSplitPaneUI()
{
+ // Nothing to do here.
}
/**
@@ -991,16 +988,16 @@ public class BasicSplitPaneUI extends SplitPaneUI
*/
protected void installDefaults()
{
+ LookAndFeel.installColors(splitPane, "SplitPane.background",
+ "SplitPane.foreground");
+ LookAndFeel.installBorder(splitPane, "SplitPane.border");
divider = createDefaultDivider();
resetLayoutManager();
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"));
+ splitPane.setDividerSize(UIManager.getInt("SplitPane.dividerSize"));
splitPane.setOpaque(true);
}
@@ -1301,15 +1298,41 @@ public class BasicSplitPaneUI extends SplitPaneUI
*/
public void setDividerLocation(JSplitPane jc, int location)
{
+ location = validLocation(location);
+ Container p = jc.getParent();
+ Dimension rightPrefSize = jc.getRightComponent().getPreferredSize();
+ Dimension size = jc.getSize();
+ // check if the size has been set for the splitpane
+ if (size.width == 0 && size.height == 0)
+ size = jc.getPreferredSize();
+
+ if (getOrientation() == 0 && location > size.height)
+ {
+ location = size.height;
+ while (p != null)
+ {
+ p.setSize(p.getWidth(), p.getHeight() + rightPrefSize.height);
+ p = p.getParent();
+ }
+ }
+ else if (location > size.width)
+ {
+ location = size.width;
+ while (p != null)
+ {
+ p.setSize(p.getWidth() + rightPrefSize.width, p.getHeight());
+ p = p.getParent();
+ }
+ }
+
setLastDragLocation(getDividerLocation(splitPane));
splitPane.setLastDividerLocation(getDividerLocation(splitPane));
int[] tmpSizes = layoutManager.getSizes();
- tmpSizes[0] = location
+ tmpSizes[0] = location
- layoutManager.getInitialLocation(splitPane.getInsets());
tmpSizes[1] = layoutManager.getAvailableSize(splitPane.getSize(),
splitPane.getInsets())
- - tmpSizes[0] - tmpSizes[1];
-
+ - tmpSizes[0];
layoutManager.setSizes(tmpSizes);
splitPane.revalidate();
splitPane.repaint();
@@ -1338,11 +1361,9 @@ public class BasicSplitPaneUI extends SplitPaneUI
*/
public int getMinimumDividerLocation(JSplitPane jc)
{
- int value = layoutManager.getInitialLocation(jc.getInsets())
- - layoutManager.getAvailableSize(jc.getSize(), jc.getInsets())
- + splitPane.getDividerSize();
- if (layoutManager.components[1] != null)
- value += layoutManager.minimumSizeOfComponent(1);
+ int value = layoutManager.getInitialLocation(jc.getInsets());
+ if (layoutManager.components[0] != null)
+ value -= layoutManager.minimumSizeOfComponent(0);
return value;
}
@@ -1388,6 +1409,7 @@ public class BasicSplitPaneUI extends SplitPaneUI
*/
public void paint(Graphics g, JComponent jc)
{
+ // TODO: What should be done here?
}
/**
@@ -1550,10 +1572,12 @@ public class BasicSplitPaneUI extends SplitPaneUI
*/
private int validLocation(int location)
{
- if (location < getMinimumDividerLocation(splitPane))
- return getMinimumDividerLocation(splitPane);
- if (location > getMaximumDividerLocation(splitPane))
- return getMaximumDividerLocation(splitPane);
+ int min = getMinimumDividerLocation(splitPane);
+ int max = getMaximumDividerLocation(splitPane);
+ if (min > 0 && location < min)
+ return min;
+ if (max > 0 && location > max)
+ return max;
return location;
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java
index 7e9d9b9820c..ce9ea3ec7f1 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java
@@ -64,9 +64,9 @@ import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
+import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
-import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@@ -136,36 +136,36 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
{
- if (e.getSource() == incrButton)
- {
- if (++currentScrollLocation >= tabCount)
- currentScrollLocation = tabCount - 1;
-
- int width = 0;
- for (int i = currentScrollLocation - 1; i < tabCount; i++)
- width += rects[i].width;
- if (width < viewport.getWidth())
- // FIXME: Still getting mouse events after the button is disabled.
- // incrButton.setEnabled(false);
- currentScrollLocation--;
- else if (! decrButton.isEnabled())
- decrButton.setEnabled(true);
- tabPane.revalidate();
- tabPane.repaint();
- return;
- }
- else if (e.getSource() == decrButton)
- {
- if (--currentScrollLocation < 0)
- currentScrollLocation = 0;
- if (currentScrollLocation == 0)
- decrButton.setEnabled(false);
- else if (! incrButton.isEnabled())
- incrButton.setEnabled(true);
- tabPane.revalidate();
- tabPane.repaint();
- return;
- }
+ if (e.getSource() == incrButton)
+ {
+ if (++currentScrollLocation >= tabCount)
+ currentScrollLocation = tabCount - 1;
+
+ int width = 0;
+ for (int i = currentScrollLocation - 1; i < tabCount; i++)
+ width += rects[i].width;
+ if (width < viewport.getWidth())
+ // FIXME: Still getting mouse events after the button is disabled.
+ // incrButton.setEnabled(false);
+ currentScrollLocation--;
+ else if (! decrButton.isEnabled())
+ decrButton.setEnabled(true);
+ tabPane.revalidate();
+ tabPane.repaint();
+ return;
+ }
+ else if (e.getSource() == decrButton)
+ {
+ if (--currentScrollLocation < 0)
+ currentScrollLocation = 0;
+ if (currentScrollLocation == 0)
+ decrButton.setEnabled(false);
+ else if (! incrButton.isEnabled())
+ incrButton.setEnabled(true);
+ tabPane.revalidate();
+ tabPane.repaint();
+ return;
+ }
}
int index = tabForCoordinate(tabPane, x, y);
@@ -173,7 +173,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
// We need to check since there are areas where tabs cannot be
// e.g. in the inset area.
if (index != -1 && tabPane.isEnabledAt(index))
- tabPane.setSelectedIndex(index);
+ tabPane.setSelectedIndex(index);
tabPane.revalidate();
tabPane.repaint();
}
@@ -198,15 +198,15 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
if (e.getPropertyName().equals("tabLayoutPolicy"))
{
- layoutManager = createLayoutManager();
-
- tabPane.setLayout(layoutManager);
+ layoutManager = createLayoutManager();
+
+ tabPane.setLayout(layoutManager);
}
else if (e.getPropertyName().equals("tabPlacement")
- && tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
+ && tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
{
- incrButton = createIncreaseButton();
- decrButton = createDecreaseButton();
+ incrButton = createIncreaseButton();
+ decrButton = createDecreaseButton();
}
tabPane.layout();
tabPane.repaint();
@@ -245,13 +245,13 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPane.getSelectedIndex() != -1)
{
- Component visible = getVisibleComponent();
- Insets insets = getContentBorderInsets(tabPane.getTabPlacement());
- 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);
+ Component visible = getVisibleComponent();
+ Insets insets = getContentBorderInsets(tabPane.getTabPlacement());
+ 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);
}
}
@@ -275,35 +275,35 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
Dimension dims;
for (int i = 0; i < tabPane.getTabCount(); i++)
{
- c = tabPane.getComponentAt(i);
- if (c == null)
- continue;
- calcRect = c.getBounds();
- dims = c.getPreferredSize();
- if (dims != null)
- {
- componentHeight = Math.max(componentHeight, dims.height);
- componentWidth = Math.max(componentWidth, dims.width);
- }
+ c = tabPane.getComponentAt(i);
+ if (c == null)
+ continue;
+ calcRect = c.getBounds();
+ dims = c.getPreferredSize();
+ if (dims != null)
+ {
+ componentHeight = Math.max(componentHeight, dims.height);
+ componentWidth = Math.max(componentWidth, dims.width);
+ }
}
Insets insets = tabPane.getInsets();
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
- int min = calculateMaxTabWidth(tabPlacement);
- width = Math.max(min, componentWidth);
-
- int tabAreaHeight = preferredTabAreaHeight(tabPlacement, width);
- height = tabAreaHeight + componentHeight;
+ int min = calculateMaxTabWidth(tabPlacement);
+ width = Math.max(min, componentWidth);
+
+ int tabAreaHeight = preferredTabAreaHeight(tabPlacement, width);
+ height = tabAreaHeight + componentHeight;
}
else
{
- int min = calculateMaxTabHeight(tabPlacement);
- height = Math.max(min, componentHeight);
-
- int tabAreaWidth = preferredTabAreaWidth(tabPlacement, height);
- width = tabAreaWidth + componentWidth;
+ int min = calculateMaxTabHeight(tabPlacement);
+ height = Math.max(min, componentHeight);
+
+ int tabAreaWidth = preferredTabAreaWidth(tabPlacement, height);
+ width = tabAreaWidth + componentWidth;
}
return new Dimension(width, height);
@@ -330,7 +330,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
protected void calculateTabRects(int tabPlacement, int tabCount)
{
if (tabCount == 0)
- return;
+ return;
assureRectsCreated(tabCount);
FontMetrics fm = getFontMetrics();
@@ -343,113 +343,112 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
- int maxHeight = calculateMaxTabHeight(tabPlacement);
-
- calcRect.width -= tabAreaInsets.left + tabAreaInsets.right;
- max = calcRect.width + tabAreaInsets.left + insets.left;
- start += tabAreaInsets.left + insets.left;
- int width = 0;
- int runWidth = start;
-
- for (int i = 0; i < tabCount; i++)
- {
- width = calculateTabWidth(tabPlacement, i, fm);
-
- if (runWidth + width > max)
- {
- runWidth = tabAreaInsets.left + insets.left
- + getTabRunIndent(tabPlacement, ++runs);
- rects[i] = new Rectangle(runWidth,
- insets.top + tabAreaInsets.top,
- width, maxHeight);
- runWidth += width;
- if (runs > tabRuns.length - 1)
- expandTabRunsArray();
- tabRuns[runs] = i;
- }
- else
- {
- rects[i] = new Rectangle(runWidth,
- insets.top + tabAreaInsets.top,
- width, maxHeight);
- runWidth += width;
- }
- }
- runs++;
- tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right;
- tabAreaRect.height = runs * maxTabHeight
- - (runs - 1) * tabRunOverlay
- + tabAreaInsets.top + tabAreaInsets.bottom;
- contentRect.width = tabAreaRect.width;
- contentRect.height = tabPane.getHeight() - insets.top
- - insets.bottom - tabAreaRect.height;
- contentRect.x = insets.left;
- tabAreaRect.x = insets.left;
- if (tabPlacement == SwingConstants.BOTTOM)
- {
- contentRect.y = insets.top;
- tabAreaRect.y = contentRect.y + contentRect.height;
- }
- else
- {
- tabAreaRect.y = insets.top;
- contentRect.y = tabAreaRect.y + tabAreaRect.height;
- }
+ int maxHeight = calculateMaxTabHeight(tabPlacement);
+
+ calcRect.width -= tabAreaInsets.left + tabAreaInsets.right;
+ max = calcRect.width + tabAreaInsets.left + insets.left;
+ start += tabAreaInsets.left + insets.left;
+ int width = 0;
+ int runWidth = start;
+
+ for (int i = 0; i < tabCount; i++)
+ {
+ width = calculateTabWidth(tabPlacement, i, fm);
+ if (runWidth + width > max)
+ {
+ runWidth = tabAreaInsets.left + insets.left
+ + getTabRunIndent(tabPlacement, ++runs);
+ rects[i] = new Rectangle(runWidth,
+ insets.top + tabAreaInsets.top,
+ width, maxHeight);
+ runWidth += width;
+ if (runs > tabRuns.length - 1)
+ expandTabRunsArray();
+ tabRuns[runs] = i;
+ }
+ else
+ {
+ rects[i] = new Rectangle(runWidth,
+ insets.top + tabAreaInsets.top,
+ width, maxHeight);
+ runWidth += width;
+ }
+ }
+ runs++;
+ tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right;
+ tabAreaRect.height = runs * maxTabHeight
+ - (runs - 1) * tabRunOverlay
+ + tabAreaInsets.top + tabAreaInsets.bottom;
+ contentRect.width = tabAreaRect.width;
+ contentRect.height = tabPane.getHeight() - insets.top
+ - insets.bottom - tabAreaRect.height;
+ contentRect.x = insets.left;
+ tabAreaRect.x = insets.left;
+ if (tabPlacement == SwingConstants.BOTTOM)
+ {
+ contentRect.y = insets.top;
+ tabAreaRect.y = contentRect.y + contentRect.height;
+ }
+ else
+ {
+ tabAreaRect.y = insets.top;
+ contentRect.y = tabAreaRect.y + tabAreaRect.height;
+ }
}
else
{
- int maxWidth = calculateMaxTabWidth(tabPlacement);
- calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom;
- max = calcRect.height + tabAreaInsets.top + insets.top;
-
- int height = 0;
- start += tabAreaInsets.top + insets.top;
- int runHeight = start;
-
- int fontHeight = fm.getHeight();
-
- for (int i = 0; i < tabCount; i++)
- {
- height = calculateTabHeight(tabPlacement, i, fontHeight);
- if (runHeight + height > max)
- {
- runHeight = tabAreaInsets.top + insets.top
- + getTabRunIndent(tabPlacement, ++runs);
- rects[i] = new Rectangle(insets.left + tabAreaInsets.left,
- runHeight, maxWidth, height);
- runHeight += height;
- if (runs > tabRuns.length - 1)
- expandTabRunsArray();
- tabRuns[runs] = i;
- }
- else
- {
- rects[i] = new Rectangle(insets.left + tabAreaInsets.left,
- runHeight, maxWidth, height);
- runHeight += height;
- }
- }
- runs++;
-
- tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay
- + tabAreaInsets.left + tabAreaInsets.right;
- tabAreaRect.height = tabPane.getHeight() - insets.top
- - insets.bottom;
- tabAreaRect.y = insets.top;
- contentRect.width = tabPane.getWidth() - insets.left - insets.right
- - tabAreaRect.width;
- contentRect.height = tabAreaRect.height;
- contentRect.y = insets.top;
- if (tabPlacement == SwingConstants.LEFT)
- {
- tabAreaRect.x = insets.left;
- contentRect.x = tabAreaRect.x + tabAreaRect.width;
- }
- else
- {
- contentRect.x = insets.left;
- tabAreaRect.x = contentRect.x + contentRect.width;
- }
+ int maxWidth = calculateMaxTabWidth(tabPlacement);
+ calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom;
+ max = calcRect.height + tabAreaInsets.top + insets.top;
+
+ int height = 0;
+ start += tabAreaInsets.top + insets.top;
+ int runHeight = start;
+
+ int fontHeight = fm.getHeight();
+
+ for (int i = 0; i < tabCount; i++)
+ {
+ height = calculateTabHeight(tabPlacement, i, fontHeight);
+ if (runHeight + height > max)
+ {
+ runHeight = tabAreaInsets.top + insets.top
+ + getTabRunIndent(tabPlacement, ++runs);
+ rects[i] = new Rectangle(insets.left + tabAreaInsets.left,
+ runHeight, maxWidth, height);
+ runHeight += height;
+ if (runs > tabRuns.length - 1)
+ expandTabRunsArray();
+ tabRuns[runs] = i;
+ }
+ else
+ {
+ rects[i] = new Rectangle(insets.left + tabAreaInsets.left,
+ runHeight, maxWidth, height);
+ runHeight += height;
+ }
+ }
+ runs++;
+
+ tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay
+ + tabAreaInsets.left + tabAreaInsets.right;
+ tabAreaRect.height = tabPane.getHeight() - insets.top
+ - insets.bottom;
+ tabAreaRect.y = insets.top;
+ contentRect.width = tabPane.getWidth() - insets.left - insets.right
+ - tabAreaRect.width;
+ contentRect.height = tabAreaRect.height;
+ contentRect.y = insets.top;
+ if (tabPlacement == SwingConstants.LEFT)
+ {
+ tabAreaRect.x = insets.left;
+ contentRect.x = tabAreaRect.x + tabAreaRect.width;
+ }
+ else
+ {
+ contentRect.x = insets.left;
+ tabAreaRect.x = contentRect.x + contentRect.width;
+ }
}
runCount = runs;
@@ -457,62 +456,62 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
normalizeTabRuns(tabPlacement, tabCount, start, max);
selectedRun = getRunForTab(tabCount, tabPane.getSelectedIndex());
if (shouldRotateTabRuns(tabPlacement))
- rotateTabRuns(tabPlacement, selectedRun);
+ rotateTabRuns(tabPlacement, selectedRun);
// Need to pad the runs and move them to the correct location.
for (int i = 0; i < runCount; i++)
{
- int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1;
- if (first == tabCount)
- first = 0;
- int last = lastTabInRun(tabCount, i);
- if (shouldPadTabRun(tabPlacement, i))
- padTabRun(tabPlacement, first, last, max);
-
- // Done padding, now need to move it.
- if (tabPlacement == SwingConstants.TOP && i > 0)
- {
- for (int j = first; j <= last; j++)
- rects[j].y += (runCount - i) * maxTabHeight
- - (runCount - i) * tabRunOverlay;
- }
-
- if (tabPlacement == SwingConstants.BOTTOM)
- {
- int height = tabPane.getBounds().height - insets.bottom
- - tabAreaInsets.bottom;
- int adjustment;
- if (i == 0)
- adjustment = height - maxTabHeight;
- else
- adjustment = height - (runCount - i + 1) * maxTabHeight
- - (runCount - i) * tabRunOverlay;
-
- for (int j = first; j <= last; j++)
- rects[j].y = adjustment;
- }
-
- if (tabPlacement == SwingConstants.LEFT && i > 0)
- {
- for (int j = first; j <= last; j++)
- rects[j].x += (runCount - i) * maxTabWidth
- - (runCount - i) * tabRunOverlay;
- }
-
- if (tabPlacement == SwingConstants.RIGHT)
- {
- int width = tabPane.getBounds().width - insets.right
- - tabAreaInsets.right;
- int adjustment;
- if (i == 0)
- adjustment = width - maxTabWidth;
- else
- adjustment = width - (runCount - i + 1) * maxTabWidth
- + (runCount - i) * tabRunOverlay;
-
- for (int j = first; j <= last; j++)
- rects[j].x = adjustment;
- }
+ int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1;
+ if (first == tabCount)
+ first = 0;
+ int last = lastTabInRun(tabCount, i);
+ if (shouldPadTabRun(tabPlacement, i))
+ padTabRun(tabPlacement, first, last, max);
+
+ // Done padding, now need to move it.
+ if (tabPlacement == SwingConstants.TOP && i > 0)
+ {
+ for (int j = first; j <= last; j++)
+ rects[j].y += (runCount - i) * maxTabHeight
+ - (runCount - i) * tabRunOverlay;
+ }
+
+ if (tabPlacement == SwingConstants.BOTTOM)
+ {
+ int height = tabPane.getBounds().height - insets.bottom
+ - tabAreaInsets.bottom;
+ int adjustment;
+ if (i == 0)
+ adjustment = height - maxTabHeight;
+ else
+ adjustment = height - (runCount - i + 1) * maxTabHeight
+ - (runCount - i) * tabRunOverlay;
+
+ for (int j = first; j <= last; j++)
+ rects[j].y = adjustment;
+ }
+
+ if (tabPlacement == SwingConstants.LEFT && i > 0)
+ {
+ for (int j = first; j <= last; j++)
+ rects[j].x += (runCount - i) * maxTabWidth
+ - (runCount - i) * tabRunOverlay;
+ }
+
+ if (tabPlacement == SwingConstants.RIGHT)
+ {
+ int width = tabPane.getBounds().width - insets.right
+ - tabAreaInsets.right;
+ int adjustment;
+ if (i == 0)
+ adjustment = width - maxTabWidth;
+ else
+ adjustment = width - (runCount - i + 1) * maxTabWidth
+ + (runCount - i) * tabRunOverlay;
+
+ for (int j = first; j <= last; j++)
+ rects[j].x = adjustment;
+ }
}
padSelectedTab(tabPlacement, tabPane.getSelectedIndex());
}
@@ -565,74 +564,74 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == SwingUtilities.TOP
|| tabPlacement == SwingUtilities.BOTTOM)
{
- // We should only do this for runCount - 1, cause we can only shift that many times between
- // runs.
- for (int i = 1; i < runCount; i++)
- {
- Rectangle currRun = rects[lastTabInRun(tabCount, i)];
- Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))];
- int spaceInCurr = currRun.x + currRun.width;
- int spaceInNext = nextRun.x + nextRun.width;
-
- int diffNow = spaceInCurr - spaceInNext;
- int diffLater = (spaceInCurr - currRun.width)
- - (spaceInNext + currRun.width);
- while (Math.abs(diffLater) < Math.abs(diffNow)
- && spaceInNext + currRun.width < max)
- {
- tabRuns[i]--;
- spaceInNext += currRun.width;
- spaceInCurr -= currRun.width;
- currRun = rects[lastTabInRun(tabCount, i)];
- diffNow = spaceInCurr - spaceInNext;
- diffLater = (spaceInCurr - currRun.width)
- - (spaceInNext + currRun.width);
- }
-
- // Fix the bounds.
- int first = lastTabInRun(tabCount, i) + 1;
- int last = lastTabInRun(tabCount, getNextTabRun(i));
- int currX = tabAreaInsets.left;
- for (int j = first; j <= last; j++)
- {
- rects[j].x = currX;
- currX += rects[j].width;
- }
- }
+ // We should only do this for runCount - 1, cause we can only shift that many times between
+ // runs.
+ for (int i = 1; i < runCount; i++)
+ {
+ Rectangle currRun = rects[lastTabInRun(tabCount, i)];
+ Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))];
+ int spaceInCurr = currRun.x + currRun.width;
+ int spaceInNext = nextRun.x + nextRun.width;
+
+ int diffNow = spaceInCurr - spaceInNext;
+ int diffLater = (spaceInCurr - currRun.width)
+ - (spaceInNext + currRun.width);
+ while (Math.abs(diffLater) < Math.abs(diffNow)
+ && spaceInNext + currRun.width < max)
+ {
+ tabRuns[i]--;
+ spaceInNext += currRun.width;
+ spaceInCurr -= currRun.width;
+ currRun = rects[lastTabInRun(tabCount, i)];
+ diffNow = spaceInCurr - spaceInNext;
+ diffLater = (spaceInCurr - currRun.width)
+ - (spaceInNext + currRun.width);
+ }
+
+ // Fix the bounds.
+ int first = lastTabInRun(tabCount, i) + 1;
+ int last = lastTabInRun(tabCount, getNextTabRun(i));
+ int currX = tabAreaInsets.left;
+ for (int j = first; j <= last; j++)
+ {
+ rects[j].x = currX;
+ currX += rects[j].width;
+ }
+ }
}
else
{
- for (int i = 1; i < runCount; i++)
- {
- Rectangle currRun = rects[lastTabInRun(tabCount, i)];
- Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))];
- int spaceInCurr = currRun.y + currRun.height;
- int spaceInNext = nextRun.y + nextRun.height;
-
- int diffNow = spaceInCurr - spaceInNext;
- int diffLater = (spaceInCurr - currRun.height)
- - (spaceInNext + currRun.height);
- while (Math.abs(diffLater) < Math.abs(diffNow)
- && spaceInNext + currRun.height < max)
- {
- tabRuns[i]--;
- spaceInNext += currRun.height;
- spaceInCurr -= currRun.height;
- currRun = rects[lastTabInRun(tabCount, i)];
- diffNow = spaceInCurr - spaceInNext;
- diffLater = (spaceInCurr - currRun.height)
- - (spaceInNext + currRun.height);
- }
-
- int first = lastTabInRun(tabCount, i) + 1;
- int last = lastTabInRun(tabCount, getNextTabRun(i));
- int currY = tabAreaInsets.top;
- for (int j = first; j <= last; j++)
- {
- rects[j].y = currY;
- currY += rects[j].height;
- }
- }
+ for (int i = 1; i < runCount; i++)
+ {
+ Rectangle currRun = rects[lastTabInRun(tabCount, i)];
+ Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))];
+ int spaceInCurr = currRun.y + currRun.height;
+ int spaceInNext = nextRun.y + nextRun.height;
+
+ int diffNow = spaceInCurr - spaceInNext;
+ int diffLater = (spaceInCurr - currRun.height)
+ - (spaceInNext + currRun.height);
+ while (Math.abs(diffLater) < Math.abs(diffNow)
+ && spaceInNext + currRun.height < max)
+ {
+ tabRuns[i]--;
+ spaceInNext += currRun.height;
+ spaceInCurr -= currRun.height;
+ currRun = rects[lastTabInRun(tabCount, i)];
+ diffNow = spaceInCurr - spaceInNext;
+ diffLater = (spaceInCurr - currRun.height)
+ - (spaceInNext + currRun.height);
+ }
+
+ int first = lastTabInRun(tabCount, i) + 1;
+ int last = lastTabInRun(tabCount, getNextTabRun(i));
+ int currY = tabAreaInsets.top;
+ for (int j = first; j <= last; j++)
+ {
+ rects[j].y = currY;
+ currY += rects[j].height;
+ }
+ }
}
}
@@ -673,42 +672,42 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
- int runWidth = rects[end].x + rects[end].width;
- int spaceRemaining = max - runWidth;
- int numTabs = end - start + 1;
-
- // now divvy up the space.
- int spaceAllocated = spaceRemaining / numTabs;
- int currX = rects[start].x;
- for (int i = start; i <= end; i++)
- {
- rects[i].x = currX;
- rects[i].width += spaceAllocated;
- currX += rects[i].width;
- // This is used because since the spaceAllocated
- // variable is an int, it rounds down. Sometimes,
- // we don't fill an entire row, so we make it do
- // so now.
- if (i == end && rects[i].x + rects[i].width != max)
- rects[i].width = max - rects[i].x;
- }
+ int runWidth = rects[end].x + rects[end].width;
+ int spaceRemaining = max - runWidth;
+ int numTabs = end - start + 1;
+
+ // now divvy up the space.
+ int spaceAllocated = spaceRemaining / numTabs;
+ int currX = rects[start].x;
+ for (int i = start; i <= end; i++)
+ {
+ rects[i].x = currX;
+ rects[i].width += spaceAllocated;
+ currX += rects[i].width;
+ // This is used because since the spaceAllocated
+ // variable is an int, it rounds down. Sometimes,
+ // we don't fill an entire row, so we make it do
+ // so now.
+ if (i == end && rects[i].x + rects[i].width != max)
+ rects[i].width = max - rects[i].x;
+ }
}
else
{
- int runHeight = rects[end].y + rects[end].height;
- int spaceRemaining = max - runHeight;
- int numTabs = end - start + 1;
-
- int spaceAllocated = spaceRemaining / numTabs;
- int currY = rects[start].y;
- for (int i = start; i <= end; i++)
- {
- rects[i].y = currY;
- rects[i].height += spaceAllocated;
- currY += rects[i].height;
- if (i == end && rects[i].y + rects[i].height != max)
- rects[i].height = max - rects[i].y;
- }
+ int runHeight = rects[end].y + rects[end].height;
+ int spaceRemaining = max - runHeight;
+ int numTabs = end - start + 1;
+
+ int spaceAllocated = spaceRemaining / numTabs;
+ int currY = rects[start].y;
+ for (int i = start; i <= end; i++)
+ {
+ rects[i].y = currY;
+ rects[i].height += spaceAllocated;
+ currY += rects[i].height;
+ if (i == end && rects[i].y + rects[i].height != max)
+ rects[i].height = max - rects[i].y;
+ }
}
}
@@ -736,7 +735,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
protected int preferredTabAreaHeight(int tabPlacement, int width)
{
if (tabPane.getTabCount() == 0)
- return calculateTabAreaHeight(tabPlacement, 0, 0);
+ return calculateTabAreaHeight(tabPlacement, 0, 0);
int runs = 0;
int runWidth = 0;
@@ -758,14 +757,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
// be IF we got our desired width.
for (int i = 0; i < tabPane.getTabCount(); i++)
{
- tabWidth = calculateTabWidth(tabPlacement, i, fm);
- if (runWidth + tabWidth > width)
- {
- runWidth = tabWidth;
- runs++;
- }
- else
- runWidth += tabWidth;
+ tabWidth = calculateTabWidth(tabPlacement, i, fm);
+ if (runWidth + tabWidth > width)
+ {
+ runWidth = tabWidth;
+ runs++;
+ }
+ else
+ runWidth += tabWidth;
}
runs++;
@@ -787,7 +786,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
protected int preferredTabAreaWidth(int tabPlacement, int height)
{
if (tabPane.getTabCount() == 0)
- return calculateTabAreaHeight(tabPlacement, 0, 0);
+ return calculateTabAreaHeight(tabPlacement, 0, 0);
int runs = 0;
int runHeight = 0;
@@ -804,14 +803,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
for (int i = 0; i < tabPane.getTabCount(); i++)
{
- tabHeight = calculateTabHeight(tabPlacement, i, fontHeight);
- if (runHeight + tabHeight > height)
- {
- runHeight = tabHeight;
- runs++;
- }
- else
- runHeight += tabHeight;
+ tabHeight = calculateTabHeight(tabPlacement, i, fontHeight);
+ if (runHeight + tabHeight > height)
+ {
+ runHeight = tabHeight;
+ runs++;
+ }
+ else
+ runHeight += tabHeight;
}
runs++;
@@ -831,19 +830,19 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
protected void rotateTabRuns(int tabPlacement, int selectedRun)
{
if (runCount == 1 || selectedRun == 1 || selectedRun == -1)
- return;
+ return;
int[] newTabRuns = new int[tabRuns.length];
int currentRun = selectedRun;
int i = 1;
do
{
- newTabRuns[i] = tabRuns[currentRun];
- currentRun = getNextTabRun(currentRun);
- i++;
+ newTabRuns[i] = tabRuns[currentRun];
+ currentRun = getNextTabRun(currentRun);
+ i++;
}
while (i < runCount);
if (runCount > 1)
- newTabRuns[0] = tabRuns[currentRun];
+ newTabRuns[0] = tabRuns[currentRun];
tabRuns = newTabRuns;
BasicTabbedPaneUI.this.selectedRun = 1;
@@ -902,7 +901,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
protected int preferredTabAreaHeight(int tabPlacement, int width)
{
if (tabPane.getTabCount() == 0)
- return calculateTabAreaHeight(tabPlacement, 0, 0);
+ return calculateTabAreaHeight(tabPlacement, 0, 0);
int runs = 1;
@@ -923,7 +922,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
protected int preferredTabAreaWidth(int tabPlacement, int height)
{
if (tabPane.getTabCount() == 0)
- return calculateTabAreaHeight(tabPlacement, 0, 0);
+ return calculateTabAreaHeight(tabPlacement, 0, 0);
int runs = 1;
@@ -944,7 +943,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
protected void calculateTabRects(int tabPlacement, int tabCount)
{
if (tabCount == 0)
- return;
+ return;
assureRectsCreated(tabCount);
FontMetrics fm = getFontMetrics();
@@ -958,76 +957,76 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
- int maxHeight = calculateMaxTabHeight(tabPlacement);
- calcRect.width -= tabAreaInsets.left + tabAreaInsets.right;
- max = calcRect.width + tabAreaInsets.left + insets.left;
- start = tabAreaInsets.left + insets.left;
- int width = 0;
- int runWidth = start;
- top = insets.top + tabAreaInsets.top;
- for (int i = 0; i < tabCount; i++)
- {
- width = calculateTabWidth(tabPlacement, i, fm);
-
- rects[i] = new Rectangle(runWidth, top, width, maxHeight);
- runWidth += width;
- }
- tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right;
- tabAreaRect.height = runs * maxTabHeight
- - (runs - 1) * tabRunOverlay
- + tabAreaInsets.top + tabAreaInsets.bottom;
- contentRect.width = tabAreaRect.width;
- contentRect.height = tabPane.getHeight() - insets.top
- - insets.bottom - tabAreaRect.height;
- contentRect.x = insets.left;
- tabAreaRect.x = insets.left;
- if (tabPlacement == SwingConstants.BOTTOM)
- {
- contentRect.y = insets.top;
- tabAreaRect.y = contentRect.y + contentRect.height;
- }
- else
- {
- tabAreaRect.y = insets.top;
- contentRect.y = tabAreaRect.y + tabAreaRect.height;
- }
+ int maxHeight = calculateMaxTabHeight(tabPlacement);
+ calcRect.width -= tabAreaInsets.left + tabAreaInsets.right;
+ max = calcRect.width + tabAreaInsets.left + insets.left;
+ start = tabAreaInsets.left + insets.left;
+ int width = 0;
+ int runWidth = start;
+ top = insets.top + tabAreaInsets.top;
+ for (int i = 0; i < tabCount; i++)
+ {
+ width = calculateTabWidth(tabPlacement, i, fm);
+
+ rects[i] = new Rectangle(runWidth, top, width, maxHeight);
+ runWidth += width;
+ }
+ tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right;
+ tabAreaRect.height = runs * maxTabHeight
+ - (runs - 1) * tabRunOverlay
+ + tabAreaInsets.top + tabAreaInsets.bottom;
+ contentRect.width = tabAreaRect.width;
+ contentRect.height = tabPane.getHeight() - insets.top
+ - insets.bottom - tabAreaRect.height;
+ contentRect.x = insets.left;
+ tabAreaRect.x = insets.left;
+ if (tabPlacement == SwingConstants.BOTTOM)
+ {
+ contentRect.y = insets.top;
+ tabAreaRect.y = contentRect.y + contentRect.height;
+ }
+ else
+ {
+ tabAreaRect.y = insets.top;
+ contentRect.y = tabAreaRect.y + tabAreaRect.height;
+ }
}
else
{
- int maxWidth = calculateMaxTabWidth(tabPlacement);
-
- calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom;
- max = calcRect.height + tabAreaInsets.top;
- int height = 0;
- start = tabAreaInsets.top + insets.top;
- int runHeight = start;
- int fontHeight = fm.getHeight();
- top = insets.left + tabAreaInsets.left;
- for (int i = 0; i < tabCount; i++)
- {
- height = calculateTabHeight(tabPlacement, i, fontHeight);
- rects[i] = new Rectangle(top, runHeight, maxWidth, height);
- runHeight += height;
- }
- tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay
- + tabAreaInsets.left + tabAreaInsets.right;
- tabAreaRect.height = tabPane.getHeight() - insets.top
- - insets.bottom;
- tabAreaRect.y = insets.top;
- contentRect.width = tabPane.getWidth() - insets.left - insets.right
- - tabAreaRect.width;
- contentRect.height = tabAreaRect.height;
- contentRect.y = insets.top;
- if (tabPlacement == SwingConstants.LEFT)
- {
- tabAreaRect.x = insets.left;
- contentRect.x = tabAreaRect.x + tabAreaRect.width;
- }
- else
- {
- contentRect.x = insets.left;
- tabAreaRect.x = contentRect.x + contentRect.width;
- }
+ int maxWidth = calculateMaxTabWidth(tabPlacement);
+
+ calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom;
+ max = calcRect.height + tabAreaInsets.top;
+ int height = 0;
+ start = tabAreaInsets.top + insets.top;
+ int runHeight = start;
+ int fontHeight = fm.getHeight();
+ top = insets.left + tabAreaInsets.left;
+ for (int i = 0; i < tabCount; i++)
+ {
+ height = calculateTabHeight(tabPlacement, i, fontHeight);
+ rects[i] = new Rectangle(top, runHeight, maxWidth, height);
+ runHeight += height;
+ }
+ tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay
+ + tabAreaInsets.left + tabAreaInsets.right;
+ tabAreaRect.height = tabPane.getHeight() - insets.top
+ - insets.bottom;
+ tabAreaRect.y = insets.top;
+ contentRect.width = tabPane.getWidth() - insets.left - insets.right
+ - tabAreaRect.width;
+ contentRect.height = tabAreaRect.height;
+ contentRect.y = insets.top;
+ if (tabPlacement == SwingConstants.LEFT)
+ {
+ tabAreaRect.x = insets.left;
+ contentRect.x = tabAreaRect.x + tabAreaRect.width;
+ }
+ else
+ {
+ contentRect.x = insets.left;
+ tabAreaRect.x = contentRect.x + contentRect.width;
+ }
}
runCount = runs;
@@ -1047,68 +1046,68 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
int tabCount = tabPane.getTabCount();
Point p = null;
if (tabCount == 0)
- return;
+ return;
int tabPlacement = tabPane.getTabPlacement();
incrButton.hide();
decrButton.hide();
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
- if (tabAreaRect.x + tabAreaRect.width < rects[tabCount - 1].x
- + rects[tabCount - 1].width)
- {
- Dimension incrDims = incrButton.getPreferredSize();
- Dimension decrDims = decrButton.getPreferredSize();
-
- decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
- - incrDims.width - decrDims.width,
- tabAreaRect.y, decrDims.width,
- tabAreaRect.height);
- incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
- - incrDims.width, tabAreaRect.y,
- decrDims.width, tabAreaRect.height);
-
- tabAreaRect.width -= decrDims.width + incrDims.width;
- incrButton.show();
- decrButton.show();
- }
+ if (tabAreaRect.x + tabAreaRect.width < rects[tabCount - 1].x
+ + rects[tabCount - 1].width)
+ {
+ Dimension incrDims = incrButton.getPreferredSize();
+ Dimension decrDims = decrButton.getPreferredSize();
+
+ decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
+ - incrDims.width - decrDims.width,
+ tabAreaRect.y, decrDims.width,
+ tabAreaRect.height);
+ incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
+ - incrDims.width, tabAreaRect.y,
+ decrDims.width, tabAreaRect.height);
+
+ tabAreaRect.width -= decrDims.width + incrDims.width;
+ incrButton.show();
+ decrButton.show();
+ }
}
if (tabPlacement == SwingConstants.LEFT
|| tabPlacement == SwingConstants.RIGHT)
{
- if (tabAreaRect.y + tabAreaRect.height < rects[tabCount - 1].y
- + rects[tabCount - 1].height)
- {
- Dimension incrDims = incrButton.getPreferredSize();
- Dimension decrDims = decrButton.getPreferredSize();
-
- decrButton.setBounds(tabAreaRect.x,
- tabAreaRect.y + tabAreaRect.height
- - incrDims.height - decrDims.height,
- tabAreaRect.width, decrDims.height);
- incrButton.setBounds(tabAreaRect.x,
- tabAreaRect.y + tabAreaRect.height
- - incrDims.height, tabAreaRect.width,
- incrDims.height);
-
- tabAreaRect.height -= decrDims.height + incrDims.height;
- incrButton.show();
- decrButton.show();
- }
+ if (tabAreaRect.y + tabAreaRect.height < rects[tabCount - 1].y
+ + rects[tabCount - 1].height)
+ {
+ Dimension incrDims = incrButton.getPreferredSize();
+ Dimension decrDims = decrButton.getPreferredSize();
+
+ decrButton.setBounds(tabAreaRect.x,
+ tabAreaRect.y + tabAreaRect.height
+ - incrDims.height - decrDims.height,
+ tabAreaRect.width, decrDims.height);
+ incrButton.setBounds(tabAreaRect.x,
+ tabAreaRect.y + tabAreaRect.height
+ - incrDims.height, tabAreaRect.width,
+ incrDims.height);
+
+ tabAreaRect.height -= decrDims.height + incrDims.height;
+ incrButton.show();
+ decrButton.show();
+ }
}
viewport.setBounds(tabAreaRect.x, tabAreaRect.y, tabAreaRect.width,
tabAreaRect.height);
int tabC = tabPane.getTabCount() - 1;
if (tabCount > 0)
{
- int w = Math.max(rects[tabC].width + rects[tabC].x, tabAreaRect.width);
- int h = Math.max(rects[tabC].height, tabAreaRect.height);
- p = findPointForIndex(currentScrollLocation);
-
- // we want to cover that entire space so that borders that run under
- // the tab area don't show up when we move the viewport around.
- panel.setSize(w + p.x, h + p.y);
+ int w = Math.max(rects[tabC].width + rects[tabC].x, tabAreaRect.width);
+ int h = Math.max(rects[tabC].height, tabAreaRect.height);
+ p = findPointForIndex(currentScrollLocation);
+
+ // we want to cover that entire space so that borders that run under
+ // the tab area don't show up when we move the viewport around.
+ panel.setSize(w + p.x, h + p.y);
}
viewport.setViewPosition(p);
viewport.repaint();
@@ -1160,7 +1159,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
public void paint(Graphics g, JComponent c)
{
- paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex());
+ paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex());
}
}
@@ -1182,6 +1181,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
private class ScrollingViewport extends JViewport implements UIResource
{
+ // TODO: Maybe remove this inner class.
}
/**
@@ -1407,22 +1407,22 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == TOP || tabPlacement == BOTTOM)
{
- if (index > 0)
- {
- w += rects[index - 1].x + rects[index - 1].width;
- if (index > selectedIndex)
- w -= insets.left + insets.right;
- }
+ if (index > 0)
+ {
+ w += rects[index - 1].x + rects[index - 1].width;
+ if (index > selectedIndex)
+ w -= insets.left + insets.right;
+ }
}
else
{
- if (index > 0)
- {
- h += rects[index - 1].y + rects[index - 1].height;
- if (index > selectedIndex)
- h -= insets.top + insets.bottom;
- }
+ if (index > 0)
+ {
+ h += rects[index - 1].y + rects[index - 1].height;
+ if (index > selectedIndex)
+ h -= insets.top + insets.bottom;
+ }
}
Point p = new Point(w, h);
@@ -1451,16 +1451,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
super.installUI(c);
if (c instanceof JTabbedPane)
{
- tabPane = (JTabbedPane) c;
-
- installComponents();
- installDefaults();
- installListeners();
- installKeyboardActions();
-
- layoutManager = createLayoutManager();
- tabPane.setLayout(layoutManager);
- tabPane.layout();
+ tabPane = (JTabbedPane) c;
+
+ installComponents();
+ installDefaults();
+ installListeners();
+ installKeyboardActions();
+
+ layoutManager = createLayoutManager();
+ tabPane.setLayout(layoutManager);
+ tabPane.layout();
}
}
@@ -1495,23 +1495,23 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
return new TabbedPaneLayout();
else
{
- incrButton = createIncreaseButton();
- decrButton = createDecreaseButton();
- viewport = new ScrollingViewport();
- viewport.setLayout(null);
- panel = new ScrollingPanel();
- viewport.setView(panel);
- tabPane.add(incrButton);
- tabPane.add(decrButton);
- tabPane.add(viewport);
- currentScrollLocation = 0;
- decrButton.setEnabled(false);
- panel.addMouseListener(mouseListener);
- incrButton.addMouseListener(mouseListener);
- decrButton.addMouseListener(mouseListener);
- viewport.setBackground(Color.LIGHT_GRAY);
-
- return new TabbedPaneScrollLayout();
+ incrButton = createIncreaseButton();
+ decrButton = createDecreaseButton();
+ viewport = new ScrollingViewport();
+ viewport.setLayout(null);
+ panel = new ScrollingPanel();
+ viewport.setView(panel);
+ tabPane.add(incrButton);
+ tabPane.add(decrButton);
+ tabPane.add(viewport);
+ currentScrollLocation = 0;
+ decrButton.setEnabled(false);
+ panel.addMouseListener(mouseListener);
+ incrButton.addMouseListener(mouseListener);
+ decrButton.addMouseListener(mouseListener);
+ viewport.setBackground(Color.LIGHT_GRAY);
+
+ return new TabbedPaneScrollLayout();
}
}
@@ -1536,28 +1536,26 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- tabPane.setFont(defaults.getFont("TabbedPane.font"));
- tabPane.setForeground(defaults.getColor("TabbedPane.foreground"));
- tabPane.setBackground(defaults.getColor("TabbedPane.background"));
+ LookAndFeel.installColorsAndFont(tabPane, "TabbedPane.background",
+ "TabbedPane.foreground",
+ "TabbedPane.font");
tabPane.setOpaque(false);
- highlight = defaults.getColor("TabbedPane.highlight");
- lightHighlight = defaults.getColor("TabbedPane.lightHighlight");
+ highlight = UIManager.getColor("TabbedPane.highlight");
+ lightHighlight = UIManager.getColor("TabbedPane.lightHighlight");
- shadow = defaults.getColor("TabbedPane.shadow");
- darkShadow = defaults.getColor("TabbedPane.darkShadow");
+ shadow = UIManager.getColor("TabbedPane.shadow");
+ darkShadow = UIManager.getColor("TabbedPane.darkShadow");
- focus = defaults.getColor("TabbedPane.focus");
+ focus = UIManager.getColor("TabbedPane.focus");
- textIconGap = defaults.getInt("TabbedPane.textIconGap");
- tabRunOverlay = defaults.getInt("TabbedPane.tabRunOverlay");
+ textIconGap = UIManager.getInt("TabbedPane.textIconGap");
+ tabRunOverlay = UIManager.getInt("TabbedPane.tabRunOverlay");
- tabInsets = defaults.getInsets("TabbedPane.tabbedPaneTabInsets");
- selectedTabPadInsets = defaults.getInsets("TabbedPane.tabbedPaneTabPadInsets");
- tabAreaInsets = defaults.getInsets("TabbedPane.tabbedPaneTabAreaInsets");
- contentBorderInsets = defaults.getInsets("TabbedPane.tabbedPaneContentBorderInsets");
+ tabInsets = UIManager.getInsets("TabbedPane.tabbedPaneTabInsets");
+ selectedTabPadInsets = UIManager.getInsets("TabbedPane.tabbedPaneTabPadInsets");
+ tabAreaInsets = UIManager.getInsets("TabbedPane.tabbedPaneTabAreaInsets");
+ contentBorderInsets = UIManager.getInsets("TabbedPane.tabbedPaneContentBorderInsets");
calcRect = new Rectangle();
tabRuns = new int[10];
@@ -1737,38 +1735,42 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
// we WANT to paint the outermost run first and then work our way in.
int tabCount = tabPane.getTabCount();
int currRun = 1;
+
+ if (tabCount > runCount)
+ runCount = tabCount;
+
if (tabCount < 1)
return;
-
+
if (runCount > 1)
- currRun = 0;
+ currRun = 0;
for (int i = 0; i < runCount; i++)
{
- int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1;
- if (isScroll)
- first = currentScrollLocation;
- else if (first == tabCount)
- first = 0;
- int last = lastTabInRun(tabCount, currRun);
- if (isScroll)
- {
- for (int k = first; k < tabCount; k++)
- {
- if (rects[k].x + rects[k].width - rects[first].x > viewport
- .getWidth())
- {
- last = k;
- break;
- }
- }
- }
-
- for (int j = first; j <= last; j++)
- {
- if (j != selectedIndex || isScroll)
- paintTab(g, tabPlacement, rects, j, ir, tr);
- }
- currRun = getPreviousTabRun(currRun);
+ int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1;
+ if (isScroll)
+ first = currentScrollLocation;
+ else if (first == tabCount)
+ first = 0;
+ int last = lastTabInRun(tabCount, currRun);
+ if (isScroll)
+ {
+ for (int k = first; k < tabCount; k++)
+ {
+ if (rects[k].x + rects[k].width - rects[first].x > viewport
+ .getWidth())
+ {
+ last = k;
+ break;
+ }
+ }
+ }
+
+ for (int j = first; j <= last; j++)
+ {
+ if (j != selectedIndex || isScroll)
+ paintTab(g, tabPlacement, rects, j, ir, tr);
+ }
+ currRun = getPreviousTabRun(currRun);
}
if (! isScroll)
paintTab(g, tabPlacement, rects, selectedIndex, ir, tr);
@@ -1800,24 +1802,24 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
int h = calcRect.height;
if (getRunForTab(tabPane.getTabCount(), tabIndex) == 1)
{
- Insets insets = getTabAreaInsets(tabPlacement);
- switch (tabPlacement)
- {
- case TOP:
- h += insets.bottom;
- break;
- case LEFT:
- w += insets.right;
- break;
- case BOTTOM:
- y -= insets.top;
- h += insets.top;
- break;
- case RIGHT:
- x -= insets.left;
- w += insets.left;
- break;
- }
+ Insets insets = getTabAreaInsets(tabPlacement);
+ switch (tabPlacement)
+ {
+ case TOP:
+ h += insets.bottom;
+ break;
+ case LEFT:
+ w += insets.right;
+ break;
+ case BOTTOM:
+ y -= insets.top;
+ h += insets.top;
+ break;
+ case RIGHT:
+ x -= insets.left;
+ w += insets.left;
+ break;
+ }
}
layoutLabel(tabPlacement, fm, tabIndex, title, icon, calcRect, iconRect,
@@ -1856,7 +1858,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
SwingConstants.CENTER,
SwingConstants.CENTER,
SwingConstants.CENTER,
- SwingConstants.CENTER, tabRect,
+ SwingConstants.RIGHT, tabRect,
iconRect, textRect, textIconGap);
int shiftX = getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
@@ -1904,8 +1906,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
View textView = getTextViewForTab(tabIndex);
if (textView != null)
{
- textView.paint(g, textRect);
- return;
+ textView.paint(g, textRect);
+ return;
}
Color fg = tabPane.getForegroundAt(tabIndex);
@@ -1921,37 +1923,37 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPane.isEnabledAt(tabIndex))
{
- g.setColor(fg);
+ g.setColor(fg);
- int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
+ int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
- if (mnemIndex != -1)
- BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
- textRect.x,
- textRect.y
- + metrics.getAscent());
- else
- g.drawString(title, textRect.x, textRect.y + metrics.getAscent());
+ if (mnemIndex != -1)
+ BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
+ textRect.x,
+ textRect.y
+ + metrics.getAscent());
+ else
+ g.drawString(title, textRect.x, textRect.y + metrics.getAscent());
}
else
{
- g.setColor(bg.brighter());
-
- int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
-
- if (mnemIndex != -1)
- BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
- textRect.x, textRect.y);
- else
- g.drawString(title, textRect.x, textRect.y);
-
- g.setColor(bg.darker());
- if (mnemIndex != -1)
- BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
- textRect.x + 1,
- textRect.y + 1);
- else
- g.drawString(title, textRect.x + 1, textRect.y + 1);
+ g.setColor(bg.brighter());
+
+ int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
+
+ if (mnemIndex != -1)
+ BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
+ textRect.x, textRect.y);
+ else
+ g.drawString(title, textRect.x, textRect.y);
+
+ g.setColor(bg.darker());
+ if (mnemIndex != -1)
+ BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
+ textRect.x + 1,
+ textRect.y + 1);
+ else
+ g.drawString(title, textRect.x + 1, textRect.y + 1);
}
g.setColor(saved_color);
@@ -2037,30 +2039,30 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (! isSelected || tabPlacement != SwingConstants.TOP)
{
- g.setColor(shadow);
- g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
- g.setColor(darkShadow);
- g.drawLine(x, y + h, x + w, y + h);
+ g.setColor(shadow);
+ g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
+ g.setColor(darkShadow);
+ g.drawLine(x, y + h, x + w, y + h);
}
if (! isSelected || tabPlacement != SwingConstants.LEFT)
{
- g.setColor(darkShadow);
- g.drawLine(x + w, y, x + w, y + h);
- g.setColor(shadow);
- g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
+ g.setColor(darkShadow);
+ g.drawLine(x + w, y, x + w, y + h);
+ g.setColor(shadow);
+ g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
}
if (! isSelected || tabPlacement != SwingConstants.RIGHT)
{
- g.setColor(lightHighlight);
- g.drawLine(x, y, x, y + h);
+ g.setColor(lightHighlight);
+ g.drawLine(x, y, x, y + h);
}
if (! isSelected || tabPlacement != SwingConstants.BOTTOM)
{
- g.setColor(lightHighlight);
- g.drawLine(x, y, x + w, y);
+ g.setColor(lightHighlight);
+ g.drawLine(x, y, x + w, y);
}
g.setColor(saved);
@@ -2087,10 +2089,10 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
g.setColor(Color.LIGHT_GRAY);
else
{
- Color bg = tabPane.getBackgroundAt(tabIndex);
- if (bg == null)
- bg = Color.GRAY;
- g.setColor(bg);
+ Color bg = tabPane.getBackgroundAt(tabIndex);
+ if (bg == null)
+ bg = Color.GRAY;
+ g.setColor(bg);
}
g.fillRect(x, y, w, h);
@@ -2144,14 +2146,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == SwingConstants.TOP)
{
- if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
- {
- Point p = findPointForIndex(currentScrollLocation);
- diff = p.x;
- }
-
- g.drawLine(x, y, startgap - diff, y);
- g.drawLine(endgap - diff, y, x + w, y);
+ if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
+ {
+ Point p = findPointForIndex(currentScrollLocation);
+ diff = p.x;
+ }
+
+ g.drawLine(x, y, startgap - diff, y);
+ g.drawLine(endgap - diff, y, x + w, y);
}
else
g.drawLine(x, y, x + w, y);
@@ -2184,14 +2186,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == SwingConstants.LEFT)
{
- if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
- {
- Point p = findPointForIndex(currentScrollLocation);
- diff = p.y;
- }
-
- g.drawLine(x, y, x, startgap - diff);
- g.drawLine(x, endgap - diff, x, y + h);
+ if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
+ {
+ Point p = findPointForIndex(currentScrollLocation);
+ diff = p.y;
+ }
+
+ g.drawLine(x, y, x, startgap - diff);
+ g.drawLine(x, endgap - diff, x, y + h);
}
else
g.drawLine(x, y, x, y + h);
@@ -2223,26 +2225,26 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == SwingConstants.BOTTOM)
{
- if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
- {
- Point p = findPointForIndex(currentScrollLocation);
- diff = p.x;
- }
-
- g.setColor(shadow);
- g.drawLine(x + 1, y + h - 1, startgap - diff, y + h - 1);
- g.drawLine(endgap - diff, y + h - 1, x + w - 1, y + h - 1);
-
- g.setColor(darkShadow);
- g.drawLine(x, y + h, startgap - diff, y + h);
- g.drawLine(endgap - diff, y + h, x + w, y + h);
+ if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
+ {
+ Point p = findPointForIndex(currentScrollLocation);
+ diff = p.x;
+ }
+
+ g.setColor(shadow);
+ g.drawLine(x + 1, y + h - 1, startgap - diff, y + h - 1);
+ g.drawLine(endgap - diff, y + h - 1, x + w - 1, y + h - 1);
+
+ g.setColor(darkShadow);
+ g.drawLine(x, y + h, startgap - diff, y + h);
+ g.drawLine(endgap - diff, y + h, x + w, y + h);
}
else
{
- g.setColor(shadow);
- g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
- g.setColor(darkShadow);
- g.drawLine(x, y + h, x + w, y + h);
+ g.setColor(shadow);
+ g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
+ g.setColor(darkShadow);
+ g.drawLine(x, y + h, x + w, y + h);
}
g.setColor(saved);
@@ -2271,26 +2273,26 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == SwingConstants.RIGHT)
{
- if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
- {
- Point p = findPointForIndex(currentScrollLocation);
- diff = p.y;
- }
-
- g.setColor(shadow);
- g.drawLine(x + w - 1, y + 1, x + w - 1, startgap - diff);
- g.drawLine(x + w - 1, endgap - diff, x + w - 1, y + h - 1);
-
- g.setColor(darkShadow);
- g.drawLine(x + w, y, x + w, startgap - diff);
- g.drawLine(x + w, endgap - diff, x + w, y + h);
+ if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
+ {
+ Point p = findPointForIndex(currentScrollLocation);
+ diff = p.y;
+ }
+
+ g.setColor(shadow);
+ g.drawLine(x + w - 1, y + 1, x + w - 1, startgap - diff);
+ g.drawLine(x + w - 1, endgap - diff, x + w - 1, y + h - 1);
+
+ g.setColor(darkShadow);
+ g.drawLine(x + w, y, x + w, startgap - diff);
+ g.drawLine(x + w, endgap - diff, x + w, y + h);
}
else
{
- g.setColor(shadow);
- g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
- g.setColor(darkShadow);
- g.drawLine(x + w, y, x + w, y + h);
+ g.setColor(shadow);
+ g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
+ g.setColor(darkShadow);
+ g.drawLine(x + w, y, x + w, y + h);
}
g.setColor(saved);
@@ -2337,16 +2339,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
int currRun = 1;
for (int i = 0; i < runCount; i++)
{
- int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1;
- if (first == tabCount)
- first = 0;
- int last = lastTabInRun(tabCount, currRun);
- for (int j = first; j <= last; j++)
- {
- if (getTabBounds(pane, j).contains(p))
- return j;
- }
- currRun = getNextTabRun(currRun);
+ int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1;
+ if (first == tabCount)
+ first = 0;
+ int last = lastTabInRun(tabCount, currRun);
+ for (int j = first; j <= last; j++)
+ {
+ if (getTabBounds(pane, j).contains(p))
+ return j;
+ }
+ currRun = getNextTabRun(currRun);
}
return -1;
}
@@ -2400,10 +2402,10 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
return;
else
{
- int numToCopy = Math.min(tabCount, rects.length);
- Rectangle[] tmp = new Rectangle[tabCount];
- System.arraycopy(rects, 0, tmp, 0, numToCopy);
- rects = tmp;
+ int numToCopy = Math.min(tabCount, rects.length);
+ Rectangle[] tmp = new Rectangle[tabCount];
+ System.arraycopy(rects, 0, tmp, 0, numToCopy);
+ rects = tmp;
}
}
@@ -2418,9 +2420,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
tabRuns = new int[10];
else
{
- int[] newRuns = new int[tabRuns.length + 10];
- System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length);
- tabRuns = newRuns;
+ int[] newRuns = new int[tabRuns.length + 10];
+ System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length);
+ tabRuns = newRuns;
}
}
@@ -2438,12 +2440,12 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
return 1;
for (int i = 0; i < runCount; i++)
{
- int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1;
- if (first == tabCount)
- first = 0;
- int last = lastTabInRun(tabCount, i);
- if (last >= tabIndex && first <= tabIndex)
- return i;
+ int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1;
+ if (first == tabCount)
+ first = 0;
+ int last = lastTabInRun(tabCount, i);
+ if (last >= tabIndex && first <= tabIndex)
+ return i;
}
return -1;
}
@@ -2560,21 +2562,22 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
Icon icon = getIconForTab(tabIndex);
Insets insets = getTabInsets(tabPlacement, tabIndex);
+ int height = 0;
if (icon != null)
{
- Rectangle vr = new Rectangle();
- Rectangle ir = new Rectangle();
- Rectangle tr = new Rectangle();
- layoutLabel(tabPlacement, getFontMetrics(), tabIndex,
- tabPane.getTitleAt(tabIndex), icon, vr, ir, tr,
- tabIndex == tabPane.getSelectedIndex());
- calcRect = tr.union(ir);
+ Rectangle vr = new Rectangle();
+ Rectangle ir = new Rectangle();
+ Rectangle tr = new Rectangle();
+ layoutLabel(tabPlacement, getFontMetrics(), tabIndex,
+ tabPane.getTitleAt(tabIndex), icon, vr, ir, tr,
+ tabIndex == tabPane.getSelectedIndex());
+ height = tr.union(ir).height;
}
else
- calcRect.height = fontHeight;
+ height = fontHeight;
- calcRect.height += insets.top + insets.bottom;
- return calcRect.height;
+ height += insets.top + insets.bottom;
+ return height;
}
/**
@@ -2614,21 +2617,22 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
Icon icon = getIconForTab(tabIndex);
Insets insets = getTabInsets(tabPlacement, tabIndex);
+ int width = 0;
if (icon != null)
{
- Rectangle vr = new Rectangle();
- Rectangle ir = new Rectangle();
- Rectangle tr = new Rectangle();
- layoutLabel(tabPlacement, getFontMetrics(), tabIndex,
- tabPane.getTitleAt(tabIndex), icon, vr, ir, tr,
- tabIndex == tabPane.getSelectedIndex());
- calcRect = tr.union(ir);
+ Rectangle vr = new Rectangle();
+ Rectangle ir = new Rectangle();
+ Rectangle tr = new Rectangle();
+ layoutLabel(tabPlacement, getFontMetrics(), tabIndex,
+ tabPane.getTitleAt(tabIndex), icon, vr, ir, tr,
+ tabIndex == tabPane.getSelectedIndex());
+ width = tr.union(ir).width;
}
else
- calcRect.width = metrics.stringWidth(tabPane.getTitleAt(tabIndex));
+ width = metrics.stringWidth(tabPane.getTitleAt(tabIndex));
- calcRect.width += insets.left + insets.right;
- return calcRect.width;
+ width += insets.left + insets.right;
+ return width;
}
/**
@@ -2775,37 +2779,37 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
- if (direction == SwingConstants.WEST)
- selectPreviousTabInRun(tabPane.getSelectedIndex());
- else if (direction == SwingConstants.EAST)
- selectNextTabInRun(tabPane.getSelectedIndex());
-
- else
- {
- int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
- tabPane.getSelectedIndex(),
- (tabPlacement == SwingConstants.RIGHT)
- ? true : false);
- selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
- offset);
- }
+ if (direction == SwingConstants.WEST)
+ selectPreviousTabInRun(tabPane.getSelectedIndex());
+ else if (direction == SwingConstants.EAST)
+ selectNextTabInRun(tabPane.getSelectedIndex());
+
+ else
+ {
+ int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
+ tabPane.getSelectedIndex(),
+ (tabPlacement == SwingConstants.RIGHT)
+ ? true : false);
+ selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
+ offset);
+ }
}
if (tabPlacement == SwingConstants.LEFT
|| tabPlacement == SwingConstants.RIGHT)
{
- if (direction == SwingConstants.NORTH)
- selectPreviousTabInRun(tabPane.getSelectedIndex());
- else if (direction == SwingConstants.SOUTH)
- selectNextTabInRun(tabPane.getSelectedIndex());
- else
- {
- int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
- tabPane.getSelectedIndex(),
- (tabPlacement == SwingConstants.RIGHT)
- ? true : false);
- selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
- offset);
- }
+ if (direction == SwingConstants.NORTH)
+ selectPreviousTabInRun(tabPane.getSelectedIndex());
+ else if (direction == SwingConstants.SOUTH)
+ selectNextTabInRun(tabPane.getSelectedIndex());
+ else
+ {
+ int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
+ tabPane.getSelectedIndex(),
+ (tabPlacement == SwingConstants.RIGHT)
+ ? true : false);
+ selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
+ offset);
+ }
}
}
@@ -2869,16 +2873,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
int y = rects[tabIndex].y + rects[tabIndex].height / 2;
switch (tabPlacement)
- {
- case SwingConstants.TOP:
- case SwingConstants.BOTTOM:
- y += offset;
- break;
- case SwingConstants.RIGHT:
- case SwingConstants.LEFT:
- x += offset;
- break;
- }
+ {
+ case SwingConstants.TOP:
+ case SwingConstants.BOTTOM:
+ y += offset;
+ break;
+ case SwingConstants.RIGHT:
+ case SwingConstants.LEFT:
+ x += offset;
+ break;
+ }
int index = tabForCoordinate(tabPane, x, y);
if (index != -1)
@@ -3042,31 +3046,31 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
// Sun's version will happily throw an NPE if params are null,
// so I won't check it either.
switch (targetPlacement)
- {
- case SwingConstants.TOP:
- targetInsets.top = topInsets.top;
- targetInsets.left = topInsets.left;
- targetInsets.right = topInsets.right;
- targetInsets.bottom = topInsets.bottom;
- break;
- case SwingConstants.LEFT:
- targetInsets.left = topInsets.top;
- targetInsets.top = topInsets.left;
- targetInsets.right = topInsets.bottom;
- targetInsets.bottom = topInsets.right;
- break;
- case SwingConstants.BOTTOM:
- targetInsets.top = topInsets.bottom;
- targetInsets.bottom = topInsets.top;
- targetInsets.left = topInsets.left;
- targetInsets.right = topInsets.right;
- break;
- case SwingConstants.RIGHT:
- targetInsets.top = topInsets.left;
- targetInsets.left = topInsets.bottom;
- targetInsets.bottom = topInsets.right;
- targetInsets.right = topInsets.top;
- break;
- }
+ {
+ case SwingConstants.TOP:
+ targetInsets.top = topInsets.top;
+ targetInsets.left = topInsets.left;
+ targetInsets.right = topInsets.right;
+ targetInsets.bottom = topInsets.bottom;
+ break;
+ case SwingConstants.LEFT:
+ targetInsets.left = topInsets.top;
+ targetInsets.top = topInsets.left;
+ targetInsets.right = topInsets.bottom;
+ targetInsets.bottom = topInsets.right;
+ break;
+ case SwingConstants.BOTTOM:
+ targetInsets.top = topInsets.bottom;
+ targetInsets.bottom = topInsets.top;
+ targetInsets.left = topInsets.left;
+ targetInsets.right = topInsets.right;
+ break;
+ case SwingConstants.RIGHT:
+ targetInsets.top = topInsets.left;
+ targetInsets.left = topInsets.bottom;
+ targetInsets.bottom = topInsets.right;
+ targetInsets.right = topInsets.top;
+ break;
+ }
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java
index 700b406d076..ec0467a74f3 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java
@@ -46,7 +46,7 @@ import java.awt.event.MouseEvent;
import javax.swing.CellRendererPane;
import javax.swing.JComponent;
-import javax.swing.UIDefaults;
+import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.MouseInputListener;
@@ -57,8 +57,7 @@ import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
-public class BasicTableHeaderUI
- extends TableHeaderUI
+public class BasicTableHeaderUI extends TableHeaderUI
{
public static ComponentUI createUI(JComponent h)
@@ -71,16 +70,42 @@ public class BasicTableHeaderUI
protected CellRendererPane rendererPane;
protected Border cellBorder;
- class MouseInputHandler
- implements MouseInputListener
+ public class MouseInputHandler implements MouseInputListener
{
- public void mouseClicked(MouseEvent e) {}
- public void mouseDragged(MouseEvent e) {}
- public void mouseEntered(MouseEvent e) {}
- public void mouseExited(MouseEvent e) {}
- public void mouseMoved(MouseEvent e) {}
- public void mousePressed(MouseEvent e) {}
- public void mouseReleased(MouseEvent e) {}
+ public void mouseClicked(MouseEvent e)
+ {
+ // TODO: Implement this properly.
+ }
+
+ public void mouseDragged(MouseEvent e)
+ {
+ // TODO: Implement this properly.
+ }
+
+ public void mouseEntered(MouseEvent e)
+ {
+ // TODO: Implement this properly.
+ }
+
+ public void mouseExited(MouseEvent e)
+ {
+ // TODO: Implement this properly.
+ }
+
+ public void mouseMoved(MouseEvent e)
+ {
+ // TODO: Implement this properly.
+ }
+
+ public void mousePressed(MouseEvent e)
+ {
+ // TODO: Implement this properly.
+ }
+
+ public void mouseReleased(MouseEvent e)
+ {
+ // TODO: Implement this properly.
+ }
}
protected MouseInputListener createMouseInputListener()
@@ -95,15 +120,15 @@ public class BasicTableHeaderUI
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- header.setBackground(defaults.getColor("TableHeader.background"));
- header.setForeground(defaults.getColor("TableHeader.foreground"));
- header.setFont(defaults.getFont("TableHeader.font"));
- cellBorder = defaults.getBorder("TableHeader.cellBorder");
+ LookAndFeel.installColorsAndFont(header, "TableHeader.background",
+ "TableHeader.foreground",
+ "TableHeader.font");
+ cellBorder = UIManager.getBorder("TableHeader.cellBorder");
}
protected void installKeyboardActions()
{
+ // TODO: Implement this properly.
}
protected void installListeners()
@@ -128,6 +153,7 @@ public class BasicTableHeaderUI
protected void uninstallKeyboardActions()
{
+ // TODO: Implement this properly.
}
protected void uninstallListeners()
@@ -157,6 +183,7 @@ public class BasicTableHeaderUI
Rectangle bounds = header.getHeaderRect(i);
if (bounds.intersects(clip))
{
+ Rectangle oldClip = gfx.getClipBounds();
TableColumn col = cmod.getColumn(i);
TableCellRenderer rend = col.getHeaderRenderer();
if (rend == null)
@@ -173,10 +200,12 @@ public class BasicTableHeaderUI
if (comp instanceof JComponent)
((JComponent)comp).setBorder(cellBorder);
gfx.translate(bounds.x, bounds.y);
+ gfx.setClip(0, 0, bounds.width, bounds.height);
comp.setSize(bounds.width, bounds.height);
comp.setLocation(0,0);
comp.paint(gfx);
gfx.translate(-bounds.x, -bounds.y);
+ gfx.setClip(oldClip);
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java
index 4559937eb69..25a845b36b8 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java
@@ -49,35 +49,38 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
-import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
-import javax.swing.BorderFactory;
import javax.swing.CellRendererPane;
+import javax.swing.DefaultListSelectionModel;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
+import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.MouseInputListener;
+import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.InputMapUIResource;
import javax.swing.plaf.TableUI;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
+import javax.swing.table.TableModel;
-public class BasicTableUI
- extends TableUI
+public class BasicTableUI extends TableUI
{
public static ComponentUI createUI(JComponent comp)
{
@@ -93,23 +96,72 @@ public class BasicTableUI
/** The normal cell border. */
Border cellBorder;
- /** The cell border for selected/highlighted cells. */
- Border highlightCellBorder;
-
/** The action bound to KeyStrokes. */
TableAction action;
- class FocusHandler implements FocusListener
+ /**
+ * Listens for changes to the tables properties.
+ */
+ private PropertyChangeListener propertyChangeListener;
+
+ /**
+ * Handles key events for the JTable. Key events should be handled through
+ * the InputMap/ActionMap mechanism since JDK1.3. This class is only there
+ * for backwards compatibility.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ public class KeyHandler implements KeyListener
+ {
+
+ /**
+ * Receives notification that a key has been pressed and released.
+ *
+ * @param event the key event
+ */
+ public void keyTyped(KeyEvent event)
+ {
+ // Key events should be handled through the InputMap/ActionMap mechanism
+ // since JDK1.3. This class is only there for backwards compatibility.
+ }
+
+ /**
+ * Receives notification that a key has been pressed.
+ *
+ * @param event the key event
+ */
+ public void keyPressed(KeyEvent event)
+ {
+ // Key events should be handled through the InputMap/ActionMap mechanism
+ // since JDK1.3. This class is only there for backwards compatibility.
+ }
+
+ /**
+ * Receives notification that a key has been released.
+ *
+ * @param event the key event
+ */
+ public void keyReleased(KeyEvent event)
+ {
+ // Key events should be handled through the InputMap/ActionMap mechanism
+ // since JDK1.3. This class is only there for backwards compatibility.
+ }
+ }
+
+ public class FocusHandler implements FocusListener
{
public void focusGained(FocusEvent e)
{
+ // TODO: Implement this properly.
}
+
public void focusLost(FocusEvent e)
{
+ // TODO: Implement this properly.
}
}
- class MouseInputHandler implements MouseInputListener
+ public class MouseInputHandler implements MouseInputListener
{
Point begin, curr;
@@ -145,54 +197,123 @@ public class BasicTableUI
public void mouseClicked(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
+
public void mouseDragged(MouseEvent e)
{
- curr = new Point(e.getX(), e.getY());
- updateSelection(e.isControlDown());
+ if (table.isEnabled())
+ {
+ curr = new Point(e.getX(), e.getY());
+ updateSelection(e.isControlDown());
+ }
}
+
public void mouseEntered(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
+
public void mouseExited(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
+
public void mouseMoved(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
+
public void mousePressed(MouseEvent e)
{
- ListSelectionModel rowModel = table.getSelectionModel();
- ListSelectionModel colModel = table.getColumnModel().getSelectionModel();
- int rowLead = rowModel.getLeadSelectionIndex();
- int colLead = colModel.getLeadSelectionIndex();
+ if (table.isEnabled())
+ {
+ ListSelectionModel rowModel = table.getSelectionModel();
+ ListSelectionModel colModel = table.getColumnModel().getSelectionModel();
+ int rowLead = rowModel.getLeadSelectionIndex();
+ int colLead = colModel.getLeadSelectionIndex();
- begin = new Point(e.getX(), e.getY());
- curr = new Point(e.getX(), e.getY());
- //if control is pressed and the cell is already selected, deselect it
- if (e.isControlDown() && table.
- isCellSelected(table.rowAtPoint(begin),table.columnAtPoint(begin)))
- {
- table.getSelectionModel().
- removeSelectionInterval(table.rowAtPoint(begin),
- table.rowAtPoint(begin));
- table.getColumnModel().getSelectionModel().
- removeSelectionInterval(table.columnAtPoint(begin),
- table.columnAtPoint(begin));
- }
- else
- updateSelection(e.isControlDown());
+ begin = new Point(e.getX(), e.getY());
+ curr = new Point(e.getX(), e.getY());
+ //if control is pressed and the cell is already selected, deselect it
+ if (e.isControlDown() && table.
+ isCellSelected(table.rowAtPoint(begin),table.columnAtPoint(begin)))
+ {
+ table.getSelectionModel().
+ removeSelectionInterval(table.rowAtPoint(begin),
+ table.rowAtPoint(begin));
+ table.getColumnModel().getSelectionModel().
+ removeSelectionInterval(table.columnAtPoint(begin),
+ table.columnAtPoint(begin));
+ }
+ else
+ updateSelection(e.isControlDown());
- // If we were editing, but the moved to another cell, stop editing
- if (rowLead != rowModel.getLeadSelectionIndex() ||
- colLead != colModel.getLeadSelectionIndex())
- if (table.isEditing())
- table.editingStopped(new ChangeEvent(e));
+ // If we were editing, but the moved to another cell, stop editing
+ if (rowLead != rowModel.getLeadSelectionIndex() ||
+ colLead != colModel.getLeadSelectionIndex())
+ if (table.isEditing())
+ table.editingStopped(new ChangeEvent(e));
+ }
}
+
public void mouseReleased(MouseEvent e)
{
- begin = null;
- curr = null;
+ if (table.isEnabled())
+ {
+ begin = null;
+ curr = null;
+ }
+ }
+ }
+
+ /**
+ * Listens for changes to the model property of the JTable and adjusts some
+ * settings.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class PropertyChangeHandler implements PropertyChangeListener
+ {
+ /**
+ * Receives notification if one of the JTable's properties changes.
+ *
+ * @param ev the property change event
+ */
+ public void propertyChange(PropertyChangeEvent ev)
+ {
+ String propName = ev.getPropertyName();
+ if (propName.equals("model"))
+ {
+ ListSelectionModel rowSel = table.getSelectionModel();
+ rowSel.clearSelection();
+ ListSelectionModel colSel = table.getColumnModel().getSelectionModel();
+ colSel.clearSelection();
+ TableModel model = table.getModel();
+
+ // Adjust lead and anchor selection indices of the row and column
+ // selection models.
+ if (model.getRowCount() > 0)
+ {
+ rowSel.setAnchorSelectionIndex(0);
+ rowSel.setLeadSelectionIndex(0);
+ }
+ else
+ {
+ rowSel.setAnchorSelectionIndex(-1);
+ rowSel.setLeadSelectionIndex(-1);
+ }
+ if (model.getColumnCount() > 0)
+ {
+ colSel.setAnchorSelectionIndex(0);
+ colSel.setLeadSelectionIndex(0);
+ }
+ else
+ {
+ colSel.setAnchorSelectionIndex(-1);
+ colSel.setLeadSelectionIndex(-1);
+ }
+ }
}
}
@@ -206,6 +327,17 @@ public class BasicTableUI
return new MouseInputHandler();
}
+
+ /**
+ * Creates and returns a key listener for the JTable.
+ *
+ * @return a key listener for the JTable
+ */
+ protected KeyListener createKeyListener()
+ {
+ return new KeyHandler();
+ }
+
/**
* Return the maximum size of the table. The maximum height is the row
* height times the number of rows. The maximum width is the sum of
@@ -255,47 +387,13 @@ public class BasicTableUI
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- table.setFont(defaults.getFont("Table.font"));
- table.setGridColor(defaults.getColor("Table.gridColor"));
- table.setForeground(defaults.getColor("Table.foreground"));
- table.setBackground(defaults.getColor("Table.background"));
- table.setSelectionForeground(defaults.getColor("Table.selectionForeground"));
- table.setSelectionBackground(defaults.getColor("Table.selectionBackground"));
+ LookAndFeel.installColorsAndFont(table, "Table.background",
+ "Table.foreground", "Table.font");
+ table.setGridColor(UIManager.getColor("Table.gridColor"));
+ table.setSelectionForeground(UIManager.getColor("Table.selectionForeground"));
+ table.setSelectionBackground(UIManager.getColor("Table.selectionBackground"));
table.setOpaque(true);
-
- highlightCellBorder = defaults.getBorder("Table.focusCellHighlightBorder");
- cellBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1);
- }
-
- private int convertModifiers(int mod)
- {
- if ((mod & KeyEvent.SHIFT_DOWN_MASK) != 0)
- {
- mod |= KeyEvent.SHIFT_MASK;
- mod &= ~KeyEvent.SHIFT_DOWN_MASK;
- }
- if ((mod & KeyEvent.CTRL_DOWN_MASK) != 0)
- {
- mod |= KeyEvent.CTRL_MASK;
- mod &= ~KeyEvent.CTRL_DOWN_MASK;
- }
- if ((mod & KeyEvent.META_DOWN_MASK) != 0)
- {
- mod |= KeyEvent.META_MASK;
- mod &= ~KeyEvent.META_DOWN_MASK;
- }
- if ((mod & KeyEvent.ALT_DOWN_MASK) != 0)
- {
- mod |= KeyEvent.ALT_MASK;
- mod &= ~KeyEvent.ALT_DOWN_MASK;
- }
- if ((mod & KeyEvent.ALT_GRAPH_DOWN_MASK) != 0)
- {
- mod |= KeyEvent.ALT_GRAPH_MASK;
- mod &= ~KeyEvent.ALT_GRAPH_DOWN_MASK;
- }
- return mod;
+ rendererPane = new CellRendererPane();
}
protected void installKeyboardActions()
@@ -304,27 +402,21 @@ public class BasicTableUI
InputMap ancestorMap = (InputMap)defaults.get("Table.ancestorInputMap");
InputMapUIResource parentInputMap = new InputMapUIResource();
// FIXME: The JDK uses a LazyActionMap for parentActionMap
- ActionMap parentActionMap = new ActionMap();
+ ActionMap parentActionMap = new ActionMapUIResource();
action = new TableAction();
Object keys[] = ancestorMap.allKeys();
// Register key bindings in the UI InputMap-ActionMap pair
- // Note that we register key bindings with both the old and new modifier
- // masks: InputEvent.SHIFT_MASK and InputEvent.SHIFT_DOWN_MASK and so on.
for (int i = 0; i < keys.length; i++)
{
- parentInputMap.put(KeyStroke.getKeyStroke
- (((KeyStroke)keys[i]).getKeyCode(), convertModifiers
- (((KeyStroke)keys[i]).getModifiers())),
- (String)ancestorMap.get((KeyStroke)keys[i]));
+ KeyStroke stroke = (KeyStroke)keys[i];
+ String actionString = (String) ancestorMap.get(stroke);
- parentInputMap.put(KeyStroke.getKeyStroke
- (((KeyStroke)keys[i]).getKeyCode(),
- ((KeyStroke)keys[i]).getModifiers()),
- (String)ancestorMap.get((KeyStroke)keys[i]));
+ parentInputMap.put(KeyStroke.getKeyStroke(stroke.getKeyCode(),
+ stroke.getModifiers()),
+ actionString);
- parentActionMap.put
- ((String)ancestorMap.get((KeyStroke)keys[i]), new ActionListenerProxy
- (action, (String)ancestorMap.get((KeyStroke)keys[i])));
+ parentActionMap.put (actionString,
+ new ActionListenerProxy (action, actionString));
}
// Set the UI InputMap-ActionMap pair to be the parents of the
@@ -383,8 +475,8 @@ public class BasicTableUI
*/
public void actionPerformed (ActionEvent e)
{
- ListSelectionModel rowModel = table.getSelectionModel();
- ListSelectionModel colModel = table.getColumnModel().getSelectionModel();
+ DefaultListSelectionModel rowModel = (DefaultListSelectionModel) table.getSelectionModel();
+ DefaultListSelectionModel colModel = (DefaultListSelectionModel) table.getColumnModel().getSelectionModel();
int rowLead = rowModel.getLeadSelectionIndex();
int rowMax = table.getModel().getRowCount() - 1;
@@ -392,74 +484,75 @@ public class BasicTableUI
int colLead = colModel.getLeadSelectionIndex();
int colMax = table.getModel().getColumnCount() - 1;
- if (e.getActionCommand().equals("selectPreviousRowExtendSelection"))
+ String command = e.getActionCommand();
+
+ if (command.equals("selectPreviousRowExtendSelection"))
{
rowModel.setLeadSelectionIndex(Math.max(rowLead - 1, 0));
colModel.setLeadSelectionIndex(colLead);
}
- else if (e.getActionCommand().equals("selectLastColumn"))
+ else if (command.equals("selectLastColumn"))
{
- table.clearSelection();
rowModel.setSelectionInterval(rowLead, rowLead);
colModel.setSelectionInterval(colMax, colMax);
}
- else if (e.getActionCommand().equals("startEditing"))
+ else if (command.equals("startEditing"))
{
if (table.isCellEditable(rowLead, colLead))
table.editCellAt(rowLead,colLead);
}
- else if (e.getActionCommand().equals("selectFirstRowExtendSelection"))
+ else if (command.equals("selectFirstRowExtendSelection"))
{
rowModel.setLeadSelectionIndex(0);
colModel.setLeadSelectionIndex(colLead);
}
- else if (e.getActionCommand().equals("selectFirstColumn"))
+ else if (command.equals("selectFirstColumn"))
{
rowModel.setSelectionInterval(rowLead, rowLead);
colModel.setSelectionInterval(0, 0);
}
- else if (e.getActionCommand().equals("selectFirstColumnExtendSelection"))
+ else if (command.equals("selectFirstColumnExtendSelection"))
{
colModel.setLeadSelectionIndex(0);
rowModel.setLeadSelectionIndex(rowLead);
- }
- else if (e.getActionCommand().equals("selectLastRow"))
+ }
+ else if (command.equals("selectLastRow"))
{
rowModel.setSelectionInterval(rowMax,rowMax);
colModel.setSelectionInterval(colLead, colLead);
}
- else if (e.getActionCommand().equals("selectNextRowExtendSelection"))
+ else if (command.equals("selectNextRowExtendSelection"))
{
rowModel.setLeadSelectionIndex(Math.min(rowLead + 1, rowMax));
colModel.setLeadSelectionIndex(colLead);
}
- else if (e.getActionCommand().equals("selectFirstRow"))
+ else if (command.equals("selectFirstRow"))
{
rowModel.setSelectionInterval(0,0);
colModel.setSelectionInterval(colLead, colLead);
}
- else if (e.getActionCommand().equals("selectNextColumnExtendSelection"))
+ else if (command.equals("selectNextColumnExtendSelection"))
{
colModel.setLeadSelectionIndex(Math.min(colLead + 1, colMax));
rowModel.setLeadSelectionIndex(rowLead);
}
- else if (e.getActionCommand().equals("selectLastColumnExtendSelection"))
+ else if (command.equals("selectLastColumnExtendSelection"))
{
colModel.setLeadSelectionIndex(colMax);
rowModel.setLeadSelectionIndex(rowLead);
}
- else if (e.getActionCommand().equals("selectPreviousColumnExtendSelection"))
+ else if (command.equals("selectPreviousColumnExtendSelection"))
{
colModel.setLeadSelectionIndex(Math.max(colLead - 1, 0));
rowModel.setLeadSelectionIndex(rowLead);
}
- else if (e.getActionCommand().equals("selectNextRow"))
+ else if (command.equals("selectNextRow"))
{
rowModel.setSelectionInterval(Math.min(rowLead + 1, rowMax),
Math.min(rowLead + 1, rowMax));
colModel.setSelectionInterval(colLead,colLead);
}
- else if (e.getActionCommand().equals("scrollUpExtendSelection"))
+ else if (command.equals("scrollUpExtendSelection"))
{
int target;
if (rowLead == getFirstVisibleRowIndex())
@@ -472,13 +565,13 @@ public class BasicTableUI
rowModel.setLeadSelectionIndex(target);
colModel.setLeadSelectionIndex(colLead);
}
- else if (e.getActionCommand().equals("selectPreviousRow"))
+ else if (command.equals("selectPreviousRow"))
{
rowModel.setSelectionInterval(Math.max(rowLead - 1, 0),
Math.max(rowLead - 1, 0));
colModel.setSelectionInterval(colLead,colLead);
}
- else if (e.getActionCommand().equals("scrollRightChangeSelection"))
+ else if (command.equals("scrollRightChangeSelection"))
{
int target;
if (colLead == getLastVisibleColumnIndex())
@@ -491,13 +584,13 @@ public class BasicTableUI
colModel.setSelectionInterval(target, target);
rowModel.setSelectionInterval(rowLead, rowLead);
}
- else if (e.getActionCommand().equals("selectPreviousColumn"))
+ else if (command.equals("selectPreviousColumn"))
{
rowModel.setSelectionInterval(rowLead,rowLead);
colModel.setSelectionInterval(Math.max(colLead - 1, 0),
Math.max(colLead - 1, 0));
}
- else if (e.getActionCommand().equals("scrollLeftChangeSelection"))
+ else if (command.equals("scrollLeftChangeSelection"))
{
int target;
if (colLead == getFirstVisibleColumnIndex())
@@ -510,11 +603,11 @@ public class BasicTableUI
colModel.setSelectionInterval(target, target);
rowModel.setSelectionInterval(rowLead, rowLead);
}
- else if (e.getActionCommand().equals("clearSelection"))
+ else if (command.equals("clearSelection"))
{
table.clearSelection();
}
- else if (e.getActionCommand().equals("cancel"))
+ else if (command.equals("cancel"))
{
// FIXME: implement other parts of "cancel" like undo-ing last
// selection. Right now it just calls editingCancelled if
@@ -522,10 +615,10 @@ public class BasicTableUI
if (table.isEditing())
table.editingCanceled(new ChangeEvent("cancel"));
}
- else if (e.getActionCommand().equals("selectNextRowCell")
- || e.getActionCommand().equals("selectPreviousRowCell")
- || e.getActionCommand().equals("selectNextColumnCell")
- || e.getActionCommand().equals("selectPreviousColumnCell"))
+ else if (command.equals("selectNextRowCell")
+ || command.equals("selectPreviousRowCell")
+ || command.equals("selectNextColumnCell")
+ || command.equals("selectPreviousColumnCell"))
{
// If nothing is selected, select the first cell in the table
if (table.getSelectedRowCount() == 0 &&
@@ -561,13 +654,13 @@ public class BasicTableUI
// when you get to the edges of the table.
if (!multColsSelected && !multRowsSelected)
{
- if (e.getActionCommand().indexOf("Column") != -1)
+ if (command.indexOf("Column") != -1)
advanceSingleSelection(colModel, colMax, rowModel, rowMax,
- (e.getActionCommand().equals
+ (command.equals
("selectPreviousColumnCell")));
else
advanceSingleSelection(rowModel, rowMax, colModel, colMax,
- (e.getActionCommand().equals
+ (command.equals
("selectPreviousRowCell")));
return;
}
@@ -588,25 +681,25 @@ public class BasicTableUI
// If there are multiple rows and columns selected, select the next
// cell and wrap at the edges of the selection.
- if (e.getActionCommand().indexOf("Column") != -1)
+ if (command.indexOf("Column") != -1)
advanceMultipleSelection(colModel, colMinSelected, colMaxSelected,
rowModel, rowMinSelected, rowMaxSelected,
- (e.getActionCommand().equals
+ (command.equals
("selectPreviousColumnCell")), true);
else
advanceMultipleSelection(rowModel, rowMinSelected, rowMaxSelected,
colModel, colMinSelected, colMaxSelected,
- (e.getActionCommand().equals
+ (command.equals
("selectPreviousRowCell")), false);
}
- else if (e.getActionCommand().equals("selectNextColumn"))
+ else if (command.equals("selectNextColumn"))
{
rowModel.setSelectionInterval(rowLead,rowLead);
colModel.setSelectionInterval(Math.min(colLead + 1, colMax),
Math.min(colLead + 1, colMax));
}
- else if (e.getActionCommand().equals("scrollLeftExtendSelection"))
+ else if (command.equals("scrollLeftExtendSelection"))
{
int target;
if (colLead == getFirstVisibleColumnIndex())
@@ -619,7 +712,7 @@ public class BasicTableUI
colModel.setLeadSelectionIndex(target);
rowModel.setLeadSelectionIndex(rowLead);
}
- else if (e.getActionCommand().equals("scrollDownChangeSelection"))
+ else if (command.equals("scrollDownChangeSelection"))
{
int target;
if (rowLead == getLastVisibleRowIndex())
@@ -632,7 +725,7 @@ public class BasicTableUI
rowModel.setSelectionInterval(target, target);
colModel.setSelectionInterval(colLead, colLead);
}
- else if (e.getActionCommand().equals("scrollRightExtendSelection"))
+ else if (command.equals("scrollRightExtendSelection"))
{
int target;
if (colLead == getLastVisibleColumnIndex())
@@ -645,16 +738,16 @@ public class BasicTableUI
colModel.setLeadSelectionIndex(target);
rowModel.setLeadSelectionIndex(rowLead);
}
- else if (e.getActionCommand().equals("selectAll"))
+ else if (command.equals("selectAll"))
{
table.selectAll();
}
- else if (e.getActionCommand().equals("selectLastRowExtendSelection"))
+ else if (command.equals("selectLastRowExtendSelection"))
{
rowModel.setLeadSelectionIndex(rowMax);
colModel.setLeadSelectionIndex(colLead);
}
- else if (e.getActionCommand().equals("scrollDownExtendSelection"))
+ else if (command.equals("scrollDownExtendSelection"))
{
int target;
if (rowLead == getLastVisibleRowIndex())
@@ -666,8 +759,8 @@ public class BasicTableUI
rowModel.setLeadSelectionIndex(target);
colModel.setLeadSelectionIndex(colLead);
- }
- else if (e.getActionCommand().equals("scrollUpChangeSelection"))
+ }
+ else if (command.equals("scrollUpChangeSelection"))
{
int target;
if (rowLead == getFirstVisibleRowIndex())
@@ -680,22 +773,119 @@ public class BasicTableUI
rowModel.setSelectionInterval(target, target);
colModel.setSelectionInterval(colLead, colLead);
}
+ else if (command.equals("selectNextRowChangeLead"))
+ {
+ if (rowModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
+ {
+ // just "selectNextRow"
+ rowModel.setSelectionInterval(Math.min(rowLead + 1, rowMax),
+ Math.min(rowLead + 1, rowMax));
+ colModel.setSelectionInterval(colLead,colLead);
+ }
+ else
+ rowModel.moveLeadSelectionIndex(Math.min(rowLead + 1, rowMax));
+ }
+ else if (command.equals("selectPreviousRowChangeLead"))
+ {
+ if (rowModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
+ {
+ // just selectPreviousRow
+ rowModel.setSelectionInterval(Math.max(rowLead - 1, 0),
+ Math.min(rowLead -1, 0));
+ colModel.setSelectionInterval(colLead,colLead);
+ }
+ else
+ rowModel.moveLeadSelectionIndex(Math.max(rowLead - 1, 0));
+ }
+ else if (command.equals("selectNextColumnChangeLead"))
+ {
+ if (colModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
+ {
+ // just selectNextColumn
+ rowModel.setSelectionInterval(rowLead,rowLead);
+ colModel.setSelectionInterval(Math.min(colLead + 1, colMax),
+ Math.min(colLead + 1, colMax));
+ }
+ else
+ colModel.moveLeadSelectionIndex(Math.min(colLead + 1, colMax));
+ }
+ else if (command.equals("selectPreviousColumnChangeLead"))
+ {
+ if (colModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
+ {
+ // just selectPreviousColumn
+ rowModel.setSelectionInterval(rowLead,rowLead);
+ colModel.setSelectionInterval(Math.max(colLead - 1, 0),
+ Math.max(colLead - 1, 0));
+
+ }
+ else
+ colModel.moveLeadSelectionIndex(Math.max(colLead - 1, 0));
+ }
+ else if (command.equals("addToSelection"))
+ {
+ if (!table.isEditing())
+ {
+ int oldRowAnchor = rowModel.getAnchorSelectionIndex();
+ int oldColAnchor = colModel.getAnchorSelectionIndex();
+ rowModel.addSelectionInterval(rowLead, rowLead);
+ colModel.addSelectionInterval(colLead, colLead);
+ rowModel.setAnchorSelectionIndex(oldRowAnchor);
+ colModel.setAnchorSelectionIndex(oldColAnchor);
+ }
+ }
+ else if (command.equals("extendTo"))
+ {
+ rowModel.setSelectionInterval(rowModel.getAnchorSelectionIndex(),
+ rowLead);
+ colModel.setSelectionInterval(colModel.getAnchorSelectionIndex(),
+ colLead);
+ }
+ else if (command.equals("toggleAndAnchor"))
+ {
+ if (rowModel.isSelectedIndex(rowLead))
+ rowModel.removeSelectionInterval(rowLead, rowLead);
+ else
+ rowModel.addSelectionInterval(rowLead, rowLead);
+
+ if (colModel.isSelectedIndex(colLead))
+ colModel.removeSelectionInterval(colLead, colLead);
+ else
+ colModel.addSelectionInterval(colLead, colLead);
+
+ rowModel.setAnchorSelectionIndex(rowLead);
+ colModel.setAnchorSelectionIndex(colLead);
+ }
else
{
// If we're here that means we bound this TableAction class
// to a keyboard input but we either want to ignore that input
// or we just haven't implemented its action yet.
+
+ // Uncomment the following line to print the names of unused bindings
+ // when their keys are pressed
+
+ // System.out.println ("not implemented: "+e.getActionCommand());
}
- if (table.isEditing() && e.getActionCommand() != "startEditing")
- table.editingCanceled(new ChangeEvent("update"));
- table.repaint();
-
+ // Any commands whose keyStrokes should be used by the Editor should not
+ // cause editing to be stopped: ie, the SPACE sends "addToSelection" but
+ // if the table is in editing mode, the space should not cause us to stop
+ // editing because it should be used by the Editor.
+ if (table.isEditing() && command != "startEditing"
+ && command != "addToSelection")
+ table.editingStopped(new ChangeEvent("update"));
+
table.scrollRectToVisible
(table.getCellRect(rowModel.getLeadSelectionIndex(),
colModel.getLeadSelectionIndex(), false));
+ table.repaint();
}
+ /**
+ * Returns the column index of the first visible column.
+ * @return the column index of the first visible column.
+ */
int getFirstVisibleColumnIndex()
{
ComponentOrientation or = table.getComponentOrientation();
@@ -922,10 +1112,19 @@ public class BasicTableUI
protected void installListeners()
{
- table.addFocusListener(focusListener);
+ if (focusListener == null)
+ focusListener = createFocusListener();
+ table.addFocusListener(focusListener);
+ if (keyListener == null)
+ keyListener = createKeyListener();
table.addKeyListener(keyListener);
+ if (mouseInputListener == null)
+ mouseInputListener = createMouseInputListener();
table.addMouseListener(mouseInputListener);
table.addMouseMotionListener(mouseInputListener);
+ if (propertyChangeListener == null)
+ propertyChangeListener = new PropertyChangeHandler();
+ table.addPropertyChangeListener(propertyChangeListener);
}
protected void uninstallDefaults()
@@ -950,6 +1149,7 @@ public class BasicTableUI
protected void uninstallKeyboardActions()
{
+ // TODO: Implement this properly.
}
protected void uninstallListeners()
@@ -958,13 +1158,13 @@ public class BasicTableUI
table.removeKeyListener(keyListener);
table.removeMouseListener(mouseInputListener);
table.removeMouseMotionListener(mouseInputListener);
+ table.removePropertyChangeListener(propertyChangeListener);
+ propertyChangeListener = null;
}
public void installUI(JComponent comp)
{
table = (JTable)comp;
- focusListener = createFocusListener();
- mouseInputListener = createMouseInputListener();
installDefaults();
installKeyboardActions();
installListeners();
@@ -977,6 +1177,60 @@ public class BasicTableUI
uninstallDefaults();
}
+ /**
+ * Paints a single cell in the table.
+ *
+ * @param g The graphics context to paint in
+ * @param row The row number to paint
+ * @param col The column number to paint
+ * @param bounds The bounds of the cell to paint, assuming a coordinate
+ * system beginning at <code>(0,0)</code> in the upper left corner of the
+ * table
+ * @param rend A cell renderer to paint with
+ * @param data The data to provide to the cell renderer
+ * @param rowLead The lead selection for the rows of the table.
+ * @param colLead The lead selection for the columns of the table.
+ */
+ void paintCell(Graphics g, int row, int col, Rectangle bounds,
+ TableCellRenderer rend, TableModel data,
+ int rowLead, int colLead)
+ {
+ boolean rowSelAllowed = table.getRowSelectionAllowed();
+ boolean colSelAllowed = table.getColumnSelectionAllowed();
+ boolean isSel = false;
+ if (rowSelAllowed && colSelAllowed || !rowSelAllowed && !colSelAllowed)
+ isSel = table.isCellSelected(row, col);
+ else
+ isSel = table.isRowSelected(row) && table.getRowSelectionAllowed()
+ || table.isColumnSelected(col) && table.getColumnSelectionAllowed();
+
+ // Determine the focused cell. The focused cell is the cell at the
+ // leadSelectionIndices of the row and column selection model.
+ ListSelectionModel rowSel = table.getSelectionModel();
+ ListSelectionModel colSel = table.getColumnModel().getSelectionModel();
+ boolean hasFocus = table.hasFocus() && table.isEnabled()
+ && rowSel.getLeadSelectionIndex() == row
+ && colSel.getLeadSelectionIndex() == col;
+
+ Component comp = rend.getTableCellRendererComponent(table,
+ data.getValueAt(row, col),
+ isSel, hasFocus, row, col);
+
+ rendererPane.paintComponent(g, comp, table, bounds);
+
+ // FIXME: this is manual painting of the Caret, why doesn't the
+ // JTextField take care of this itself?
+ if (comp instanceof JTextField)
+ {
+ Rectangle oldClip = g.getClipBounds();
+ g.translate(bounds.x, bounds.y);
+ g.clipRect(0, 0, bounds.width, bounds.height);
+ ((JTextField)comp).getCaret().paint(g);
+ g.translate(-bounds.x, -bounds.y);
+ g.setClip(oldClip);
+ }
+ }
+
public void paint(Graphics gfx, JComponent ignored)
{
int ncols = table.getColumnCount();
@@ -1002,40 +1256,24 @@ public class BasicTableUI
y = y0;
TableColumn col = cols.getColumn(c);
int width = col.getWidth();
- int modelCol = col.getModelIndex();
-
+ int halfGapWidth = gap.width / 2;
+ int halfGapHeight = gap.height / 2;
for (int r = 0; r < nrows && y < ymax; ++r)
{
- Rectangle bounds = new Rectangle(x, y, width, height);
- if (bounds.intersects(clip))
- {
- TableCellRenderer rend = table.getCellRenderer(r, c);
- Component comp = table.prepareRenderer(rend, r, c);
- gfx.translate(x, y);
- comp.setBounds(new Rectangle(0, 0, width, height));
- // Set correct border on cell renderer.
- // Only the lead selection cell gets a border
- if (comp instanceof JComponent)
- {
- if (table.getSelectionModel().getLeadSelectionIndex() == r
- && table.getColumnModel().getSelectionModel().
- getLeadSelectionIndex() == c)
- ((JComponent) comp).setBorder(highlightCellBorder);
- else
- ((JComponent) comp).setBorder(cellBorder);
- }
- comp.paint(gfx);
- if (comp instanceof JTextField)
- ((JTextField)comp).getCaret().paint(gfx);
- gfx.translate(-x, -y);
+ Rectangle bounds = new Rectangle(x + halfGapWidth,
+ y + halfGapHeight + 1,
+ width - gap.width + 1,
+ height - gap.height);
+ if (bounds.intersects(clip))
+ {
+ paintCell(gfx, r, c, bounds, table.getCellRenderer(r, c),
+ table.getModel(),
+ table.getSelectionModel().getLeadSelectionIndex(),
+ table.getColumnModel().getSelectionModel().getLeadSelectionIndex());
}
- y += height;
- if (gap != null)
- y += gap.height;
+ y += height;
}
x += width;
- if (gap != null)
- x += gap.width;
}
// tighten up the x and y max bounds
@@ -1044,7 +1282,7 @@ public class BasicTableUI
Color grid = table.getGridColor();
- // paint vertical grid lines
+ // paint vertical grid lines
if (grid != null && table.getShowVerticalLines())
{
x = x0;
@@ -1053,9 +1291,7 @@ public class BasicTableUI
boolean paintedLine = false;
for (int c = 0; c < ncols && x < xmax; ++c)
{
- x += cols.getColumn(c).getWidth();;
- if (gap != null)
- x += gap.width;
+ x += cols.getColumn(c).getWidth();
gfx.drawLine(x, y0, x, ymax);
paintedLine = true;
}
@@ -1072,8 +1308,6 @@ public class BasicTableUI
for (int r = 0; r < nrows && y < ymax; ++r)
{
y += height;
- if (gap != null)
- y += gap.height;
gfx.drawLine(x0, y, xmax, y);
paintedLine = true;
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java
index 97b0ccb6ee6..36854e07fe0 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java
@@ -39,11 +39,16 @@ exception statement from your version. */
package javax.swing.plaf.basic;
+import java.beans.PropertyChangeEvent;
+
import javax.swing.JComponent;
+import javax.swing.JTextArea;
+import javax.swing.UIDefaults;
import javax.swing.plaf.ComponentUI;
import javax.swing.text.Element;
import javax.swing.text.PlainView;
import javax.swing.text.View;
+import javax.swing.text.WrappedPlainView;
public class BasicTextAreaUI extends BasicTextUI
{
@@ -54,15 +59,55 @@ public class BasicTextAreaUI extends BasicTextUI
public BasicTextAreaUI()
{
+ // Nothing to do here.
}
+ /**
+ * Create the view. Returns a WrappedPlainView if the text area
+ * has lineWrap set to true, otherwise returns a PlainView. If
+ * lineWrap is true has to check whether the wrap style is word
+ * or character and return an appropriate WrappedPlainView.
+ *
+ * @param elem the element to create a View for
+ * @return an appropriate View for the element
+ */
public View create(Element elem)
{
- return new PlainView(elem);
+ JTextArea comp = (JTextArea)getComponent();
+ if (comp.getLineWrap())
+ {
+ if (comp.getWrapStyleWord())
+ return new WrappedPlainView(elem, true);
+ else
+ return new WrappedPlainView(elem, false);
+ }
+ else
+ return new PlainView(elem);
}
+ /**
+ * Returns the prefix for entries in the {@link UIDefaults} table.
+ *
+ * @return "TextArea"
+ */
protected String getPropertyPrefix()
{
return "TextArea";
}
+
+ /**
+ * Receives notification whenever one of the text component's bound
+ * properties changes. This changes the view to WrappedPlainView
+ * if setLineWrap(true) is called, and back to PlainView if
+ * setLineWrap(false) is called.
+ *
+ * @param ev the property change event
+ */
+ protected void propertyChange(PropertyChangeEvent ev)
+ {
+ JTextArea comp = (JTextArea)getComponent();
+ if (ev.getPropertyName() == "lineWrap"
+ || ev.getPropertyName() == "wrapStyleWord")
+ modelChanged();
+ }
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java
index a300446c262..4e2ca9f93df 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java
@@ -41,6 +41,7 @@ package javax.swing.plaf.basic;
import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
+import javax.swing.UIDefaults;
import javax.swing.plaf.ComponentUI;
import javax.swing.text.Element;
import javax.swing.text.FieldView;
@@ -63,6 +64,11 @@ public class BasicTextFieldUI extends BasicTextUI
return new BasicTextFieldUI();
}
+ /**
+ * Returns the prefix for entries in the {@link UIDefaults} table.
+ *
+ * @return "TextField"
+ */
protected String getPropertyPrefix()
{
return "TextField";
@@ -73,8 +79,22 @@ public class BasicTextFieldUI extends BasicTextUI
super.installUI(c);
}
+ /**
+ * Receives notification whenever one of the text component's bound
+ * properties changes. Here we check for the editable and enabled
+ * properties and adjust the background color accordingly.
+ *
+ * @param event the property change event
+ */
protected void propertyChange(PropertyChangeEvent event)
{
- // Does nothing by default.
+ if (event.getPropertyName().equals("editable"))
+ {
+ boolean editable = ((Boolean) event.getNewValue()).booleanValue();
+ if (editable)
+ textComponent.setBackground(background);
+ else
+ textComponent.setBackground(inactiveBackground);
+ }
}
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java
index 55d908e1b88..decbed56829 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java
@@ -38,10 +38,18 @@ exception statement from your version. */
package javax.swing.plaf.basic;
+import java.awt.Color;
+
import javax.swing.JComponent;
+import javax.swing.JTextPane;
+import javax.swing.plaf.ColorUIResource;
+import javax.swing.UIDefaults;
import javax.swing.plaf.ComponentUI;
import javax.swing.text.Element;
import javax.swing.text.PlainView;
+import javax.swing.text.Style;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
import javax.swing.text.View;
public class BasicTextPaneUI extends BasicEditorPaneUI
@@ -61,8 +69,32 @@ public class BasicTextPaneUI extends BasicEditorPaneUI
return new PlainView(elem);
}
+ /**
+ * Returns the prefix for entries in the {@link UIDefaults} table.
+ *
+ * @return "TextPane"
+ */
protected String getPropertyPrefix()
{
return "TextPane";
}
+
+ /**
+ * Installs this UI on the specified <code>JTextPane</code>. This calls the
+ * super implementation and then adds a default style to the text pane.
+ *
+ * @param c the text pane to install the UI to
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ JTextPane tp = (JTextPane) c;
+ Style defaultStyle = tp.getStyle(StyleContext.DEFAULT_STYLE);
+ defaultStyle.addAttribute(StyleConstants.Foreground,
+ new ColorUIResource(Color.BLACK));
+ defaultStyle.addAttribute(StyleConstants.FontFamily, "Serif");
+ defaultStyle.addAttribute(StyleConstants.Italic, Boolean.FALSE);
+ defaultStyle.addAttribute(StyleConstants.Bold, Boolean.FALSE);
+ defaultStyle.addAttribute(StyleConstants.FontSize, new Integer(12));
+ }
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java
index 91ccb0056bb..b9de92640c8 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.swing.plaf.basic;
+import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
@@ -54,6 +55,8 @@ import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
+import javax.swing.LookAndFeel;
+import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
@@ -73,7 +76,6 @@ import javax.swing.text.Element;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
import javax.swing.text.Keymap;
-import javax.swing.text.PlainView;
import javax.swing.text.Position;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
@@ -92,11 +94,11 @@ public abstract class BasicTextUI extends TextUI
/**
* A {@link DefaultCaret} that implements {@link UIResource}.
*/
- public static class BasicCaret extends DefaultCaret
- implements UIResource
+ public static class BasicCaret extends DefaultCaret implements UIResource
{
public BasicCaret()
{
+ // Nothing to do here.
}
}
@@ -108,6 +110,7 @@ public abstract class BasicTextUI extends TextUI
{
public BasicHighlighter()
{
+ // Nothing to do here.
}
}
@@ -241,7 +244,7 @@ public abstract class BasicTextUI extends TextUI
public void paint(Graphics g, Shape s)
{
if (view != null)
- view.paint(g, s);
+ view.paint(g, s);
}
@@ -252,10 +255,10 @@ public abstract class BasicTextUI extends TextUI
*
* This is delegated to the real root view.
*
- * @param pos the position of the character in the model
+ * @param position the position of the character in the model
* @param a the area that is occupied by the view
- * @param bias either {@link Position.Bias.Forward} or
- * {@link Position.Bias.Backward} depending on the preferred
+ * @param bias either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward} depending on the preferred
* direction bias. If <code>null</code> this defaults to
* <code>Position.Bias.Forward</code>
*
@@ -327,12 +330,41 @@ public abstract class BasicTextUI extends TextUI
{
view.changedUpdate(ev, shape, vf);
}
+
+ /**
+ * Returns the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction <code>d</code>.
+ *
+ * @param c the text component
+ * @param pos the document position
+ * @param b the bias for <code>pos</code>
+ * @param d the direction, must be either {@link SwingConstants#NORTH},
+ * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
+ * {@link SwingConstants#EAST}
+ * @param biasRet an array of {@link Position.Bias} that can hold at least
+ * one element, which is filled with the bias of the return position
+ * on method exit
+ *
+ * @return the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction
+ * <code>d</code>
+ *
+ * @throws BadLocationException if <code>pos</code> is not a valid offset in
+ * the document model
+ */
+ public int getNextVisualPositionFrom(JTextComponent c, int pos,
+ Position.Bias b, int d,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ return view.getNextVisualPositionFrom(c, pos, b, d, biasRet);
+ }
}
/**
* Receives notifications when properties of the text component change.
*/
- class UpdateHandler implements PropertyChangeListener
+ class PropertyChangeHandler implements PropertyChangeListener
{
/**
* Notifies when a property of the text component changes.
@@ -342,10 +374,12 @@ public abstract class BasicTextUI extends TextUI
public void propertyChange(PropertyChangeEvent event)
{
if (event.getPropertyName().equals("document"))
- {
+ {
// Document changed.
- modelChanged();
- }
+ modelChanged();
+ }
+
+ BasicTextUI.this.propertyChange(event);
}
}
@@ -364,11 +398,10 @@ public abstract class BasicTextUI extends TextUI
*/
public void changedUpdate(DocumentEvent ev)
{
- Dimension size = textComponent.getSize();
- rootView.changedUpdate(ev, new Rectangle(0, 0, size.width, size.height),
+ rootView.changedUpdate(ev, getVisibleEditorRect(),
rootView.getViewFactory());
}
-
+
/**
* Notification about a document insert event.
*
@@ -376,12 +409,8 @@ public abstract class BasicTextUI extends TextUI
*/
public void insertUpdate(DocumentEvent ev)
{
- Dimension size = textComponent.getSize();
- rootView.insertUpdate(ev, new Rectangle(0, 0, size.width, size.height),
+ rootView.insertUpdate(ev, getVisibleEditorRect(),
rootView.getViewFactory());
- int caretPos = textComponent.getCaretPosition();
- if (caretPos >= ev.getOffset())
- textComponent.setCaretPosition(caretPos + ev.getLength());
}
/**
@@ -391,12 +420,8 @@ public abstract class BasicTextUI extends TextUI
*/
public void removeUpdate(DocumentEvent ev)
{
- Dimension size = textComponent.getSize();
- rootView.removeUpdate(ev, new Rectangle(0, 0, size.width, size.height),
+ rootView.removeUpdate(ev, getVisibleEditorRect(),
rootView.getViewFactory());
- int caretPos = textComponent.getCaretPosition();
- if (caretPos >= ev.getOffset())
- textComponent.setCaretPosition(ev.getOffset());
}
}
@@ -419,16 +444,29 @@ public abstract class BasicTextUI extends TextUI
/**
* Receives notification when the model changes.
*/
- UpdateHandler updateHandler = new UpdateHandler();
+ PropertyChangeHandler updateHandler = new PropertyChangeHandler();
/** The DocumentEvent handler. */
DocumentHandler documentHandler = new DocumentHandler();
/**
+ * The standard background color. This is the color which is used to paint
+ * text in enabled text components.
+ */
+ Color background;
+
+ /**
+ * The inactive background color. This is the color which is used to paint
+ * text in disabled text components.
+ */
+ Color inactiveBackground;
+
+ /**
* Creates a new <code>BasicTextUI</code> instance.
*/
public BasicTextUI()
{
+ // Nothing to do here.
}
/**
@@ -506,14 +544,20 @@ public abstract class BasicTextUI extends TextUI
textComponent.setHighlighter(createHighlighter());
String prefix = getPropertyPrefix();
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- textComponent.setBackground(defaults.getColor(prefix + ".background"));
- textComponent.setForeground(defaults.getColor(prefix + ".foreground"));
- textComponent.setMargin(defaults.getInsets(prefix + ".margin"));
- textComponent.setBorder(defaults.getBorder(prefix + ".border"));
- textComponent.setFont(defaults.getFont(prefix + ".font"));
-
- caret.setBlinkRate(defaults.getInt(prefix + ".caretBlinkRate"));
+ LookAndFeel.installColorsAndFont(textComponent, prefix + ".background",
+ prefix + ".foreground", prefix + ".font");
+ LookAndFeel.installBorder(textComponent, prefix + ".border");
+ textComponent.setMargin(UIManager.getInsets(prefix + ".margin"));
+
+ caret.setBlinkRate(UIManager.getInt(prefix + ".caretBlinkRate"));
+
+ // Fetch the colors for enabled/disabled text components.
+ background = UIManager.getColor(prefix + ".background");
+ inactiveBackground = UIManager.getColor(prefix + ".inactiveBackground");
+ textComponent.setDisabledTextColor
+ (UIManager.getColor(prefix + ".inactiveForeground"));
+ textComponent.setSelectedTextColor(UIManager.getColor(prefix + ".selectionForeground"));
+ textComponent.setSelectionColor(UIManager.getColor(prefix + ".selectionBackground"));
}
/**
@@ -704,6 +748,7 @@ public abstract class BasicTextUI extends TextUI
protected void uninstallListeners()
{
textComponent.removeFocusListener(focuslistener);
+ textComponent.getDocument().removeDocumentListener(documentHandler);
}
/**
@@ -757,6 +802,18 @@ public abstract class BasicTextUI extends TextUI
}
/**
+ * Returns the minimum size for text components. This returns the size
+ * of the component's insets.
+ *
+ * @return the minimum size for text components
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ Insets i = c.getInsets();
+ return new Dimension(i.left + i.right, i.top + i.bottom);
+ }
+
+ /**
* Paints the text component.
*
* @param g the <code>Graphics</code> context to paint to
@@ -776,10 +833,10 @@ public abstract class BasicTextUI extends TextUI
{
Caret caret = textComponent.getCaret();
Highlighter highlighter = textComponent.getHighlighter();
-
+
if (textComponent.isOpaque())
paintBackground(g);
-
+
if (highlighter != null
&& textComponent.getSelectionStart() != textComponent.getSelectionEnd())
highlighter.paint(g);
@@ -797,8 +854,10 @@ public abstract class BasicTextUI extends TextUI
*/
protected void paintBackground(Graphics g)
{
- g.setColor(textComponent.getBackground());
- g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight());
+ // This method does nothing. All the background filling is done by the
+ // ComponentUI update method. However, the method is called by paint
+ // to provide a way for subclasses to draw something different (e.g.
+ // background images etc) on the background.
}
/**
@@ -885,10 +944,10 @@ public abstract class BasicTextUI extends TextUI
/**
* Maps a position in the document into the coordinate space of the View.
* The output rectangle usually reflects the font height but has a width
- * of zero. A bias of {@link Position.Bias.Forward} is used in this method.
+ * of zero. A bias of {@link Position.Bias#Forward} is used in this method.
*
+ * @param t the text component
* @param pos the position of the character in the model
- * @param a the area that is occupied by the view
*
* @return a rectangle that gives the location of the document position
* inside the view coordinate space
@@ -908,10 +967,10 @@ public abstract class BasicTextUI extends TextUI
* The output rectangle usually reflects the font height but has a width
* of zero.
*
+ * @param t the text component
* @param pos the position of the character in the model
- * @param a the area that is occupied by the view
- * @param bias either {@link Position.Bias.Forward} or
- * {@link Position.Bias.Backward} depending on the preferred
+ * @param bias either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward} depending on the preferred
* direction bias. If <code>null</code> this defaults to
* <code>Position.Bias.Forward</code>
*
@@ -957,7 +1016,7 @@ public abstract class BasicTextUI extends TextUI
*/
public int viewToModel(JTextComponent t, Point pt, Position.Bias[] biasReturn)
{
- return 0; // FIXME: Implement me.
+ return rootView.viewToModel(pt.x, pt.y, getVisibleEditorRect(), biasReturn);
}
/**
@@ -999,16 +1058,17 @@ public abstract class BasicTextUI extends TextUI
*/
protected Rectangle getVisibleEditorRect()
{
+ JTextComponent textComponent = getComponent();
int width = textComponent.getWidth();
int height = textComponent.getHeight();
if (width <= 0 || height <= 0)
- return null;
+ return new Rectangle(0, 0, 0, 0);
Insets insets = textComponent.getInsets();
return new Rectangle(insets.left, insets.top,
- width - insets.left + insets.right,
- height - insets.top + insets.bottom);
+ width - insets.left - insets.right,
+ height - insets.top - insets.bottom);
}
/**
@@ -1020,6 +1080,8 @@ public abstract class BasicTextUI extends TextUI
{
rootView.setView(view);
view.setParent(rootView);
+ textComponent.revalidate();
+ textComponent.repaint();
}
/**
@@ -1043,4 +1105,17 @@ public abstract class BasicTextUI extends TextUI
View view = factory.create(elem);
setView(view);
}
+
+ /**
+ * Receives notification whenever one of the text component's bound
+ * properties changes. This default implementation does nothing.
+ * It is a hook that enables subclasses to react to property changes
+ * on the text component.
+ *
+ * @param ev the property change event
+ */
+ protected void propertyChange(PropertyChangeEvent ev)
+ {
+ // The default implementation does nothing.
+ }
}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java
index 9106b0b6673..896ea0c89dc 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java
@@ -38,7 +38,13 @@ exception statement from your version. */
package javax.swing.plaf.basic;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import javax.swing.AbstractButton;
import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
import javax.swing.plaf.ComponentUI;
public class BasicToggleButtonUI extends BasicButtonUI
@@ -58,5 +64,62 @@ public class BasicToggleButtonUI extends BasicButtonUI
{
return "ToggleButton.";
}
-}
+ /**
+ * Paint the component, which is an {@link AbstractButton}, according to
+ * its current state.
+ *
+ * @param g The graphics context to paint with
+ * @param c The component to paint the state of
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ AbstractButton b = (AbstractButton) c;
+
+ Rectangle tr = new Rectangle();
+ Rectangle ir = new Rectangle();
+ Rectangle vr = new Rectangle();
+
+ Font f = c.getFont();
+
+ g.setFont(f);
+
+ if (b.isBorderPainted())
+ SwingUtilities.calculateInnerArea(b, vr);
+ else
+ vr = SwingUtilities.getLocalBounds(b);
+ String text = SwingUtilities.layoutCompoundLabel(c, g.getFontMetrics(f),
+ b.getText(),
+ currentIcon(b),
+ b.getVerticalAlignment(),
+ b.getHorizontalAlignment(),
+ b.getVerticalTextPosition(),
+ b.getHorizontalTextPosition(),
+ vr, ir, tr,
+ b.getIconTextGap()
+ + defaultTextShiftOffset);
+
+ if ((b.getModel().isArmed() && b.getModel().isPressed())
+ || b.isSelected())
+ paintButtonPressed(g, b);
+
+ paintIcon(g, b, ir);
+ if (text != null)
+ paintText(g, b, tr, text);
+ if (b.isFocusOwner() && b.isFocusPainted())
+ paintFocus(g, b, vr, tr, ir);
+ }
+
+ /**
+ * Paints the icon for the toggle button. This delegates to
+ * {@link BasicButtonUI#paintIcon(Graphics, JComponent, Rectangle)}.
+ *
+ * @param g the graphics context
+ * @param b the button to paint the icon for
+ * @param iconRect the area allocated for the icon
+ */
+ protected void paintIcon(Graphics g, AbstractButton b, Rectangle iconRect)
+ {
+ super.paintIcon(g, b, iconRect);
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java
index db29fdca583..79cf0b0c213 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java
@@ -43,7 +43,6 @@ import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JSeparator;
-import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
@@ -73,9 +72,7 @@ public class BasicToolBarSeparatorUI extends BasicSeparatorUI
*/
protected void installDefaults(JSeparator s)
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- size = defaults.getDimension("ToolBar.separatorSize");
+ size = UIManager.getDimension("ToolBar.separatorSize");
}
/**
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java
index 8be89efcfa6..ef4ed835f86 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java
@@ -65,10 +65,11 @@ import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JToolBar;
+import javax.swing.KeyStroke;
+import javax.swing.LookAndFeel;
import javax.swing.RootPaneContainer;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
-import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.MouseInputListener;
@@ -133,6 +134,26 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
protected FocusListener toolBarFocusListener;
/**
+ * @deprecated since JDK1.3.
+ */
+ protected KeyStroke leftKey;
+
+ /**
+ * @deprecated since JDK1.3.
+ */
+ protected KeyStroke rightKey;
+
+ /**
+ * @deprecated since JDK1.3.
+ */
+ protected KeyStroke upKey;
+
+ /**
+ * @deprecated since JDK1.3.
+ */
+ protected KeyStroke downKey;
+
+ /**
* The floating window that is responsible for holding the JToolBar when it
* is dragged outside of its original parent.
*/
@@ -566,18 +587,16 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
*/
protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ LookAndFeel.installBorder(toolBar, "ToolBar.border");
+ LookAndFeel.installColorsAndFont(toolBar, "ToolBar.background",
+ "ToolBar.foreground", "ToolBar.font");
- toolBar.setBorder(new ToolBarBorder());
- toolBar.setBackground(defaults.getColor("ToolBar.background"));
- toolBar.setForeground(defaults.getColor("ToolBar.foreground"));
- toolBar.setFont(defaults.getFont("ToolBar.font"));
+ dockingBorderColor = UIManager.getColor("ToolBar.dockingForeground");
+ dockingColor = UIManager.getColor("ToolBar.dockingBackground");
- dockingBorderColor = defaults.getColor("ToolBar.dockingForeground");
- dockingColor = defaults.getColor("ToolBar.dockingBackground");
-
- floatingBorderColor = defaults.getColor("ToolBar.floatingForeground");
- floatingColor = defaults.getColor("ToolBar.floatingBackground");
+ floatingBorderColor = UIManager.getColor("ToolBar.floatingForeground");
+ floatingColor = UIManager.getColor("ToolBar.floatingBackground");
+ setRolloverBorders(toolBar.isRollover());
}
/**
@@ -591,10 +610,8 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
/**
* This method installs listeners for the JToolBar.
- *
- * @param toolbar The JToolBar to register listeners for.
*/
- protected void installListeners(JToolBar toolbar)
+ protected void installListeners()
{
dockingListener = createDockingListener();
toolBar.addMouseListener(dockingListener);
@@ -694,7 +711,7 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
toolBar.setOpaque(true);
installDefaults();
installComponents();
- installListeners(toolBar);
+ installListeners();
installKeyboardActions();
}
}
@@ -1000,6 +1017,7 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
*/
public void mouseMoved(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -1030,13 +1048,15 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
}
origin = new Point(0, 0);
- SwingUtilities.convertPointToScreen(ssd, toolBar);
+ if (toolBar.isShowing())
+ SwingUtilities.convertPointToScreen(ssd, toolBar);
if (! (SwingUtilities.getAncestorOfClass(Window.class, toolBar) instanceof UIResource))
// Need to know who keeps the toolBar if it gets dragged back into it.
origParent = toolBar.getParent();
-
- SwingUtilities.convertPointToScreen(origin, toolBar);
+
+ if (toolBar.isShowing())
+ SwingUtilities.convertPointToScreen(origin, toolBar);
isDragging = true;
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java
index b7a08aa728e..5cec2e33365 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java
@@ -1,5 +1,5 @@
/* BasicToolTipUI.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,20 +39,18 @@ 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.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
+import java.awt.Toolkit;
import javax.swing.JComponent;
import javax.swing.JToolTip;
+import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
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.ToolTipUI;
@@ -61,58 +59,12 @@ import javax.swing.plaf.ToolTipUI;
*/
public class BasicToolTipUI extends ToolTipUI
{
- /** The default Border around the JToolTip. */
- private static Border defaultBorder = new Border()
- {
- // FIXME: This needs to go into Basic Look and Feel
- // defaults.
- /**
- * This method returns the border insets.
- *
- * @param c The Component to find Border insets for.
- *
- * @return The Border insets.
- */
- public Insets getBorderInsets(Component c)
- {
- return new Insets(4, 4, 4, 4);
- }
+ /** The shared instance of BasicToolTipUI used for all ToolTips. */
+ private static BasicToolTipUI shared;
- /**
- * This method returns whether the border is opaque.
- *
- * @return Whether the border is opaque.
- */
- public boolean isBorderOpaque()
- {
- return false;
- }
-
- /**
- * This method paints the border.
- *
- * @param c The Component to paint this border around.
- * @param g The Graphics object to paint with.
- * @param x The x coordinate to start painting at.
- * @param y The y coordinate to start painting at.
- * @param w The width of the Component.
- * @param h The height of the Component.
- */
- public void paintBorder(Component c, Graphics g, int x, int y, int w,
- int h)
- {
- Color saved = g.getColor();
- g.setColor(Color.BLACK);
-
- g.drawRect(0, 0, w - 1, h - 1);
-
- g.setColor(saved);
- }
- };
-
- /** The shared instance of BasicToolTipUI used for all ToolTips. */
- private static BasicToolTipUI shared;
+ /** The tooltip's text */
+ private String text;
/**
* Creates a new BasicToolTipUI object.
@@ -124,7 +76,7 @@ public class BasicToolTipUI extends ToolTipUI
/**
* This method creates a new BasicToolTip UI for the given
- * JComponent.
+ * JComponent.
*
* @param c The JComponent to create a UI for.
*
@@ -132,9 +84,9 @@ public class BasicToolTipUI extends ToolTipUI
*/
public static ComponentUI createUI(JComponent c)
{
- if (shared == null)
- shared = new BasicToolTipUI();
- return shared;
+ if (shared == null)
+ shared = new BasicToolTipUI();
+ return shared;
}
/**
@@ -171,12 +123,16 @@ public class BasicToolTipUI extends ToolTipUI
public Dimension getPreferredSize(JComponent c)
{
JToolTip tip = (JToolTip) c;
+ FontMetrics fm;
+ Toolkit g = tip.getToolkit();
+ text = tip.getTipText();
+
Rectangle vr = new Rectangle();
Rectangle ir = new Rectangle();
Rectangle tr = new Rectangle();
Insets insets = tip.getInsets();
- FontMetrics fm = tip.getToolkit().getFontMetrics(tip.getFont());
- SwingUtilities.layoutCompoundLabel(tip, fm, tip.getTipText(), null,
+ fm = g.getFontMetrics(tip.getFont());
+ SwingUtilities.layoutCompoundLabel(tip, fm, text, null,
SwingConstants.CENTER,
SwingConstants.CENTER,
SwingConstants.CENTER,
@@ -192,11 +148,9 @@ public class BasicToolTipUI extends ToolTipUI
*/
protected void installDefaults(JComponent c)
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- c.setBackground(defaults.getColor("ToolTip.background"));
- c.setForeground(defaults.getColor("ToolTip.foreground"));
- c.setFont(defaults.getFont("ToolTip.font"));
- c.setBorder(defaultBorder);
+ LookAndFeel.installColorsAndFont(c, "ToolTip.background",
+ "ToolTip.foreground", "ToolTip.font");
+ LookAndFeel.installBorder(c, "ToolTip.border");
}
/**
@@ -206,6 +160,7 @@ public class BasicToolTipUI extends ToolTipUI
*/
protected void installListeners(JComponent c)
{
+ // TODO: Implement this properly.
}
/**
@@ -231,6 +186,7 @@ public class BasicToolTipUI extends ToolTipUI
JToolTip tip = (JToolTip) c;
String text = tip.getTipText();
+ Toolkit t = tip.getToolkit();
if (text == null)
return;
@@ -238,19 +194,19 @@ public class BasicToolTipUI extends ToolTipUI
vr = SwingUtilities.calculateInnerArea(tip, vr);
Rectangle ir = new Rectangle();
Rectangle tr = new Rectangle();
- FontMetrics fm = tip.getToolkit().getFontMetrics(tip.getFont());
- SwingUtilities.layoutCompoundLabel(tip, fm, tip.getTipText(), null,
+ FontMetrics fm = t.getFontMetrics(tip.getFont());
+ int ascent = fm.getAscent();
+ SwingUtilities.layoutCompoundLabel(tip, fm, text, null,
SwingConstants.CENTER,
SwingConstants.CENTER,
SwingConstants.CENTER,
SwingConstants.CENTER, vr, ir, tr, 0);
-
Color saved = g.getColor();
g.setColor(Color.BLACK);
- g.drawString(text, vr.x, vr.y + fm.getAscent());
+ g.drawString(text, vr.x, vr.y + ascent);
- g.setColor(saved);
+ g.setColor(saved);
}
/**
@@ -273,6 +229,7 @@ public class BasicToolTipUI extends ToolTipUI
*/
protected void uninstallListeners(JComponent c)
{
+ // TODO: Implement this properly.
}
/**
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java
index 6f714a39cb2..e967cd424fc 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java
@@ -44,6 +44,7 @@ import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
+import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
@@ -62,6 +63,7 @@ import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
+import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.AbstractAction;
@@ -76,6 +78,7 @@ import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.KeyStroke;
+import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIDefaults;
@@ -89,6 +92,7 @@ import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
+import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.InputMapUIResource;
import javax.swing.plaf.TreeUI;
@@ -96,7 +100,6 @@ import javax.swing.text.Caret;
import javax.swing.tree.AbstractLayoutCache;
import javax.swing.tree.DefaultTreeCellEditor;
import javax.swing.tree.DefaultTreeCellRenderer;
-import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.FixedHeightLayoutCache;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
@@ -110,11 +113,11 @@ import javax.swing.tree.TreeSelectionModel;
* the Basic look and feel.
*
* @see javax.swing.JTree
- * @author Sascha Brawer (brawer@dandelis.ch)
+ *
* @author Lillian Angel (langel@redhat.com)
+ * @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class BasicTreeUI
- extends TreeUI
+public class BasicTreeUI extends TreeUI
{
/** Collapse Icon for the tree. */
protected transient Icon collapsedIcon;
@@ -136,9 +139,6 @@ public class BasicTreeUI
*/
protected int totalChildIndent;
- /** Minimum preferred size. */
- protected Dimension preferredMinsize;
-
/** Index of the row that was last selected. */
protected int lastSelectedRow;
@@ -174,6 +174,9 @@ public class BasicTreeUI
/** Size needed to completely display all the nodes. */
protected Dimension preferredSize;
+
+ /** Minimum size needed to completely display all the nodes. */
+ protected Dimension preferredMinSize;
/** Is the preferredSize valid? */
protected boolean validCachedPreferredSize;
@@ -223,38 +226,38 @@ public class BasicTreeUI
/** Set to true if the editor has a different size than the renderer. */
protected boolean editorHasDifferentSize;
-
+
/** The action listener for the editor's Timer. */
- private Timer editorTimer = new EditorUpdateTimer();
+ Timer editorTimer = new EditorUpdateTimer();
/** The new value of the node after editing. */
- private Object newVal;
+ Object newVal;
/** The action bound to KeyStrokes. */
- private TreeAction action;
+ TreeAction action;
/** Boolean to keep track of editing. */
- private boolean isEditing;
+ boolean isEditing;
+
+ /** The bounds of the current cell. */
+ Rectangle bounds;
+
+ /** The current path of the visible nodes in the tree. */
+ TreePath currentVisiblePath;
+
+ /** The gap between the icon and text. */
+ int gap = 4;
/** Listeners */
private PropertyChangeListener propertyChangeListener;
-
private FocusListener focusListener;
-
private TreeSelectionListener treeSelectionListener;
-
- private MouseInputListener mouseInputListener;
-
+ private MouseListener mouseListener;
private KeyListener keyListener;
-
private PropertyChangeListener selectionModelPropertyChangeListener;
-
private ComponentListener componentListener;
-
- private CellEditorListener cellEditorListener;
-
+ CellEditorListener cellEditorListener;
private TreeExpansionListener treeExpansionListener;
-
private TreeModelListener treeModelListener;
/**
@@ -262,6 +265,7 @@ public class BasicTreeUI
*/
public BasicTreeUI()
{
+ validCachedPreferredSize = false;
drawingCache = new Hashtable();
nodeDimensions = createNodeDimensions();
configureLayoutCache();
@@ -269,7 +273,7 @@ public class BasicTreeUI
propertyChangeListener = createPropertyChangeListener();
focusListener = createFocusListener();
treeSelectionListener = createTreeSelectionListener();
- mouseInputListener = new MouseInputHandler(null, null, null);
+ mouseListener = createMouseListener();
keyListener = createKeyListener();
selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener();
componentListener = createComponentListener();
@@ -331,7 +335,7 @@ public class BasicTreeUI
*
* @return the indent value for the left child.
*/
- public int getLeftChildIndent(int newAmount)
+ public int getLeftChildIndent()
{
return leftChildIndent;
}
@@ -456,7 +460,6 @@ public class BasicTreeUI
protected void setCellRenderer(TreeCellRenderer tcr)
{
currentCellRenderer = tcr;
- tree.setCellRenderer(tcr);
updateRenderer();
}
@@ -625,14 +628,13 @@ public class BasicTreeUI
{
Object cell = path.getLastPathComponent();
- TreeModel mod = tree.getModel();
- if (mod != null)
+ if (treeModel != null)
{
- Object root = mod.getRoot();
+ Object root = treeModel.getRoot();
+
if (!tree.isRootVisible() && tree.isExpanded(new TreePath(root)))
root = getNextNode(root);
-
- Point loc = getCellLocation(0, 0, tree, mod, cell, root);
+ Point loc = getCellLocation(0, 0, tree, treeModel, cell, root);
return getCellBounds(loc.x, loc.y, cell);
}
}
@@ -650,21 +652,11 @@ public class BasicTreeUI
*/
public TreePath getPathForRow(JTree tree, int row)
{
- TreeModel mod = tree.getModel();
- if (mod != null)
+ if (treeModel != null && currentVisiblePath != null)
{
- Object node = mod.getRoot();
- if (!tree.isRootVisible()
- && tree.isExpanded(new TreePath(getPathToRoot(node, 0))))
- node = getNextNode(node);
-
- for (int i = 0; i < row; i++)
- node = getNextVisibleNode(node);
-
- if (node == null)
- return null;
-
- return new TreePath(getPathToRoot(node, 0));
+ Object[] nodes = currentVisiblePath.getPath();
+ if (row < nodes.length)
+ return new TreePath(getPathToRoot(nodes[row], 0));
}
return null;
}
@@ -683,17 +675,20 @@ public class BasicTreeUI
*/
public int getRowForPath(JTree tree, TreePath path)
{
- int row = path.getPathCount();
- if (tree.isVisible(path))
- return row;
-
- path = path.getParentPath();
- while (row > 0 && !tree.isVisible(path))
+ int row = 0;
+ Object dest = path.getLastPathComponent();
+ int rowCount = getRowCount(tree);
+ if (currentVisiblePath != null)
{
- path = path.getParentPath();
- row--;
+ Object[] nodes = currentVisiblePath.getPath();
+ while (row < rowCount)
+ {
+ if (dest.equals(nodes[row]))
+ return row;
+ row++;
+ }
}
- return row;
+ return -1;
}
/**
@@ -705,22 +700,10 @@ public class BasicTreeUI
*/
public int getRowCount(JTree tree)
{
- TreeModel mod = tree.getModel();
- int count = 0;
- if (mod != null)
- {
- Object node = mod.getRoot();
- if (!tree.isRootVisible()
- && tree.isExpanded(new TreePath((getPathToRoot(node, 0)))))
- node = getNextNode(node);
-
- while (node != null)
- {
- count++;
- node = getNextVisibleNode(node);
- }
- }
- return count;
+ updateCurrentVisiblePath();
+ if (currentVisiblePath != null)
+ return currentVisiblePath.getPathCount();
+ return 0;
}
/**
@@ -739,9 +722,6 @@ public class BasicTreeUI
*/
public TreePath getClosestPathForLocation(JTree tree, int x, int y)
{
- // FIXME: what if root is hidden? should not depend on (0,0)
- // should start counting rows from where root is.
-
int row = Math.round(y / getRowHeight());
TreePath path = getPathForRow(tree, row);
@@ -828,7 +808,7 @@ public class BasicTreeUI
*/
protected void prepareForUIInstall()
{
- // FIXME: not implemented
+ // TODO: Implement this properly.
}
/**
@@ -837,7 +817,7 @@ public class BasicTreeUI
*/
protected void completeUIInstall()
{
- // FIXME: not implemented
+ // TODO: Implement this properly.
}
/**
@@ -846,7 +826,7 @@ public class BasicTreeUI
*/
protected void completeUIUninstall()
{
- // FIXME: not implemented
+ // TODO: Implement this properly.
}
/**
@@ -854,7 +834,10 @@ public class BasicTreeUI
*/
protected void installComponents()
{
- // FIXME: not implemented
+ currentCellRenderer = createDefaultCellRenderer();
+ rendererPane = createCellRendererPane();
+ createdRenderer = true;
+ setCellRenderer(currentCellRenderer);
}
/**
@@ -865,8 +848,7 @@ public class BasicTreeUI
*/
protected AbstractLayoutCache.NodeDimensions createNodeDimensions()
{
- // FIXME: not implemented
- return null;
+ return new NodeDimensionsHandler();
}
/**
@@ -1035,7 +1017,7 @@ public class BasicTreeUI
tree.removePropertyChangeListener(propertyChangeListener);
tree.removeFocusListener(focusListener);
tree.removeTreeSelectionListener(treeSelectionListener);
- tree.removeMouseListener(mouseInputListener);
+ tree.removeMouseListener(mouseListener);
tree.removeKeyListener(keyListener);
tree.removePropertyChangeListener(selectionModelPropertyChangeListener);
tree.removeComponentListener(componentListener);
@@ -1044,9 +1026,8 @@ public class BasicTreeUI
TreeCellEditor tce = tree.getCellEditor();
if (tce != null)
tce.removeCellEditorListener(cellEditorListener);
- TreeModel tm = tree.getModel();
- if (tm != null)
- tm.removeTreeModelListener(treeModelListener);
+ if (treeModel != null)
+ treeModel.removeTreeModelListener(treeModelListener);
}
/**
@@ -1054,6 +1035,7 @@ public class BasicTreeUI
*/
protected void uninstallKeyboardActions()
{
+ // TODO: Implement this properly.
}
/**
@@ -1061,7 +1043,10 @@ public class BasicTreeUI
*/
protected void uninstallComponents()
{
- // FIXME: not implemented
+ currentCellRenderer = null;
+ rendererPane = null;
+ createdRenderer = false;
+ setCellRenderer(currentCellRenderer);
}
/**
@@ -1072,8 +1057,7 @@ public class BasicTreeUI
*/
protected int getVerticalLegBuffer()
{
- // FIXME: not implemented
- return 0;
+ return getRowHeight() / 2;
}
/**
@@ -1085,17 +1069,17 @@ public class BasicTreeUI
*/
protected int getHorizontalLegBuffer()
{
- // FIXME: not implemented
- return 0;
+ return rightChildIndent / 2;
}
/**
* Make all the nodes that are expanded in JTree expanded in LayoutCache. This
- * invokes update ExpandedDescendants with the root path.
+ * invokes updateExpandedDescendants with the root path.
*/
protected void updateLayoutCacheExpandedNodes()
{
- // FIXME: not implemented
+ if (treeModel != null)
+ updateExpandedDescendants(new TreePath(treeModel.getRoot()));
}
/**
@@ -1108,7 +1092,9 @@ public class BasicTreeUI
*/
protected void updateExpandedDescendants(TreePath path)
{
- // FIXME: not implemented
+ Enumeration expanded = tree.getExpandedDescendants(path);
+ while (expanded.hasMoreElements())
+ treeState.setExpandedState(((TreePath) expanded.nextElement()), true);
}
/**
@@ -1128,7 +1114,7 @@ public class BasicTreeUI
*/
protected void updateDepthOffset()
{
- // FIXME: not implemented
+ depthOffset += getVerticalLegBuffer();
}
/**
@@ -1148,7 +1134,15 @@ public class BasicTreeUI
*/
protected void updateRenderer()
{
- // FIXME: not implemented
+ if (tree != null)
+ {
+ if(tree.getCellRenderer() == null)
+ {
+ if(currentCellRenderer == null)
+ currentCellRenderer = createDefaultCellRenderer();
+ tree.setCellRenderer(currentCellRenderer);
+ }
+ }
}
/**
@@ -1166,19 +1160,36 @@ public class BasicTreeUI
*/
protected void updateSize()
{
- // FIXME: not implemented
+ preferredSize = null;
+ updateCachedPreferredSize();
+ tree.treeDidChange();
}
/**
* Updates the <code>preferredSize</code> instance variable, which is
- * returned from <code>getPreferredSize()</code>. For left to right
- * orientations, the size is determined from the current AbstractLayoutCache.
- * For RTL orientations, the preferred size becomes the width minus the
- * minimum x position.
+ * returned from <code>getPreferredSize()</code>.
*/
protected void updateCachedPreferredSize()
{
- // FIXME: not implemented
+ int maxWidth = 0;
+ boolean isLeaf = false;
+ if (currentVisiblePath != null)
+ {
+ Object[] path = currentVisiblePath.getPath();
+ for (int i = 0; i < path.length; i++)
+ {
+ TreePath curr = new TreePath(getPathToRoot(path[i], 0));
+ Rectangle bounds = getPathBounds(tree, curr);
+ if (treeModel != null)
+ isLeaf = treeModel.isLeaf(path[i]);
+ if (!isLeaf && hasControlIcons())
+ bounds.width += getCurrentControlIcon(curr).getIconWidth();
+ maxWidth = Math.max(maxWidth, bounds.x + bounds.width);
+ }
+ preferredSize = new Dimension(maxWidth, (getRowHeight() * path.length));
+ }
+ else preferredSize = new Dimension(0, 0);
+ validCachedPreferredSize = true;
}
/**
@@ -1189,7 +1200,9 @@ public class BasicTreeUI
*/
protected void pathWasExpanded(TreePath path)
{
- // FIXME: not implemented
+ validCachedPreferredSize = false;
+ tree.revalidate();
+ tree.repaint();
}
/**
@@ -1197,28 +1210,28 @@ public class BasicTreeUI
*/
protected void pathWasCollapsed(TreePath path)
{
- // FIXME: not implemented
+ validCachedPreferredSize = false;
+ tree.revalidate();
+ tree.repaint();
}
/**
* Install all defaults for the tree.
- *
- * @param tree
- * is the JTree to install defaults for
*/
- protected void installDefaults(JTree tree)
+ protected void installDefaults()
{
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
-
- tree.setFont(defaults.getFont("Tree.font"));
- tree.setForeground(defaults.getColor("Tree.foreground"));
- tree.setBackground(defaults.getColor("Tree.background"));
+ LookAndFeel.installColorsAndFont(tree, "Tree.background",
+ "Tree.foreground", "Tree.font");
tree.setOpaque(true);
- rightChildIndent = defaults.getInt("Tree.rightChildIndent");
- leftChildIndent = defaults.getInt("Tree.leftChildIndent");
- setRowHeight(defaults.getInt("Tree.rowHeight"));
+ rightChildIndent = UIManager.getInt("Tree.rightChildIndent");
+ leftChildIndent = UIManager.getInt("Tree.leftChildIndent");
+ setRowHeight(UIManager.getInt("Tree.rowHeight"));
+ tree.setRowHeight(UIManager.getInt("Tree.rowHeight"));
tree.requestFocusInWindow(false);
+ tree.setScrollsOnExpand(UIManager.getBoolean("Tree.scrollsOnExpand"));
+ setExpandedIcon(UIManager.getIcon("Tree.expandedIcon"));
+ setCollapsedIcon(UIManager.getIcon("Tree.collapsedIcon"));
}
/**
@@ -1229,7 +1242,7 @@ public class BasicTreeUI
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
InputMap focusInputMap = (InputMap) defaults.get("Tree.focusInputMap");
InputMapUIResource parentInputMap = new InputMapUIResource();
- ActionMap parentActionMap = new ActionMap();
+ ActionMap parentActionMap = new ActionMapUIResource();
action = new TreeAction();
Object keys[] = focusInputMap.allKeys();
@@ -1308,7 +1321,7 @@ public class BasicTreeUI
tree.addPropertyChangeListener(propertyChangeListener);
tree.addFocusListener(focusListener);
tree.addTreeSelectionListener(treeSelectionListener);
- tree.addMouseListener(mouseInputListener);
+ tree.addMouseListener(mouseListener);
tree.addKeyListener(keyListener);
tree.addPropertyChangeListener(selectionModelPropertyChangeListener);
tree.addComponentListener(componentListener);
@@ -1325,37 +1338,36 @@ public class BasicTreeUI
*/
public void installUI(JComponent c)
{
- super.installUI(c);
- installDefaults((JTree) c);
tree = (JTree) c;
+ prepareForUIInstall();
+ super.installUI(c);
+ installDefaults();
- currentCellRenderer = createDefaultCellRenderer();
- rendererPane = createCellRendererPane();
- createdRenderer = true;
-
+ installComponents();
+ installKeyboardActions();
+ installListeners();
+
setCellEditor(createDefaultCellEditor());
createdCellEditor = true;
isEditing = false;
-
+
TreeModel mod = tree.getModel();
setModel(mod);
- tree.setRootVisible(true);
if (mod != null)
- tree.expandPath(new TreePath(mod.getRoot()));
+ {
+ TreePath path = new TreePath(mod.getRoot());
+ if (!tree.isExpanded(path))
+ toggleExpandState(path);
+ }
treeSelectionModel = tree.getSelectionModel();
- installKeyboardActions();
- installListeners();
completeUIInstall();
}
/**
* Uninstall the defaults for the tree
- *
- * @param tree
- * to uninstall defaults for
*/
- protected void uninstallDefaults(JTree tree)
+ protected void uninstallDefaults()
{
tree.setFont(null);
tree.setForeground(null);
@@ -1370,10 +1382,12 @@ public class BasicTreeUI
*/
public void uninstallUI(JComponent c)
{
- uninstallDefaults((JTree) c);
+ prepareForUIUninstall();
+ uninstallDefaults();
uninstallKeyboardActions();
uninstallListeners();
tree = null;
+ uninstallComponents();
completeUIUninstall();
}
@@ -1393,20 +1407,16 @@ public class BasicTreeUI
public void paint(Graphics g, JComponent c)
{
JTree tree = (JTree) c;
-
- TreeModel mod = tree.getModel();
-
- if (mod != null)
+ if (currentVisiblePath == null)
+ updateCurrentVisiblePath();
+
+ if (currentVisiblePath != null && treeModel != null)
{
- Object root = mod.getRoot();
-
- if (!tree.isRootVisible())
- tree.expandPath(new TreePath(root));
-
- paintRecursive(g, 0, 0, 0, 0, tree, mod, root);
-
+ Object root = treeModel.getRoot();
+ paintRecursive(g, 0, 0, 0, tree, treeModel, root);
+
if (hasControlIcons())
- paintControlIcons(g, 0, 0, 0, 0, tree, mod, root);
+ paintControlIcons(g, 0, 0, 0, tree, treeModel, root);
}
}
@@ -1420,7 +1430,19 @@ public class BasicTreeUI
*/
protected void ensureRowsAreVisible(int beginRow, int endRow)
{
- // FIXME: not implemented
+ if (beginRow < endRow)
+ {
+ int temp = endRow;
+ endRow = beginRow;
+ beginRow = temp;
+ }
+
+ for (int i = beginRow; i < endRow; i++)
+ {
+ TreePath path = getPathForRow(tree, i);
+ if (!tree.isVisible(path))
+ tree.makeVisible(path);
+ }
}
/**
@@ -1431,7 +1453,7 @@ public class BasicTreeUI
*/
public void setPreferredMinSize(Dimension newSize)
{
- // FIXME: not implemented
+ preferredMinSize = newSize;
}
/**
@@ -1441,8 +1463,7 @@ public class BasicTreeUI
*/
public Dimension getPreferredMinSize()
{
- // FIXME: not implemented
- return null;
+ return preferredMinSize;
}
/**
@@ -1472,28 +1493,10 @@ public class BasicTreeUI
*/
public Dimension getPreferredSize(JComponent c, boolean checkConsistancy)
{
- // FIXME: checkConsistancy not implemented, c not used
- TreeModel model = tree.getModel();
- int maxWidth = 0;
- int count = 0;
- if (model != null)
- {
- Object node = model.getRoot();
- if (node != null)
- {
- maxWidth = (int) (getCellBounds(0, 0, node).getWidth());
- while (node != null)
- {
- count++;
- Object nextNode = getNextVisibleNode(node);
- if (nextNode != null)
- maxWidth = Math.max(maxWidth,
- (int) (getCellBounds(0, 0, nextNode).getWidth()));
- node = nextNode;
- }
- }
- }
- return new Dimension(maxWidth, (getRowHeight() * count));
+ // FIXME: checkConsistancy not implemented, c not used
+ if(!validCachedPreferredSize)
+ updateCachedPreferredSize();
+ return preferredSize;
}
/**
@@ -1506,8 +1509,10 @@ public class BasicTreeUI
*/
public Dimension getMinimumSize(JComponent c)
{
- // FIXME: not implemented
- return getPreferredSize(c);
+ Dimension min = getPreferredMinSize();
+ if (min == null)
+ return new Dimension();
+ return min;
}
/**
@@ -1520,8 +1525,9 @@ public class BasicTreeUI
*/
public Dimension getMaximumSize(JComponent c)
{
- // FIXME: not implemented
- return getPreferredSize(c);
+ if (c instanceof JTree)
+ return ((JTree) c).getPreferredSize();
+ return new Dimension();
}
/**
@@ -1565,7 +1571,7 @@ public class BasicTreeUI
}
if (messageTree)
- tree.getModel().valueForPathChanged(tree.getLeadSelectionPath(), newVal);
+ treeModel.valueForPathChanged(tree.getLeadSelectionPath(), newVal);
}
/**
@@ -1584,7 +1590,7 @@ public class BasicTreeUI
int y;
if (event == null)
{
- Rectangle bounds = getPathBounds(tree, path);
+ bounds = getPathBounds(tree, path);
x = bounds.x;
y = bounds.y;
}
@@ -1600,6 +1606,7 @@ public class BasicTreeUI
{
editingPath = path;
editingRow = tree.getRowForPath(editingPath);
+
Object val = editingPath.getLastPathComponent();
cellEditor.addCellEditorListener(cellEditorListener);
stopEditingInCompleteEditing = false;
@@ -1613,6 +1620,8 @@ public class BasicTreeUI
editingComponent.getParent().validate();
tree.add(editingComponent.getParent());
editingComponent.getParent().validate();
+ validCachedPreferredSize = false;
+ tree.revalidate();
((JTextField) editingComponent).requestFocusInWindow(false);
editorTimer.start();
return true;
@@ -1634,7 +1643,8 @@ public class BasicTreeUI
protected void checkForClickInExpandControl(TreePath path, int mouseX,
int mouseY)
{
- // FIXME: not implemented
+ if (isLocationInExpandControl(path, mouseX, mouseY))
+ toggleExpandState(path);
}
/**
@@ -1655,8 +1665,18 @@ public class BasicTreeUI
protected boolean isLocationInExpandControl(TreePath path, int mouseX,
int mouseY)
{
- // FIXME: not implemented
- return false;
+ boolean cntlClick = false;
+ int row = getRowForPath(tree, path);
+
+ if (!isLeaf(row))
+ {
+ bounds = getPathBounds(tree, path);
+
+ if (hasControlIcons() && (mouseX < bounds.x)
+ && (mouseX > (bounds.x - getCurrentControlIcon(path).getIconWidth() - gap)))
+ cntlClick = true;
+ }
+ return cntlClick;
}
/**
@@ -1672,7 +1692,7 @@ public class BasicTreeUI
*/
protected void handleExpandControlClick(TreePath path, int mouseX, int mouseY)
{
- // FIXME: not implemented
+ toggleExpandState(path);
}
/**
@@ -1686,7 +1706,11 @@ public class BasicTreeUI
*/
protected void toggleExpandState(TreePath path)
{
- // FIXME: not implemented
+ if (tree.isExpanded(path))
+ tree.collapsePath(path);
+ else
+ tree.expandPath(path);
+ updateCurrentVisiblePath();
}
/**
@@ -1700,8 +1724,8 @@ public class BasicTreeUI
*/
protected boolean isToggleSelectionEvent(MouseEvent event)
{
- // FIXME: not implemented
- return false;
+ return (tree.getSelectionModel().getSelectionMode() ==
+ TreeSelectionModel.SINGLE_TREE_SELECTION);
}
/**
@@ -1715,8 +1739,8 @@ public class BasicTreeUI
*/
protected boolean isMultiSelectEvent(MouseEvent event)
{
- // FIXME: not implemented
- return false;
+ return (tree.getSelectionModel().getSelectionMode() ==
+ TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
}
/**
@@ -1731,8 +1755,7 @@ public class BasicTreeUI
*/
protected boolean isToggleEvent(MouseEvent event)
{
- // FIXME: not implemented
- return false;
+ return true;
}
/**
@@ -1749,7 +1772,29 @@ public class BasicTreeUI
*/
protected void selectPathForEvent(TreePath path, MouseEvent event)
{
- // FIXME: not implemented
+ if (isToggleSelectionEvent(event))
+ {
+ if (tree.isPathSelected(path))
+ tree.removeSelectionPath(path);
+ else
+ {
+ tree.addSelectionPath(path);
+ tree.setAnchorSelectionPath(path);
+ }
+ }
+ else if (isMultiSelectEvent(event))
+ {
+ TreePath anchor = tree.getAnchorSelectionPath();
+ if (anchor != null)
+ {
+ int aRow = getRowForPath(tree, anchor);
+ tree.addSelectionInterval(aRow, getRowForPath(tree, path));
+ }
+ else
+ tree.addSelectionPath(path);
+ }
+ else
+ tree.addSelectionPath(path);
}
/**
@@ -1766,7 +1811,7 @@ public class BasicTreeUI
return true;
Object node = pathForRow.getLastPathComponent();
- return tree.getModel().isLeaf(node);
+ return treeModel.isLeaf(node);
}
/**
@@ -1800,9 +1845,9 @@ public class BasicTreeUI
(new TreeTraverseAction(0, "")).actionPerformed(e);
else if (e.getActionCommand().equals("selectAll"))
{
- TreePath[] paths = new TreePath[tree.getRowCount()];
+ TreePath[] paths = new TreePath[tree.getVisibleRowCount()];
- Object curr = getNextVisibleNode(tree.getModel().getRoot());
+ Object curr = getNextVisibleNode(treeModel.getRoot());
int i = 0;
while (curr != null && i < paths.length)
{
@@ -1822,13 +1867,8 @@ public class BasicTreeUI
{
Object last = lead.getLastPathComponent();
TreePath path = new TreePath(getPathToRoot(last, 0));
- if (!tree.getModel().isLeaf(last))
- {
- if (tree.isExpanded(path))
- tree.collapsePath(path);
- else
- tree.expandPath(path);
- }
+ if (!treeModel.isLeaf(last))
+ toggleExpandState(path);
}
}
else if (e.getActionCommand().equals("clearSelection"))
@@ -1920,8 +1960,7 @@ public class BasicTreeUI
/**
* Updates the preferred size when scrolling, if necessary.
*/
- public class ComponentHandler
- extends ComponentAdapter
+ public class ComponentHandler extends ComponentAdapter
implements ActionListener
{
/**
@@ -1937,6 +1976,7 @@ public class BasicTreeUI
*/
public ComponentHandler()
{
+ // Nothing to do here.
}
/**
@@ -1947,6 +1987,7 @@ public class BasicTreeUI
*/
public void componentMoved(ComponentEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -1955,6 +1996,7 @@ public class BasicTreeUI
*/
protected void startTimer()
{
+ // TODO: Implement this properly.
}
/**
@@ -1976,21 +2018,22 @@ public class BasicTreeUI
*/
public void actionPerformed(ActionEvent ae)
{
+ // TODO: Implement this properly.
}
- }// ComponentHandler
+ }
/**
* Listener responsible for getting cell editing events and updating the tree
* accordingly.
*/
- public class CellEditorHandler
- implements CellEditorListener
+ public class CellEditorHandler implements CellEditorListener
{
/**
* Constructor
*/
public CellEditorHandler()
{
+ // Nothing to do here.
}
/**
@@ -2023,6 +2066,9 @@ public class BasicTreeUI
isEditing = false;
tree.requestFocusInWindow(false);
editorTimer.stop();
+ validCachedPreferredSize = false;
+ tree.revalidate();
+ tree.repaint();
}
/**
@@ -2051,6 +2097,8 @@ public class BasicTreeUI
tree.requestFocusInWindow(false);
editorTimer.stop();
isEditing = false;
+ validCachedPreferredSize = false;
+ tree.revalidate();
tree.repaint();
}
}// CellEditorHandler
@@ -2066,6 +2114,7 @@ public class BasicTreeUI
*/
public FocusHandler()
{
+ // Nothing to do here.
}
/**
@@ -2077,6 +2126,7 @@ public class BasicTreeUI
*/
public void focusGained(FocusEvent e)
{
+ // TODO: Implement this properly.
}
/**
@@ -2088,8 +2138,9 @@ public class BasicTreeUI
*/
public void focusLost(FocusEvent e)
{
+ // TODO: Implement this properly.
}
- }// FocusHandler
+ }
/**
* This is used to get multiple key down events to appropriately genereate
@@ -2109,6 +2160,7 @@ public class BasicTreeUI
*/
public KeyHandler()
{
+ // Nothing to do here.
}
/**
@@ -2122,6 +2174,7 @@ public class BasicTreeUI
*/
public void keyTyped(KeyEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -2132,6 +2185,7 @@ public class BasicTreeUI
*/
public void keyPressed(KeyEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -2142,22 +2196,22 @@ public class BasicTreeUI
*/
public void keyReleased(KeyEvent e)
{
+ // TODO: What should be done here, if anything?
}
- }// KeyHandler
+ }
/**
* MouseListener is responsible for updating the selection based on mouse
* events.
*/
- public class MouseHandler
- extends MouseAdapter
- implements MouseMotionListener
+ public class MouseHandler extends MouseAdapter implements MouseMotionListener
{
/**
* Constructor
*/
public MouseHandler()
{
+ // Nothing to do here.
}
/**
@@ -2168,6 +2222,57 @@ public class BasicTreeUI
*/
public void mousePressed(MouseEvent e)
{
+ Point click = e.getPoint();
+ TreePath path = getClosestPathForLocation(tree, click.x, click.y);
+
+ if (path != null)
+ {
+ bounds = getPathBounds(tree, path);
+ int row = getRowForPath(tree, path);
+ boolean cntlClick = isLocationInExpandControl(path, click.x, click.y);
+
+ boolean isLeaf = isLeaf(row);
+
+ TreeCellRenderer tcr = getCellRenderer();
+ Icon icon;
+ if (isLeaf)
+ icon = UIManager.getIcon("Tree.leafIcon");
+ else if (tree.isExpanded(path))
+ icon = UIManager.getIcon("Tree.openIcon");
+ else
+ icon = UIManager.getIcon("Tree.closedIcon");
+
+ if (tcr instanceof DefaultTreeCellRenderer)
+ {
+ Icon tmp = ((DefaultTreeCellRenderer) tcr).getIcon();
+ if (tmp != null)
+ icon = tmp;
+ }
+
+ // add gap*2 for the space before and after the text
+ if (icon != null)
+ bounds.width += icon.getIconWidth() + gap*2;
+
+ boolean inBounds = bounds.contains(click.x, click.y);
+ if ((inBounds || cntlClick) && tree.isVisible(path))
+ {
+ if (inBounds)
+ {
+ selectPath(tree, path);
+ if (e.getClickCount() == 2 && !isLeaf(row))
+ toggleExpandState(path);
+ }
+
+ if (cntlClick)
+ {
+ handleExpandControlClick(path, click.x, click.y);
+ if (cellEditor != null)
+ cellEditor.cancelCellEditing();
+ }
+ else if (tree.isEditable())
+ startEditing(path, e);
+ }
+ }
}
/**
@@ -2181,6 +2286,7 @@ public class BasicTreeUI
*/
public void mouseDragged(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -2192,6 +2298,7 @@ public class BasicTreeUI
*/
public void mouseMoved(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -2202,16 +2309,16 @@ public class BasicTreeUI
*/
public void mouseReleased(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
- }// MouseHandler
+ }
/**
* MouseInputHandler handles passing all mouse events, including mouse motion
* events, until the mouse is released to the destination it is constructed
* with.
*/
- public class MouseInputHandler
- implements MouseInputListener
+ public class MouseInputHandler implements MouseInputListener
{
/** Source that events are coming from */
protected Component source;
@@ -2232,6 +2339,8 @@ public class BasicTreeUI
public MouseInputHandler(Component source, Component destination,
MouseEvent e)
{
+ this.source = source;
+ this.destination = destination;
}
/**
@@ -2243,6 +2352,7 @@ public class BasicTreeUI
*/
public void mouseClicked(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -2253,42 +2363,7 @@ public class BasicTreeUI
*/
public void mousePressed(MouseEvent e)
{
- Point click = e.getPoint();
- int row = Math.round(click.y / getRowHeight());
- TreePath path = getClosestPathForLocation(tree, click.x, click.y);
-
- if (path != null)
- {
- boolean inBounds = false;
- boolean cntlClick = false;
- Rectangle bounds = getPathBounds(tree, path);
-
- bounds.x -= rightChildIndent - 4;
- bounds.width += rightChildIndent + 4;
-
- if (bounds.contains(click.x, click.y))
- inBounds = true;
- else if (hasControlIcons()
- && (click.x < (bounds.x - rightChildIndent + 5) &&
- click.x > (bounds.x - rightChildIndent - 5)))
- cntlClick = true;
-
- if ((inBounds || cntlClick) && tree.isVisible(path))
- {
- selectPath(tree, path);
-
- if ((e.getClickCount() == 2 || cntlClick) && !isLeaf(row))
- {
- if (tree.isExpanded(path))
- tree.collapsePath(path);
- else
- tree.expandPath(path);
- }
-
- if (!cntlClick && tree.isEditable())
- startEditing(path, e);
- }
- }
+ // TODO: What should be done here, if anything?
}
/**
@@ -2299,6 +2374,7 @@ public class BasicTreeUI
*/
public void mouseReleased(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -2309,6 +2385,7 @@ public class BasicTreeUI
*/
public void mouseEntered(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -2319,6 +2396,7 @@ public class BasicTreeUI
*/
public void mouseExited(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -2332,6 +2410,7 @@ public class BasicTreeUI
*/
public void mouseDragged(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -2343,6 +2422,7 @@ public class BasicTreeUI
*/
public void mouseMoved(MouseEvent e)
{
+ // TODO: What should be done here, if anything?
}
/**
@@ -2350,8 +2430,9 @@ public class BasicTreeUI
*/
protected void removeFromSource()
{
+ // TODO: Implement this properly.
}
- }// MouseInputHandler
+ }
/**
* Class responsible for getting size of node, method is forwarded to
@@ -2366,6 +2447,7 @@ public class BasicTreeUI
*/
public NodeDimensionsHandler()
{
+ // Nothing to do here.
}
/**
@@ -2413,6 +2495,7 @@ public class BasicTreeUI
*/
public PropertyChangeHandler()
{
+ // Nothing to do here.
}
/**
@@ -2424,8 +2507,15 @@ public class BasicTreeUI
*/
public void propertyChange(PropertyChangeEvent event)
{
+ if ((event.getPropertyName()).equals("rootVisible"))
+ {
+ validCachedPreferredSize = false;
+ updateCurrentVisiblePath();
+ tree.revalidate();
+ tree.repaint();
+ }
}
- }// PropertyChangeHandler
+ }
/**
* Listener on the TreeSelectionModel, resets the row selection if any of the
@@ -2440,6 +2530,7 @@ public class BasicTreeUI
*/
public SelectionModelPropertyChangeHandler()
{
+ // Nothing to do here.
}
/**
@@ -2451,8 +2542,9 @@ public class BasicTreeUI
*/
public void propertyChange(PropertyChangeEvent event)
{
+ // TODO: What should be done here, if anything?
}
- }// SelectionModelPropertyChangeHandler
+ }
/**
* ActionListener that invokes cancelEditing when action performed.
@@ -2464,8 +2556,9 @@ public class BasicTreeUI
/**
* Constructor
*/
- public TreeCancelEditingAction()
+ public TreeCancelEditingAction(String name)
{
+ // TODO: Implement this properly.
}
/**
@@ -2476,6 +2569,7 @@ public class BasicTreeUI
*/
public void actionPerformed(ActionEvent e)
{
+ // TODO: Implement this properly.
}
/**
@@ -2485,9 +2579,10 @@ public class BasicTreeUI
*/
public boolean isEnabled()
{
+ // TODO: Implement this properly.
return false;
}
- }// TreeCancelEditingAction
+ }
/**
* Updates the TreeState in response to nodes expanding/collapsing.
@@ -2501,6 +2596,7 @@ public class BasicTreeUI
*/
public TreeExpansionHandler()
{
+ // Nothing to do here.
}
/**
@@ -2511,6 +2607,9 @@ public class BasicTreeUI
*/
public void treeExpanded(TreeExpansionEvent event)
{
+ validCachedPreferredSize = false;
+ updateCurrentVisiblePath();
+ tree.revalidate();
tree.repaint();
}
@@ -2522,6 +2621,9 @@ public class BasicTreeUI
*/
public void treeCollapsed(TreeExpansionEvent event)
{
+ validCachedPreferredSize = false;
+ updateCurrentVisiblePath();
+ tree.revalidate();
tree.repaint();
}
}// TreeExpansionHandler
@@ -2547,6 +2649,7 @@ public class BasicTreeUI
*/
public TreeHomeAction(int direction, String name)
{
+ // TODO: Implement this properly
}
/**
@@ -2557,6 +2660,7 @@ public class BasicTreeUI
*/
public void actionPerformed(ActionEvent e)
{
+ // TODO: Implement this properly
}
/**
@@ -2566,9 +2670,10 @@ public class BasicTreeUI
*/
public boolean isEnabled()
{
+ // TODO: Implement this properly
return false;
}
- }// TreeHomeAction
+ }
/**
* TreeIncrementAction is used to handle up/down actions. Selection is moved
@@ -2591,6 +2696,7 @@ public class BasicTreeUI
*/
public TreeIncrementAction(int direction, String name)
{
+ // TODO: Implement this properly
}
/**
@@ -2606,11 +2712,11 @@ public class BasicTreeUI
if (e.getActionCommand().equals("selectPreviousChangeLead"))
{
Object prev = getPreviousVisibleNode(last);
-
+
if (prev != null)
{
TreePath newPath = new TreePath(getPathToRoot(prev, 0));
- selectPath(tree, new TreePath(getPathToRoot(prev, 0)));
+ selectPath(tree, newPath);
tree.setLeadSelectionPath(newPath);
}
}
@@ -2627,15 +2733,17 @@ public class BasicTreeUI
else if (e.getActionCommand().equals("selectPrevious"))
{
Object prev = getPreviousVisibleNode(last);
+
if (prev != null)
{
TreePath newPath = new TreePath(getPathToRoot(prev, 0));
- selectPath(tree, new TreePath(getPathToRoot(prev, 0)));
+ selectPath(tree, newPath);
}
}
else if (e.getActionCommand().equals("selectNext"))
{
Object next = getNextVisibleNode(last);
+
if (next != null)
{
TreePath newPath = new TreePath(getPathToRoot(next, 0));
@@ -2671,21 +2779,22 @@ public class BasicTreeUI
*/
public boolean isEnabled()
{
+ // TODO: Implement this properly
return false;
}
- }// TreeIncrementAction
+ }
/**
* Forwards all TreeModel events to the TreeState.
*/
- public class TreeModelHandler
- implements TreeModelListener
+ public class TreeModelHandler implements TreeModelListener
{
/**
* Constructor
*/
public TreeModelHandler()
{
+ // Nothing to do here.
}
/**
@@ -2703,6 +2812,9 @@ public class BasicTreeUI
*/
public void treeNodesChanged(TreeModelEvent e)
{
+ validCachedPreferredSize = false;
+ updateCurrentVisiblePath();
+ tree.revalidate();
tree.repaint();
}
@@ -2716,6 +2828,9 @@ public class BasicTreeUI
*/
public void treeNodesInserted(TreeModelEvent e)
{
+ validCachedPreferredSize = false;
+ updateCurrentVisiblePath();
+ tree.revalidate();
tree.repaint();
}
@@ -2732,6 +2847,9 @@ public class BasicTreeUI
*/
public void treeNodesRemoved(TreeModelEvent e)
{
+ validCachedPreferredSize = false;
+ updateCurrentVisiblePath();
+ tree.revalidate();
tree.repaint();
}
@@ -2747,6 +2865,12 @@ public class BasicTreeUI
*/
public void treeStructureChanged(TreeModelEvent e)
{
+ if (e.getPath().length == 1
+ && !e.getPath()[0].equals(treeModel.getRoot()))
+ tree.expandPath(new TreePath(treeModel.getRoot()));
+ updateCurrentVisiblePath();
+ validCachedPreferredSize = false;
+ tree.revalidate();
tree.repaint();
}
}// TreeModelHandler
@@ -2754,8 +2878,7 @@ public class BasicTreeUI
/**
* TreePageAction handles page up and page down events.
*/
- public class TreePageAction
- extends AbstractAction
+ public class TreePageAction extends AbstractAction
{
/** Specifies the direction to adjust the selection by. */
protected int direction;
@@ -2770,6 +2893,7 @@ public class BasicTreeUI
*/
public TreePageAction(int direction, String name)
{
+ this.direction = direction;
}
/**
@@ -2780,6 +2904,7 @@ public class BasicTreeUI
*/
public void actionPerformed(ActionEvent e)
{
+ // TODO: Implement this properly.
}
/**
@@ -2797,14 +2922,14 @@ public class BasicTreeUI
* Listens for changes in the selection model and updates the display
* accordingly.
*/
- public class TreeSelectionHandler
- implements TreeSelectionListener
+ public class TreeSelectionHandler implements TreeSelectionListener
{
/**
* Constructor
*/
public TreeSelectionHandler()
{
+ // Nothing to do here.
}
/**
@@ -2824,8 +2949,7 @@ public class BasicTreeUI
/**
* For the first selected row expandedness will be toggled.
*/
- public class TreeToggleAction
- extends AbstractAction
+ public class TreeToggleAction extends AbstractAction
{
/**
* Constructor
@@ -2835,6 +2959,7 @@ public class BasicTreeUI
*/
public TreeToggleAction(String name)
{
+ // Nothing to do here.
}
/**
@@ -2845,6 +2970,7 @@ public class BasicTreeUI
*/
public void actionPerformed(ActionEvent e)
{
+ // TODO: Implement this properly.
}
/**
@@ -2862,8 +2988,7 @@ public class BasicTreeUI
* TreeTraverseAction is the action used for left/right keys. Will toggle the
* expandedness of a node, as well as potentially incrementing the selection.
*/
- public class TreeTraverseAction
- extends AbstractAction
+ public class TreeTraverseAction extends AbstractAction
{
/**
* Determines direction to traverse, 1 means expand, -1 means collapse.
@@ -2880,6 +3005,7 @@ public class BasicTreeUI
*/
public TreeTraverseAction(int direction, String name)
{
+ this.direction = direction;
}
/**
@@ -2890,16 +3016,15 @@ public class BasicTreeUI
*/
public void actionPerformed(ActionEvent e)
{
- TreeModel mod = tree.getModel();
Object last = tree.getLeadSelectionPath().getLastPathComponent();
if (e.getActionCommand().equals("selectParent"))
{
TreePath path = new TreePath(getPathToRoot(last, 0));
- Object p = getParent(mod.getRoot(), last);
+ Object p = getParent(treeModel.getRoot(), last);
- if (!mod.isLeaf(last) && tree.isExpanded(path))
- tree.collapsePath(path);
+ if (!treeModel.isLeaf(last))
+ toggleExpandState(path);
else if (p != null)
selectPath(tree, new TreePath(getPathToRoot(p, 0)));
}
@@ -2907,8 +3032,8 @@ public class BasicTreeUI
{
TreePath path = new TreePath(getPathToRoot(last, 0));
- if (!mod.isLeaf(last) && tree.isCollapsed(path))
- tree.expandPath(path);
+ if (!treeModel.isLeaf(last))
+ toggleExpandState(path);
else
{
Object next = getNextVisibleNode(last);
@@ -2926,9 +3051,10 @@ public class BasicTreeUI
*/
public boolean isEnabled()
{
+ // TODO: Implement this properly
return false;
}
- } // TreeTraverseAction
+ }
/**
* Returns the cell bounds for painting selected cells Package private for use
@@ -2951,8 +3077,7 @@ public class BasicTreeUI
FontMetrics fm = tree.getToolkit().getFontMetrics(f);
if (s != null)
- return new Rectangle(x, y,
- SwingUtilities.computeStringWidth(fm, s) + 4,
+ return new Rectangle(x, y, SwingUtilities.computeStringWidth(fm, s),
fm.getHeight());
}
return new Rectangle(x, y, 0, 0);
@@ -2982,80 +3107,19 @@ public class BasicTreeUI
int rowHeight = getRowHeight();
if (startNode == null || startNode.equals(node))
{
- if (!tree.isRootVisible()
- && tree.isExpanded(new TreePath(mod.getRoot())))
- return new Point(x + ((getLevel(node)) * rightChildIndent), y);
-
- return new Point(x + ((getLevel(node) + 1) * rightChildIndent), y);
- }
-
- if (!mod.isLeaf(startNode)
- && tree.isExpanded(new TreePath(getPathToRoot(startNode, 0)))
- && !mod.isLeaf(startNode) && mod.getChildCount(startNode) > 0)
- {
- Object child = mod.getChild(startNode, 0);
- if (child != null)
- return getCellLocation(x, y + rowHeight, tree, mod, node, child);
+ int level = getLevel(node);
+ if (level == 0)
+ return new Point(x, y);
+ if (!tree.isRootVisible() &&
+ tree.isExpanded(new TreePath(mod.getRoot())))
+ return new Point(x + ((level - 1) * rightChildIndent), y);
+ return new Point(x + (level * rightChildIndent), y);
}
-
return getCellLocation(x, y + rowHeight, tree, mod, node,
getNextVisibleNode(startNode));
}
/**
- * Paints a node in the tree Package private for use in inner classes.
- *
- * @param g
- * the Graphics context in which to paint
- * @param x
- * the x location of the node
- * @param y
- * the y location of the node
- * @param tree
- * the tree to draw on
- * @param node
- * the object to draw
- */
- void paintNode(Graphics g, int x, int y, JTree tree, Object node,
- boolean isLeaf)
- {
- TreePath curr = new TreePath(getPathToRoot(node, 0));
- boolean selected = tree.isPathSelected(curr);
- boolean expanded = false;
- boolean hasIcons = false;
-
- if (tree.isVisible(curr))
- {
- if (!isLeaf)
- expanded = tree.isExpanded(curr);
-
- if (editingComponent != null && editingPath != null && isEditing(tree)
- && node.equals(editingPath.getLastPathComponent()))
- {
- Rectangle bounds = getPathBounds(tree, editingPath);
- rendererPane.paintComponent(g, editingComponent.getParent(), null,
- new Rectangle(0, 0, bounds.width,
- bounds.height));
- }
- else
- {
- TreeCellRenderer dtcr = tree.getCellRenderer();
- if (dtcr == null)
- dtcr = createDefaultCellRenderer();
-
- int row = getRowForPath(tree, curr);
-
- Component c = dtcr.getTreeCellRendererComponent(tree, node,
- selected, expanded,
- isLeaf, row, false);
-
- rendererPane.paintComponent(g, c, c.getParent(),
- getCellBounds(x, y, node));
- }
- }
- }
-
- /**
* Recursively paints all elements of the tree Package private for use in
* inner classes.
*
@@ -3065,8 +3129,6 @@ public class BasicTreeUI
* of the current object
* @param descent
* is the number of elements drawn
- * @param childNumber
- * is the index of the current child in the tree
* @param depth
* is the depth of the current object in the tree
* @param tree
@@ -3077,71 +3139,79 @@ public class BasicTreeUI
* is the current object to draw
* @return int - current descent of the tree
*/
- int paintRecursive(Graphics g, int indentation, int descent, int childNumber,
+ int paintRecursive(Graphics g, int indentation, int descent,
int depth, JTree tree, TreeModel mod, Object curr)
{
- Rectangle clip = g.getClipBounds();
+ Rectangle clip = tree.getVisibleRect();
if (indentation > clip.x + clip.width + rightChildIndent
|| descent > clip.y + clip.height + getRowHeight())
return descent;
+ TreePath path = new TreePath(getPathToRoot(curr, 0));
int halfHeight = getRowHeight() / 2;
int halfWidth = rightChildIndent / 2;
int y0 = descent + halfHeight;
int heightOfLine = descent + halfHeight;
+ int row = getRowForPath(tree, path);
boolean isRootVisible = tree.isRootVisible();
-
- if (mod.isLeaf(curr))
+ boolean isExpanded = tree.isExpanded(path);
+ boolean isLeaf = mod.isLeaf(curr);
+ Rectangle bounds = getPathBounds(tree, path);
+ Object root = mod.getRoot();
+
+ if (isLeaf)
{
- paintNode(g, indentation + 4, descent, tree, curr, true);
+ paintRow(g, clip, null, bounds, path, row, true, false, true);
descent += getRowHeight();
}
else
{
if (depth > 0 || isRootVisible)
{
- paintNode(g, indentation + 4, descent, tree, curr, false);
+ paintRow(g, clip, null, bounds, path, row, isExpanded, false, false);
descent += getRowHeight();
y0 += halfHeight;
}
-
- int max = 0;
- if (!mod.isLeaf(curr))
- max = mod.getChildCount(curr);
- if (tree.isExpanded(new TreePath(getPathToRoot(curr, 0))))
+
+ if (isExpanded)
{
+ int max = mod.getChildCount(curr);
for (int i = 0; i < max; i++)
{
+ Object child = mod.getChild(curr, i);
+ boolean childVis = tree.isVisible(new TreePath
+ (getPathToRoot(child, 0)));
int indent = indentation + rightChildIndent;
if (!isRootVisible && depth == 0)
indent = 0;
- else if ((!isRootVisible && !curr.equals(mod.getRoot()))
- || isRootVisible)
+ else if (isRootVisible ||
+ (!isRootVisible && !curr.equals(root)) && childVis)
{
g.setColor(getHashColor());
heightOfLine = descent + halfHeight;
- g.drawLine(indentation + halfWidth, heightOfLine,
- indentation + rightChildIndent, heightOfLine);
+ paintHorizontalLine(g, (JComponent) tree, heightOfLine,
+ indentation + halfWidth, indentation + rightChildIndent);
}
- descent = paintRecursive(g, indent, descent, i, depth + 1,
- tree, mod, mod.getChild(curr, i));
+ descent = paintRecursive(g, indent, descent, depth + 1,
+ tree, mod, child);
}
}
}
- if (tree.isExpanded(new TreePath(getPathToRoot(curr, 0))))
- if (y0 != heightOfLine && !mod.isLeaf(curr)
- && mod.getChildCount(curr) > 0)
+ if (isExpanded)
+ if (y0 != heightOfLine
+ && (mod.getChildCount(curr) > 0 &&
+ tree.isVisible(new TreePath(getPathToRoot(mod.getChild
+ (curr, 0), 0)))))
{
g.setColor(getHashColor());
- g.drawLine(indentation + halfWidth, y0, indentation + halfWidth,
- heightOfLine);
+ paintVerticalLine(g, (JComponent) tree, indentation + halfWidth, y0,
+ heightOfLine);
}
-
return descent;
}
-
+
/**
* Recursively paints all the control icons on the tree. Package private for
* use in inner classes.
@@ -3152,76 +3222,99 @@ public class BasicTreeUI
* of the current object
* @param descent
* is the number of elements drawn
- * @param childNumber
- * is the index of the current child in the tree
* @param depth
* is the depth of the current object in the tree
* @param tree
* is the tree to draw to
* @param mod
* is the TreeModel we are using to draw
- * @param curr
+ * @param node
* is the current object to draw
- * @return int - current descent of the tree
+ * @return int current descent of the tree
*/
int paintControlIcons(Graphics g, int indentation, int descent,
- int childNumber, int depth, JTree tree, TreeModel mod,
+ int depth, JTree tree, TreeModel mod,
Object node)
{
- int h = descent;
int rowHeight = getRowHeight();
- Icon ei = UIManager.getLookAndFeelDefaults().getIcon("Tree.expandedIcon");
- Icon ci = UIManager.getLookAndFeelDefaults().getIcon("Tree.collapsedIcon");
- Rectangle clip = g.getClipBounds();
+ TreePath path = new TreePath(getPathToRoot(node, 0));
+ Icon icon = getCurrentControlIcon(path);
+
+ Rectangle clip = tree.getVisibleRect();
if (indentation > clip.x + clip.width + rightChildIndent
|| descent > clip.y + clip.height + getRowHeight())
return descent;
-
+
if (mod.isLeaf(node))
descent += rowHeight;
else
- {
+ {
+ if (!node.equals(mod.getRoot()) &&
+ (tree.isRootVisible() || getLevel(node) != 1))
+ {
+ int width = icon.getIconWidth();
+ int height = icon.getIconHeight() + 2;
+ int posX = indentation - rightChildIndent;
+ int posY = descent;
+ if (width > rightChildIndent)
+ posX -= gap;
+ else posX += width/2;
+
+ if (height < rowHeight)
+ posY += height/2;
+
+ icon.paintIcon(tree, g, posX, posY);
+ }
+
if (depth > 0 || tree.isRootVisible())
descent += rowHeight;
-
- int max = 0;
- if (!mod.isLeaf(node))
- max = mod.getChildCount(node);
- if (tree.isExpanded(new TreePath(getPathToRoot(node, 0))))
+
+ if (tree.isExpanded(path))
{
- if (!node.equals(mod.getRoot()))
- ei.paintIcon(tree, g, indentation - rightChildIndent - 3, h);
-
+ int max = 0;
+ if (!mod.isLeaf(node))
+ max = mod.getChildCount(node);
+
for (int i = 0; i < max; i++)
{
int indent = indentation + rightChildIndent;
+ Object child = mod.getChild(node, i);
if (depth == 0 && !tree.isRootVisible())
- indent = -1;
-
- descent = paintControlIcons(g, indent, descent, i, depth + 1,
- tree, mod, mod.getChild(node, i));
+ indent = 1;
+ if (tree.isVisible(new TreePath(getPathToRoot(child, 0))))
+ descent = paintControlIcons(g, indent, descent, depth + 1,
+ tree, mod, child);
}
}
- else if (!node.equals(mod.getRoot()))
- ci.paintIcon(tree, g, indentation - rightChildIndent - 3,
- descent - getRowHeight());
}
-
+
return descent;
}
/**
- * Returns true if the LookAndFeel implements the control icons Package
+ * Returns true if the LookAndFeel implements the control icons. Package
* private for use in inner classes.
*
- * @return true if control icons are visible
+ * @returns true if there are control icons
*/
boolean hasControlIcons()
{
- if (UIManager.getLookAndFeelDefaults().getIcon("Tree.expandedIcon") == null
- || UIManager.getLookAndFeelDefaults().getIcon("Tree.collapsedIcon") == null)
- return false;
- return true;
+ if (expandedIcon != null || collapsedIcon != null)
+ return true;
+ return false;
+ }
+
+ /**
+ * Returns control icon. It is null if the LookAndFeel does not implements the
+ * control icons. Package private for use in inner classes.
+ *
+ * @return control icon if it exists.
+ */
+ Icon getCurrentControlIcon(TreePath path)
+ {
+ if (tree.isExpanded(path))
+ return expandedIcon;
+ return collapsedIcon;
}
/**
@@ -3235,8 +3328,10 @@ public class BasicTreeUI
*/
Object getParent(Object root, Object node)
{
- if (root == null || node == null)
+ if (root == null || node == null ||
+ root.equals(node))
return null;
+
if (node instanceof TreeNode)
return ((TreeNode) node).getParent();
return findNode(root, node);
@@ -3253,113 +3348,69 @@ public class BasicTreeUI
*/
private Object findNode(Object root, Object node)
{
- TreeModel mod = tree.getModel();
- int size = 0;
- if (!mod.isLeaf(root))
- size = mod.getChildCount(root);
- for (int i = 0; i < size; i++)
- {
- if (mod.getIndexOfChild(root, node) != -1)
- return root;
-
- Object n = findNode(mod.getChild(root, i), node);
- if (n != null)
- return n;
- }
- return null;
- }
-
- /**
- * Get next visible node in the tree. Package private for use in inner
- * classes.
- *
- * @param the
- * current node
- * @return the next visible node in the JTree. Return null if there are no
- * more.
- */
- Object getNextVisibleNode(Object node)
- {
- Object next = null;
- TreePath current = null;
-
- if (node != null)
- next = getNextNode(node);
-
- if (next != null)
+ if (!treeModel.isLeaf(root) && !root.equals(node))
{
- current = new TreePath(getPathToRoot(next, 0));
- if (tree.isVisible(current))
- return next;
-
- while (next != null && !tree.isVisible(current))
+ int size = treeModel.getChildCount(root);
+ for (int j = 0; j < size; j++)
{
- next = getNextNode(next);
+ Object child = treeModel.getChild(root, j);
+ if (node.equals(child))
+ return root;
- if (next != null)
- current = new TreePath(getPathToRoot(next, 0));
+ Object n = findNode(child, node);
+ if (n != null)
+ return n;
}
}
- return next;
+ return null;
}
-
+
/**
* Get previous visible node in the tree. Package private for use in inner
* classes.
*
- * @param the
+ * @param node -
* current node
* @return the next visible node in the JTree. Return null if there are no
* more.
*/
Object getPreviousVisibleNode(Object node)
{
- Object prev = null;
- TreePath current = null;
-
- if (node != null)
- prev = getPreviousNode(node);
-
- if (prev != null)
+ updateCurrentVisiblePath();
+ if (currentVisiblePath != null)
{
- current = new TreePath(getPathToRoot(prev, 0));
- if (tree.isVisible(current))
- return prev;
-
- while (prev != null && !tree.isVisible(current))
- {
- prev = getPreviousNode(prev);
-
- if (prev != null)
- current = new TreePath(getPathToRoot(prev, 0));
- }
+ Object[] nodes = currentVisiblePath.getPath();
+ int i = 0;
+ while (i < nodes.length && !node.equals(nodes[i]))
+ i++;
+ // return the next node
+ if (i-1 >= 0)
+ return nodes[i-1];
}
- return prev;
+ return null;
}
/**
* Returns the next node in the tree Package private for use in inner classes.
*
- * @param the
+ * @param curr -
* current node
* @return the next node in the tree
*/
Object getNextNode(Object curr)
{
- TreeModel mod = tree.getModel();
- if (!mod.isLeaf(curr) && mod.getChildCount(curr) > 0)
- return mod.getChild(curr, 0);
+ if (!treeModel.isLeaf(curr) && treeModel.getChildCount(curr) > 0)
+ return treeModel.getChild(curr, 0);
Object node = curr;
Object sibling = null;
-
do
{
sibling = getNextSibling(node);
- node = getParent(mod.getRoot(), node);
+ node = getParent(treeModel.getRoot(), node);
}
while (sibling == null && node != null);
-
+
return sibling;
}
@@ -3367,14 +3418,13 @@ public class BasicTreeUI
* Returns the previous node in the tree Package private for use in inner
* classes.
*
- * @param the
+ * @param node
* current node
* @return the previous node in the tree
*/
Object getPreviousNode(Object node)
{
- TreeModel mod = tree.getModel();
- Object parent = getParent(mod.getRoot(), node);
+ Object parent = getParent(treeModel.getRoot(), node);
if (parent == null)
return null;
@@ -3384,13 +3434,13 @@ public class BasicTreeUI
return parent;
int size = 0;
- if (!mod.isLeaf(sibling))
- size = mod.getChildCount(sibling);
+ if (!treeModel.isLeaf(sibling))
+ size = treeModel.getChildCount(sibling);
while (size > 0)
{
- sibling = mod.getChild(sibling, size - 1);
- if (!mod.isLeaf(sibling))
- size = mod.getChildCount(sibling);
+ sibling = treeModel.getChild(sibling, size - 1);
+ if (!treeModel.isLeaf(sibling))
+ size = treeModel.getChildCount(sibling);
else
size = 0;
}
@@ -3402,52 +3452,50 @@ public class BasicTreeUI
* Returns the next sibling in the tree Package private for use in inner
* classes.
*
- * @param the
+ * @param node -
* current node
* @return the next sibling in the tree
*/
Object getNextSibling(Object node)
{
- TreeModel mod = tree.getModel();
- Object parent = getParent(mod.getRoot(), node);
+ Object parent = getParent(treeModel.getRoot(), node);
if (parent == null)
return null;
- int index = mod.getIndexOfChild(parent, node) + 1;
+ int index = treeModel.getIndexOfChild(parent, node) + 1;
int size = 0;
- if (!mod.isLeaf(parent))
- size = mod.getChildCount(parent);
+ if (!treeModel.isLeaf(parent))
+ size = treeModel.getChildCount(parent);
if (index == 0 || index >= size)
return null;
- return mod.getChild(parent, index);
+ return treeModel.getChild(parent, index);
}
-
+
/**
* Returns the previous sibling in the tree Package private for use in inner
* classes.
*
- * @param the
+ * @param node -
* current node
* @return the previous sibling in the tree
*/
Object getPreviousSibling(Object node)
{
- TreeModel mod = tree.getModel();
- Object parent = getParent(mod.getRoot(), node);
+ Object parent = getParent(treeModel.getRoot(), node);
if (parent == null)
return null;
- int index = mod.getIndexOfChild(parent, node) - 1;
+ int index = treeModel.getIndexOfChild(parent, node) - 1;
int size = 0;
- if (!mod.isLeaf(parent))
- size = mod.getChildCount(parent);
+ if (!treeModel.isLeaf(parent))
+ size = treeModel.getChildCount(parent);
if (index < 0 || index >= size)
return null;
- return mod.getChild(parent, index);
+ return treeModel.getChild(parent, index);
}
/**
@@ -3463,22 +3511,24 @@ public class BasicTreeUI
{
if (path != null)
{
- if (tree.getSelectionModel().getSelectionMode() == TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION)
+ if (tree.getSelectionModel().getSelectionMode() ==
+ TreeSelectionModel.SINGLE_TREE_SELECTION)
{
+ tree.getSelectionModel().clearSelection();
tree.addSelectionPath(path);
tree.setLeadSelectionPath(path);
}
- else if (tree.getSelectionModel().getSelectionMode() == TreeSelectionModel.CONTIGUOUS_TREE_SELECTION)
+ else if (tree.getSelectionModel().getSelectionMode() ==
+ TreeSelectionModel.CONTIGUOUS_TREE_SELECTION)
{
// TODO
}
else
{
- tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
-
- tree.getSelectionModel().clearSelection();
tree.addSelectionPath(path);
tree.setLeadSelectionPath(path);
+ tree.getSelectionModel().setSelectionMode
+ (TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
}
}
}
@@ -3495,7 +3545,6 @@ public class BasicTreeUI
*/
Object[] getPathToRoot(Object node, int depth)
{
- TreeModel mod = tree.getModel();
if (node == null)
{
if (depth == 0)
@@ -3504,7 +3553,7 @@ public class BasicTreeUI
return new Object[depth];
}
- Object[] path = getPathToRoot(getParent(mod.getRoot(), node), depth + 1);
+ Object[] path = getPathToRoot(getParent(treeModel.getRoot(), node), depth + 1);
path[path.length - depth - 1] = node;
return path;
}
@@ -3512,22 +3561,23 @@ public class BasicTreeUI
/**
* Returns the level of the node in the tree.
*
- * @param the
+ * @param node -
* current node
* @return the number of the level
*/
int getLevel(Object node)
{
int count = -1;
+
Object current = node;
do
{
- current = getParent(tree.getModel().getRoot(), current);
+ current = getParent(treeModel.getRoot(), current);
count++;
}
while (current != null);
-
+
return count;
}
@@ -3586,10 +3636,271 @@ public class BasicTreeUI
* is the center position in y-direction FIXME what to do if x <
* (icon.width / 2). Same with y
*/
- protected void drawCentered(JComponent c, Graphics g, Icon icon, int x, int y)
+ protected void drawCentered(Component c, Graphics g, Icon icon, int x, int y)
{
int beginPositionX = x - icon.getIconWidth() / 2;
int beginPositionY = y - icon.getIconHeight() / 2;
icon.paintIcon(c, g, beginPositionX, beginPositionY);
}
+
+ /**
+ * Draws a dashed horizontal line.
+ *
+ * @param g - the graphics configuration.
+ * @param y - the y location to start drawing at
+ * @param x1 - the x location to start drawing at
+ * @param x2 - the x location to finish drawing at
+ */
+ protected void drawDashedHorizontalLine(Graphics g, int y, int x1, int x2)
+ {
+ for (int i = x1; i < x2; i += 2)
+ g.drawLine(i, y, i + 1, y);
+ }
+
+ /**
+ * Draws a dashed vertical line.
+ *
+ * @param g - the graphics configuration.
+ * @param x - the x location to start drawing at
+ * @param y1 - the y location to start drawing at
+ * @param y2 - the y location to finish drawing at
+ */
+ protected void drawDashedVerticalLine(Graphics g, int x, int y1, int y2)
+ {
+ for (int i = y1; i < y2; i += 2)
+ g.drawLine(x, i, x, i + 1);
+ }
+
+ /**
+ * Paints the expand (toggle) part of a row. The receiver should NOT modify
+ * clipBounds, or insets.
+ *
+ * @param g - the graphics configuration
+ * @param clipBounds -
+ * @param insets -
+ * @param bounds - bounds of expand control
+ * @param path - path to draw control for
+ * @param row - row to draw control for
+ * @param isExpanded - is the row expanded
+ * @param hasBeenExpanded - has the row already been expanded
+ * @param isLeaf - is the path a leaf
+ */
+ protected void paintExpandControl(Graphics g, Rectangle clipBounds,
+ Insets insets, Rectangle bounds,
+ TreePath path, int row,
+ boolean isExpanded, boolean hasBeenExpanded,
+ boolean isLeaf)
+ {
+ if (treeModel != null && hasControlIcons())
+ paintControlIcons(g, 0, 0, 0, tree, treeModel, path.getLastPathComponent());
+ }
+
+ /**
+ * Paints the horizontal part of the leg. The receiver should NOT modify
+ * clipBounds, or insets.
+ * NOTE: parentRow can be -1 if the root is not visible.
+ *
+ * @param g - the graphics configuration
+ * @param clipBounds -
+ * @param insets -
+ * @param bounds - bounds of expand control
+ * @param path - path to draw control for
+ * @param row - row to draw control for
+ * @param isExpanded - is the row expanded
+ * @param hasBeenExpanded - has the row already been expanded
+ * @param isLeaf - is the path a leaf
+ */
+ protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
+ Insets insets, Rectangle bounds,
+ TreePath path, int row,
+ boolean isExpanded, boolean hasBeenExpanded,
+ boolean isLeaf)
+ {
+ // FIXME: not implemented
+ }
+
+ /**
+ * Paints the vertical part of the leg. The receiver should NOT modify
+ * clipBounds, insets.
+ *
+ * @param g - the graphics configuration.
+ * @param clipBounds -
+ * @param insets -
+ * @param path - the path to draw the vertical part for.
+ */
+ protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds,
+ Insets insets, TreePath path)
+ {
+ // FIXME: not implemented
+ }
+
+ /**
+ * Paints the renderer part of a row. The receiver should NOT modify clipBounds,
+ * or insets.
+ *
+ * @param g - the graphics configuration
+ * @param clipBounds -
+ * @param insets -
+ * @param bounds - bounds of expand control
+ * @param path - path to draw control for
+ * @param row - row to draw control for
+ * @param isExpanded - is the row expanded
+ * @param hasBeenExpanded - has the row already been expanded
+ * @param isLeaf - is the path a leaf
+ */
+ protected void paintRow(Graphics g, Rectangle clipBounds,
+ Insets insets, Rectangle bounds,
+ TreePath path, int row,
+ boolean isExpanded, boolean hasBeenExpanded,
+ boolean isLeaf)
+ {
+ boolean selected = tree.isPathSelected(path);
+ boolean hasIcons = false;
+ Object node = path.getLastPathComponent();
+
+ if (tree.isVisible(path))
+ {
+ if (!validCachedPreferredSize)
+ updateCachedPreferredSize();
+ bounds.x += gap;
+ bounds.width = preferredSize.width + bounds.x;
+
+ if (editingComponent != null && editingPath != null && isEditing(tree)
+ && node.equals(editingPath.getLastPathComponent()))
+ {
+ rendererPane.paintComponent(g, editingComponent.getParent(), null,
+ bounds);
+ }
+ else
+ {
+ TreeCellRenderer dtcr = tree.getCellRenderer();
+ if (dtcr == null)
+ dtcr = createDefaultCellRenderer();
+
+ Component c = dtcr.getTreeCellRendererComponent(tree, node,
+ selected, isExpanded, isLeaf, row, tree.hasFocus());
+ rendererPane.paintComponent(g, c, c.getParent(), bounds);
+ }
+ }
+ }
+
+ /**
+ * Prepares for the UI to uninstall.
+ */
+ protected void prepareForUIUninstall()
+ {
+ // TODO: Implement this properly.
+ }
+
+ /**
+ * Returns true if the expand (toggle) control should be drawn for the
+ * specified row.
+ *
+ * @param path - current path to check for.
+ * @param row - current row to check for.
+ * @param isExpanded - true if the path is expanded
+ * @param hasBeenExpanded - true if the path has been expanded already
+ * @param isLeaf - true if the row is a lead
+ */
+ protected boolean shouldPaintExpandControl(TreePath path, int row,
+ boolean isExpanded,
+ boolean hasBeenExpanded,
+ boolean isLeaf)
+ {
+ Object node = path.getLastPathComponent();
+ if (treeModel != null && (!isLeaf && !node.equals(treeModel.getRoot())) &&
+ (tree.isRootVisible() || getLevel(node) != 1))
+ return true;
+ return false;
+ }
+
+ /**
+ * Updates the cached current TreePath of all visible
+ * nodes in the tree.
+ */
+ void updateCurrentVisiblePath()
+ {
+ if (treeModel == null)
+ return;
+
+ Object next = treeModel.getRoot();
+ Rectangle bounds = getCellBounds(0, 0, next);
+ boolean rootVisible = isRootVisible();
+
+ // If root is not a valid size to be visible, or is
+ // not visible and the tree is expanded, then the next node acts
+ // as the root
+ if ((bounds.width == 0 && bounds.height == 0) || (!rootVisible
+ && tree.isExpanded(new TreePath(next))))
+ next = getNextNode(next);
+
+ Object root = next;
+ TreePath current = null;
+ while (next != null)
+ {
+ if (current == null)
+ current = new TreePath(next);
+ else
+ current = current.pathByAddingChild(next);
+ do
+ {
+ TreePath path = new TreePath(getPathToRoot(next, 0));
+ if ((tree.isVisible(path) && tree.isExpanded(path))
+ || treeModel.isLeaf(next))
+ next = getNextNode(next);
+ else
+ {
+ Object pNext = next;
+ next = getNextSibling(pNext);
+ // if no next sibling, check parent's next sibling.
+ if (next == null)
+ {
+ Object parent = getParent(root, pNext);
+ while (next == null && parent != null)
+ {
+ next = getNextSibling(parent);
+ if (next == null)
+ parent = getParent(treeModel.getRoot(), next);
+ }
+ }
+ }
+ }
+ while (next != null &&
+ !tree.isVisible(new TreePath(getPathToRoot(next, 0))));
+ }
+
+ currentVisiblePath = current;
+ if (currentVisiblePath != null)
+ tree.setVisibleRowCount(currentVisiblePath.getPathCount());
+ else tree.setVisibleRowCount(0);
+
+ if (tree.getSelectionModel() != null && tree.getSelectionCount() == 0 &&
+ currentVisiblePath != null)
+ selectPath(tree, new TreePath(getPathToRoot(currentVisiblePath.
+ getPathComponent(0), 0)));
+ }
+
+ /**
+ * Get next visible node in the currentVisiblePath. Package private for use in
+ * inner classes.
+ *
+ * @param node
+ * current node
+ * @return the next visible node in the JTree. Return null if there are no
+ * more.
+ */
+ Object getNextVisibleNode(Object node)
+ {
+ if (currentVisiblePath != null)
+ {
+ Object[] nodes = currentVisiblePath.getPath();
+ int i = 0;
+ while (i < nodes.length && !node.equals(nodes[i]))
+ i++;
+ // return the next node
+ if (i+1 < nodes.length)
+ return nodes[i+1];
+ }
+ return null;
+ }
} // BasicTreeUI
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java
index 0d461332a70..51b902d6443 100644
--- a/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java
+++ b/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java
@@ -38,61 +38,22 @@ exception statement from your version. */
package javax.swing.plaf.basic;
-import java.awt.Component;
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.Image;
-import java.awt.Point;
-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.LookAndFeel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ViewportUI;
public class BasicViewportUI extends ViewportUI
{
-
- ChangeListener changeListener;
- Image backingStoreImage;
- int backingStoreWidth = -1;
- int backingStoreHeight = -1;
-
- class ChangeHandler implements ChangeListener
+ protected void installDefaults(JComponent c)
{
- public void stateChanged(ChangeEvent event)
- {
- JViewport v = (JViewport) event.getSource();
- v.repaint();
- }
- }
-
- void installDefaults(JComponent c)
- {
c.setOpaque(true);
+ LookAndFeel.installColorsAndFont(c, "Viewport.background",
+ "Viewport.foreground", "Viewport.font");
}
-
- void uninstallDefaults(JComponent c)
- {
- }
-
- void installListeners(JComponent c)
+ protected void uninstallDefaults(JComponent c)
{
- ((JViewport)c).addChangeListener(changeListener);
- }
-
- void uninstallListeners(JComponent c)
- {
- ((JViewport)c).removeChangeListener(changeListener);
- }
-
- public BasicViewportUI()
- {
- changeListener = new ChangeHandler();
+ // TODO: Implement this properly.
}
public static ComponentUI createUI(JComponent c)
@@ -103,132 +64,12 @@ public class BasicViewportUI extends ViewportUI
public void installUI(JComponent c)
{
super.installUI(c);
- installListeners(c);
+ installDefaults(c);
}
public void uninstallUI(JComponent c)
{
- uninstallListeners(c);
- }
-
-
- public Dimension getPreferredSize(JComponent c)
- {
- // let the ViewportLayout decide
- return null;
- }
-
- public void paint(Graphics g, JComponent c)
- {
- JViewport port = (JViewport)c;
- Component view = port.getView();
-
- if (view == null)
- return;
-
- Point pos = port.getViewPosition();
- Rectangle viewBounds = view.getBounds();
- Rectangle portBounds = port.getBounds();
-
- if (viewBounds.width == 0
- || viewBounds.height == 0
- || portBounds.width == 0
- || portBounds.height == 0)
- return;
-
- switch (port.getScrollMode())
- {
-
- case JViewport.BACKINGSTORE_SCROLL_MODE:
- paintBackingStore(g, port, view, pos, viewBounds, portBounds);
- break;
-
- case JViewport.BLIT_SCROLL_MODE:
- // FIXME: implement separate blit mode
-
- case JViewport.SIMPLE_SCROLL_MODE:
- default:
- paintSimple(g, port, view, pos, viewBounds, portBounds);
- break;
- }
- }
-
- private void paintSimple(Graphics g,
- JViewport v,
- Component view,
- Point pos,
- Rectangle viewBounds,
- Rectangle portBounds)
- {
- Rectangle oldClip = g.getClipBounds();
- g.setClip(new Rectangle(0, 0, portBounds.width, portBounds.height));
- g.translate (-pos.x, -pos.y);
- try
- {
- view.paint(g);
- }
- finally
- {
- g.translate (pos.x, pos.y);
- g.setClip (oldClip);
- }
- }
-
- private void paintBackingStore(Graphics g,
- JViewport v,
- Component view,
- Point pos,
- Rectangle viewBounds,
- Rectangle portBounds)
- {
- if (backingStoreImage == null
- || backingStoreWidth != viewBounds.width
- || backingStoreHeight != viewBounds.height)
- {
- backingStoreImage = v.createImage(viewBounds.width, viewBounds.height);
- backingStoreWidth = viewBounds.width;
- backingStoreHeight = viewBounds.height;
- }
-
- Graphics g2 = backingStoreImage.getGraphics();
-
- if (v.getBackground() != null)
- {
- // fill the backing store background
- java.awt.Color save = g2.getColor();
- g2.setColor(v.getBackground());
- g2.fillRect (0, 0, backingStoreWidth, backingStoreHeight);
- g2.setColor(save);
-
- // fill the viewport background
- save = g.getColor();
- g.setColor(v.getBackground());
- g.fillRect (0, 0, portBounds.width, portBounds.height);
- g.setColor(save);
-
- }
- else
- {
- // clear the backing store background
- g2.clearRect(0, 0, backingStoreWidth, backingStoreHeight);
-
- // clear the viewport background
- g.clearRect(0, 0, portBounds.width, portBounds.height);
- }
-
- g2.setClip(g.getClipBounds());
- g2.translate(-pos.x, -pos.y);
- try
- {
- view.paint(g2);
- }
- finally
- {
- g2.translate(pos.x, pos.y);
- }
- g2 = null;
- g.drawImage(backingStoreImage,
- 0, 0,
- (ImageObserver)null);
+ super.uninstallUI(c);
+ uninstallDefaults(c);
}
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java
index f55510684c6..4fa3b364056 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java
@@ -45,21 +45,29 @@ import java.awt.Insets;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
+import javax.swing.JButton;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
import javax.swing.JTextField;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+import javax.swing.SwingConstants;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicBorders;
+import javax.swing.text.JTextComponent;
/**
- * This factory class creates borders for the different Swing components
- * UI.
+ * A factory class that creates borders for the different Swing components.
*
* @author Roman Kennke (roman@kennke.org)
*/
@@ -69,12 +77,24 @@ public class MetalBorders
/** The shared instance for getButtonBorder(). */
private static Border buttonBorder;
+ /** The shared instance for getToggleButtonBorder(). */
+ private static Border toggleButtonBorder;
+
+ /** The shared instance for getDesktopIconBorder(). */
+ private static Border desktopIconBorder;
+
/** The shared instance for getRolloverButtonBorder(). */
private static Border toolbarButtonBorder;
/** The shared instance for getTextFieldBorder(). */
private static Border textFieldBorder;
+ /** The shared instance for getTextBorder(). */
+ private static Border textBorder;
+
+ /** The shared instance for getRolloverBorder(). */
+ private static Border rolloverBorder;
+
/**
* A MarginBorder that gets shared by multiple components.
* Created on demand by the private helper function {@link
@@ -83,20 +103,19 @@ public class MetalBorders
private static BasicBorders.MarginBorder marginBorder;
/**
- * The border that is drawn around Swing buttons.
+ * A border used for {@link JButton} components.
*/
- public static class ButtonBorder
- extends AbstractBorder
- implements UIResource
+ public static class ButtonBorder extends AbstractBorder implements UIResource
{
/** The borders insets. */
protected static Insets borderInsets = new Insets(3, 3, 3, 3);
/**
- * Creates a new instance of ButtonBorder.
+ * Creates a new instance of <code>ButtonBorder</code>.
*/
public ButtonBorder()
{
+ // Nothing to do here.
}
/**
@@ -122,46 +141,55 @@ public class MetalBorders
Color light = MetalLookAndFeel.getWhite();
Color middle = MetalLookAndFeel.getControl();
- // draw dark border
- g.setColor(darkShadow);
- g.drawRect(x, y, w - 2, h - 2);
-
- if (!bmodel.isPressed())
- {
- // draw light border
- g.setColor(light);
- g.drawRect(x + 1, y + 1, w - 2, h - 2);
+ if (c.isEnabled())
+ {
+ // draw dark border
+ g.setColor(darkShadow);
+ g.drawRect(x, y, w - 2, h - 2);
- // draw crossing pixels of both borders
- g.setColor(middle);
- g.drawRect(x + 1, y + h - 2, 0, 0);
- g.drawRect(x + w - 2, y + 1, 0, 0);
- }
- else
- {
- // draw light border
- g.setColor(light);
- g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
- g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
+ if (!bmodel.isPressed())
+ {
+ // draw light border
+ g.setColor(light);
+ g.drawRect(x + 1, y + 1, w - 2, h - 2);
- // draw shadow border
- g.setColor(middle);
- g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
- g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
+ // draw crossing pixels of both borders
+ g.setColor(middle);
+ g.drawRect(x + 1, y + h - 2, 0, 0);
+ g.drawRect(x + w - 2, y + 1, 0, 0);
+ }
+ else
+ {
+ // draw light border
+ g.setColor(light);
+ g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
+ g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
- // draw crossing pixels of both borders
- g.setColor(shadow);
- g.drawRect(x + 1, y + h - 2, 0, 0);
- g.drawRect(x + w - 2, y + 1, 0, 0);
+ // draw shadow border
+ g.setColor(middle);
+ g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
+
+ // draw crossing pixels of both borders
+ g.setColor(shadow);
+ g.drawRect(x + 1, y + h - 2, 0, 0);
+ g.drawRect(x + w - 2, y + 1, 0, 0);
+ }
+ }
+ else
+ {
+ // draw disabled border
+ g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
+ g.drawRect(x, y, w - 2, h - 2);
}
}
/**
- * Returns the insets of the ButtonBorder.
+ * Returns the insets of the <code>ButtonBorder</code>.
*
* @param c the component for which the border is used
*
- * @return the insets of the ButtonBorder
+ * @return The insets of the ButtonBorder
*/
public Insets getBorderInsets(Component c)
{
@@ -169,19 +197,20 @@ public class MetalBorders
}
/**
- * Returns the insets of the ButtonBorder in the specified Insets object.
+ * Returns the insets of the <code>ButtonBorder</code> in the specified
+ * <code>newInsets</code> object.
*
* @param c the component for which the border is used
- * @param newInsets the insets object where to put the values
+ * @param newInsets the insets object where to put the values (if
+ * <code>null</code>, a new instance is created).
*
- * @return the insets of the ButtonBorder
+ * @return The insets.
*/
public Insets getBorderInsets(Component c, Insets newInsets)
{
if (newInsets == null)
newInsets = new Insets(0, 0, 0, 0);
- AbstractButton b = (AbstractButton) c;
newInsets.bottom = borderInsets.bottom;
newInsets.left = borderInsets.left;
newInsets.right = borderInsets.right;
@@ -191,6 +220,71 @@ public class MetalBorders
}
/**
+ * A border used when painting {@link JInternalFrame} instances.
+ */
+ static class DesktopIconBorder extends AbstractBorder
+ implements UIResource
+ {
+ /**
+ * Creates a new border instance.
+ */
+ public DesktopIconBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return getBorderInsets(c, null);
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ if (newInsets == null)
+ newInsets = new Insets(3, 3, 2, 3);
+ else
+ {
+ newInsets.top = 3;
+ newInsets.left = 3;
+ newInsets.bottom = 2;
+ newInsets.right = 3;
+ }
+ return newInsets;
+ }
+
+ /**
+ * Paints the border for the specified component.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param w the width.
+ * @param h the height.
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawRect(x, y, w - 1, h - 1);
+ }
+
+ }
+
+ /**
* A simple 3D border.
*/
public static class Flush3DBorder extends AbstractBorder
@@ -201,6 +295,7 @@ public class MetalBorders
*/
public Flush3DBorder()
{
+ // Nothing to do here.
}
/**
@@ -262,6 +357,88 @@ public class MetalBorders
}
/**
+ * A border used for a {@link JInternalFrame} when it is being used as a
+ * palette.
+ *
+ * @since 1.3
+ */
+ public static class PaletteBorder extends AbstractBorder
+ implements UIResource
+ {
+ /**
+ * Creates a new <code>PaletteBorder</code>.
+ */
+ public PaletteBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return getBorderInsets(c, null);
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ * @param newInsets the insets object that, if non-<code>null</code>, will
+ * be populated with the result from this method.
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ if (newInsets == null)
+ newInsets = new Insets(1, 1, 1, 1);
+ else
+ {
+ newInsets.top = 1;
+ newInsets.left = 1;
+ newInsets.bottom = 1;
+ newInsets.right = 1;
+ }
+ return newInsets;
+ }
+
+ /**
+ * Paints the border for the specified component.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param w the width.
+ * @param h the height.
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+ Color savedColor = g.getColor();
+
+ // draw the outline
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ g.drawRect(x, y, w - 1, h - 1);
+
+ // put a dot in each corner
+ g.setColor(MetalLookAndFeel.getControl());
+ g.fillRect(x, y, 1, 1);
+ g.fillRect(x + w - 1, y, 1, 1);
+ g.fillRect(x + w - 1, y + h - 1, 1, 1);
+ g.fillRect(x, y + h - 1, 1, 1);
+ g.setColor(savedColor);
+ }
+
+ }
+
+ /**
* A border used for the {@link JTextField} component.
*/
public static class TextFieldBorder extends Flush3DBorder
@@ -272,6 +449,7 @@ public class MetalBorders
*/
public TextFieldBorder()
{
+ // Nothing to do here.
}
/**
@@ -286,8 +464,17 @@ public class MetalBorders
*/
public void paintBorder(Component c, Graphics g, int x, int y, int w,
int h)
- {
- if (c.isEnabled())
+ {
+ boolean enabledTextBorder;
+ if (c instanceof JTextComponent)
+ {
+ JTextComponent tc = (JTextComponent) c;
+ enabledTextBorder = tc.isEnabled() && tc.isEditable();
+ }
+ else
+ enabledTextBorder = false;
+
+ if (enabledTextBorder)
super.paintBorder(c, g, x, y, w, h);
else
{
@@ -301,7 +488,7 @@ public class MetalBorders
}
/**
- * A border used when painting {@link JInternalFrame} instances.
+ * A border used for the {@link JInternalFrame} component.
*/
public static class InternalFrameBorder extends AbstractBorder
implements UIResource
@@ -311,6 +498,7 @@ public class MetalBorders
*/
public InternalFrameBorder()
{
+ // Nothing to do here.
}
/**
@@ -386,7 +574,10 @@ public class MetalBorders
g.drawLine(x + w - 3, y + 14, x + w - 3, y + h - 15);
// draw the line highlights
- g.setColor(MetalLookAndFeel.getControl());
+ if (f.isSelected())
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControlShadow());
g.drawLine(x + 15, y + 3, x + w - 14, y + 3);
g.drawLine(x + 15, y + h - 2, x + w - 14, y + h - 2);
g.drawLine(x + 3, y + 15, x + 3, y + h - 14);
@@ -396,24 +587,129 @@ public class MetalBorders
}
/**
+ * A border used for {@link JInternalFrame} components that are
+ * presented as dialogs (by the {@link JOptionPane} class).
+ */
+ public static class OptionDialogBorder extends AbstractBorder
+ implements UIResource
+ {
+
+ /**
+ * Creates a new border instance.
+ */
+ public OptionDialogBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return getBorderInsets(c, null);
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ if (newInsets == null)
+ newInsets = new Insets(3, 3, 3, 3);
+ else
+ {
+ newInsets.top = 3;
+ newInsets.left = 3;
+ newInsets.bottom = 3;
+ newInsets.right = 3;
+ }
+ return newInsets;
+ }
+
+ /**
+ * Paints the border for the specified component.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param w the width.
+ * @param h the height.
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+
+ JInternalFrame f = (JInternalFrame) c;
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ if (f.getContentPane() instanceof JOptionPane)
+ {
+ JOptionPane pane = (JOptionPane) f.getContentPane();
+ int type = pane.getMessageType();
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ if (type == JOptionPane.QUESTION_MESSAGE)
+ {
+ Color bc = defaults.getColor(
+ "OptionPane.questionDialog.border.background");
+ if (bc != null)
+ g.setColor(bc);
+ }
+ if (type == JOptionPane.WARNING_MESSAGE)
+ {
+ Color bc = defaults.getColor(
+ "OptionPane.warningDialog.border.background");
+ if (bc != null)
+ g.setColor(bc);
+ }
+ else if (type == JOptionPane.ERROR_MESSAGE)
+ {
+ Color bc = defaults.getColor(
+ "OptionPane.errorDialog.border.background");
+ if (bc != null)
+ g.setColor(bc);
+ }
+ }
+
+ // fill the border background
+ g.fillRect(x, y, w, 3);
+ g.fillRect(x, y, 3, h);
+ g.fillRect(x + w - 3, y, 3, h);
+ g.fillRect(x, y + h - 3, w, 3);
+
+ // draw a dot in each corner
+ g.setColor(MetalLookAndFeel.getControl());
+ g.fillRect(x, y, 1, 1);
+ g.fillRect(x + w - 1, y, 1, 1);
+ g.fillRect(x + w - 1, y + h - 1, 1, 1);
+ g.fillRect(x, y + h - 1, 1, 1);
+
+ }
+
+ }
+
+ /**
* A border used for {@link JMenu} and {@link JMenuItem} components.
*/
- public static class MenuItemBorder
- extends AbstractBorder
- implements UIResource
+ public static class MenuItemBorder extends AbstractBorder
+ implements UIResource
{
/** The border insets. */
- protected static Insets borderInsets = new Insets(2, 2, 2, 2);
-
- // TODO: find where the real colors come from
- private static Color borderColorDark = new Color(102, 102, 153);
- private static Color borderColorLight = new Color(255, 255, 255);
+ protected static Insets borderInsets = new Insets(1, 1, 1, 1);
/**
* Creates a new border instance.
*/
public MenuItemBorder()
{
+ // Nothing to do here.
}
/**
@@ -430,15 +726,17 @@ public class MetalBorders
public void paintBorder(Component c, Graphics g, int x, int y, int w,
int h)
{
+ Color dark = MetalLookAndFeel.getPrimaryControlDarkShadow();
+ Color light = MetalLookAndFeel.getPrimaryControlHighlight();
if (c instanceof JMenu) {
JMenu menu = (JMenu) c;
if (menu.isSelected())
{
- g.setColor(borderColorDark);
+ g.setColor(dark);
g.drawLine(x, y, x, y + h);
g.drawLine(x, y, x + w, y);
g.drawLine(x + w - 2, y + 1, x + w - 2, y + h);
- g.setColor(borderColorLight);
+ g.setColor(light);
g.drawLine(x + w - 1, y + 1, x + w - 1, y + h);
}
}
@@ -446,12 +744,18 @@ public class MetalBorders
{
JMenuItem item = (JMenuItem) c;
if (item.isArmed())
- {
- g.setColor(borderColorDark);
- g.drawLine(x, y, x + w, y);
- g.setColor(borderColorLight);
- g.drawLine(x, y + h - 1, x + w, y + h - 1);
- }
+ {
+ g.setColor(dark);
+ g.drawLine(x, y, x + w, y);
+ g.setColor(light);
+ g.drawLine(x, y + h - 1, x + w, y + h - 1);
+ }
+ else
+ {
+ // Normally we draw a light line on the left.
+ g.setColor(light);
+ g.drawLine(x, y, x, y + h);
+ }
}
}
@@ -505,6 +809,7 @@ public class MetalBorders
*/
public MenuBarBorder()
{
+ // Nothing to do here.
}
/**
@@ -558,7 +863,7 @@ public class MetalBorders
}
/**
- * A border for JScrollPanes.
+ * A border for {@link JScrollPane} components.
*/
public static class ScrollPaneBorder
extends AbstractBorder
@@ -572,6 +877,7 @@ public class MetalBorders
*/
public ScrollPaneBorder()
{
+ // Nothing to do here.
}
/**
@@ -634,6 +940,45 @@ public class MetalBorders
}
/**
+ * A button border that is only visible when the mouse pointer is within
+ * the button's bounds.
+ */
+ public static class RolloverButtonBorder
+ extends MetalBorders.ButtonBorder
+ {
+ /**
+ * Creates a new border instance.
+ */
+ public RolloverButtonBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Paints the border.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param w the width.
+ * @param h the height.
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+ boolean mouseIsOver = false;
+ if (c instanceof AbstractButton)
+ {
+ ButtonModel bmodel = ((AbstractButton) c).getModel();
+ mouseIsOver = bmodel.isRollover();
+ }
+ if (mouseIsOver)
+ super.paintBorder(c, g, x, y, w, h);
+ }
+ }
+
+ /**
* This border is used in Toolbar buttons as inner border.
*/
static class RolloverMarginBorder extends AbstractBorder
@@ -646,6 +991,7 @@ public class MetalBorders
*/
public RolloverMarginBorder()
{
+ // Nothing to do here.
}
/**
@@ -693,13 +1039,14 @@ public class MetalBorders
{
/** The border's insets. */
- protected static Insets borderInsets = new Insets(2, 2, 1, 1);
+ protected static Insets borderInsets = new Insets(3, 1, 2, 1);
/**
* Constructs a new PopupMenuBorder.
*/
public PopupMenuBorder()
{
+ // Nothing to do here.
}
/**
@@ -763,13 +1110,258 @@ public class MetalBorders
// draw highlighted inner border (only top and left)
g.setColor(light);
- g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
}
}
/**
+ * A border used for the {@link JToggleButton} component.
+ *
+ * @since 1.3
+ */
+ public static class ToggleButtonBorder
+ extends ButtonBorder
+ {
+ /**
+ * Creates a new border instance.
+ */
+ public ToggleButtonBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Paints the toggle button border.
+ *
+ * @param c the component for which we paint the border
+ * @param g the Graphics context to use
+ * @param x the X coordinate of the upper left corner of c
+ * @param y the Y coordinate of the upper left corner of c
+ * @param w the width of c
+ * @param h the height of c
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+ ButtonModel bmodel = null;
+
+ if (c instanceof AbstractButton)
+ bmodel = ((AbstractButton) c).getModel();
+
+ Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
+ Color shadow = MetalLookAndFeel.getControlShadow();
+ Color light = MetalLookAndFeel.getWhite();
+ Color middle = MetalLookAndFeel.getControl();
+
+ if (c.isEnabled())
+ {
+ // draw dark border
+ g.setColor(darkShadow);
+ g.drawRect(x, y, w - 2, h - 2);
+
+ if (!bmodel.isArmed())
+ {
+ // draw light border
+ g.setColor(light);
+ g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
+ g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
+ if (bmodel.isSelected())
+ g.setColor(middle);
+ g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
+
+ // draw crossing pixels of both borders
+ g.setColor(shadow);
+ g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
+ g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
+ }
+ else
+ {
+ // draw light border
+ g.setColor(light);
+ g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
+ g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
+
+ // draw shadow border
+ g.setColor(shadow);
+ g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
+
+ // draw crossing pixels of both borders
+ g.setColor(shadow);
+ g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
+ g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
+
+ }
+ // draw corners
+ g.setColor(middle);
+ g.drawLine(x, y + h - 1, x, y + h - 1);
+ g.drawLine(x + w - 1, y, x + w - 1, y);
+ }
+ else
+ {
+ // draw disabled border
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawRect(x, y, w - 2, h - 2);
+ }
+ }
+ }
+
+ /**
+ * A border used for the {@link JToolBar} component.
+ */
+ public static class ToolBarBorder extends AbstractBorder
+ implements UIResource, SwingConstants
+ {
+ /**
+ * Creates a new border instance.
+ */
+ public ToolBarBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return getBorderInsets(c, null);
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ JToolBar tb = (JToolBar) c;
+ if (tb.getOrientation() == JToolBar.HORIZONTAL)
+ {
+ if (newInsets == null)
+ newInsets = new Insets(2, 16, 2, 2);
+ else
+ {
+ newInsets.top = 2;
+ newInsets.left = 16;
+ newInsets.bottom = 2;
+ newInsets.right = 2;
+ }
+ return newInsets;
+ }
+ else // assume JToolBar.VERTICAL
+ {
+ if (newInsets == null)
+ newInsets = new Insets(16, 2, 2, 2);
+ else
+ {
+ newInsets.top = 16;
+ newInsets.left = 2;
+ newInsets.bottom = 2;
+ newInsets.right = 2;
+ }
+ return newInsets;
+ }
+
+ }
+
+ /**
+ * Paints the border for the specified component.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param w the width.
+ * @param h the height.
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+
+ JToolBar tb = (JToolBar) c;
+ if (tb.getOrientation() == JToolBar.HORIZONTAL)
+ {
+ MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + 11, y + h - 5,
+ MetalLookAndFeel.getControlHighlight(),
+ MetalLookAndFeel.getControlDarkShadow());
+ }
+ else
+ {
+ MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + w - 5, y + 11,
+ MetalLookAndFeel.getControlHighlight(),
+ MetalLookAndFeel.getControlDarkShadow());
+ }
+ }
+
+ }
+
+ /**
+ * A border for table header cells.
+ *
+ * @since 1.3
+ */
+ public static class TableHeaderBorder extends AbstractBorder
+ {
+ /**
+ * The insets of this border.
+ */
+ // TODO: According to tests that I have done, this is really the border
+ // that should be returned by getBorderInsets(). However, the name
+ // is very distracting. Is there any deeper meaning in it?
+ protected Insets editorBorderInsets;
+
+ /**
+ * Creates a new instance of <code>TableHeaderBorder</code>.
+ */
+ public TableHeaderBorder()
+ {
+ editorBorderInsets = new Insets(1, 1, 1, 1);
+ }
+
+ /**
+ * Return the insets of this border.
+ *
+ * @return the insets of this border
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return editorBorderInsets;
+ }
+
+ /**
+ * Paints the border.
+ *
+ * @param c the component for which to paint the border
+ * @param g the graphics context to use
+ * @param x the x cooridinate of the border rectangle
+ * @param y the y cooridinate of the border rectangle
+ * @param w the width of the border rectangle
+ * @param h the height of the border rectangle
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w, int h)
+ {
+ Color dark = MetalLookAndFeel.getControlDarkShadow();
+ Color light = MetalLookAndFeel.getWhite();
+ Color old = g.getColor();
+ g.setColor(light);
+ g.drawLine(x, y, x + w - 2, y);
+ g.drawLine(x, y, x, y + h - 2);
+ g.setColor(dark);
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+ g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
+ g.setColor(old);
+ }
+ }
+
+ /**
* Returns a border for Swing buttons in the Metal Look &amp; Feel.
*
* @return a border for Swing buttons in the Metal Look &amp; Feel
@@ -785,6 +1377,40 @@ public class MetalBorders
}
return buttonBorder;
}
+
+ /**
+ * Returns a border for use with {@link JToggleButton} components.
+ *
+ * @return A border.
+ *
+ * @since 1.3
+ */
+ public static Border getToggleButtonBorder()
+ {
+ if (toggleButtonBorder == null)
+ {
+ Border outer = new ToggleButtonBorder();
+ Border inner = getMarginBorder();
+ toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource
+ (outer, inner);
+ }
+ return toggleButtonBorder;
+ }
+
+ /**
+ * Returns a border instance that is used with a {@link JInternalFrame} when
+ * it is in the iconified state.
+ *
+ * @return A border.
+ *
+ * @since 1.3
+ */
+ public static Border getDesktopIconBorder()
+ {
+ if (desktopIconBorder == null)
+ desktopIconBorder = new DesktopIconBorder();
+ return desktopIconBorder;
+ }
/**
* Returns a border for use by the {@link JTextField} component.
@@ -796,11 +1422,36 @@ public class MetalBorders
public static Border getTextFieldBorder()
{
if (textFieldBorder == null)
- textFieldBorder = new TextFieldBorder();
+ {
+ Border inner = getMarginBorder();
+ Border outer = new TextFieldBorder();
+ textFieldBorder =
+ new BorderUIResource.CompoundBorderUIResource(outer, inner);
+ }
return textFieldBorder;
}
/**
+ * Returns the border that is used for text components (except text fields,
+ * which use {@link #getTextFieldBorder}.
+ *
+ * @return the border that is used for text components
+ *
+ * @since 1.3
+ */
+ public static Border getTextBorder()
+ {
+ if (textBorder == null)
+ {
+ Border inner = getMarginBorder();
+ Border outer = new Flush3DBorder();
+ textBorder =
+ new BorderUIResource.CompoundBorderUIResource(outer, inner);
+ }
+ return textBorder;
+ }
+
+ /**
* Returns a border for Toolbar buttons in the Metal Look &amp; Feel.
*
* @return a border for Toolbar buttons in the Metal Look &amp; Feel
@@ -828,4 +1479,22 @@ public class MetalBorders
marginBorder = new BasicBorders.MarginBorder();
return marginBorder;
}
+
+ /**
+ * Returns a shared instance of a compound border for rollover buttons.
+ *
+ * @return A shared border instance.
+ */
+ static Border getRolloverBorder()
+ {
+ if (rolloverBorder == null)
+ {
+ Border outer = new MetalBorders.RolloverButtonBorder();
+ Border inner = MetalBorders.getMarginBorder();
+ rolloverBorder = new BorderUIResource.CompoundBorderUIResource(outer,
+ inner);
+ }
+ return rolloverBorder;
+ }
+
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java b/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java
new file mode 100644
index 00000000000..e6fb22e929f
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java
@@ -0,0 +1,86 @@
+/* MetalButtonListener.java
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.plaf.metal;
+
+import java.beans.PropertyChangeEvent;
+
+import javax.swing.AbstractButton;
+import javax.swing.plaf.UIResource;
+import javax.swing.plaf.basic.BasicButtonListener;
+
+/**
+ * A listener for buttons under the {@link MetalLookAndFeel}.
+ *
+ * @see MetalButtonUI#createButtonListener
+ */
+class MetalButtonListener extends BasicButtonListener
+{
+
+ /**
+ * Creates a new instance.
+ *
+ * @param button the button.
+ */
+ public MetalButtonListener(AbstractButton button)
+ {
+ super(button);
+ }
+
+ /**
+ * Handles property change events.
+ *
+ * @param e the event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ super.propertyChange(e);
+ if (e.getPropertyName().equals(
+ AbstractButton.ROLLOVER_ENABLED_CHANGED_PROPERTY))
+ {
+ AbstractButton b = (AbstractButton) e.getSource();
+ if (b.getBorder() instanceof UIResource)
+ {
+ if (Boolean.TRUE.equals(e.getNewValue()))
+ b.setBorder(MetalBorders.getRolloverBorder());
+ else if (Boolean.FALSE.equals(e.getNewValue()))
+ b.setBorder(MetalBorders.getButtonBorder());
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java
index 0dac5ec3953..02c39c1499e 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java
@@ -39,18 +39,23 @@ exception statement from your version. */
package javax.swing.plaf.metal;
import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
import javax.swing.AbstractButton;
+import javax.swing.JButton;
import javax.swing.JComponent;
-import javax.swing.JToolBar;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.UIResource;
+import javax.swing.plaf.basic.BasicButtonListener;
import javax.swing.plaf.basic.BasicButtonUI;
/**
- * The Metal Look &amp; Feel implementation for
- * {@link javax.swing.AbstractButton}s.
+ * A UI delegate for the {@link JButton} component.
*
* @author Roman Kennke (roman@kennke.org)
*/
@@ -58,27 +63,25 @@ public class MetalButtonUI
extends BasicButtonUI
{
- /** The cached MetalButtonUI instance. */
- private static MetalButtonUI instance = null;
-
- /** The color for the focus border. */
+ /** The color used to draw the focus rectangle around the text and/or icon. */
protected Color focusColor;
-
- /** The color that indicates a selected button. */
+
+ /** The background color for the button when it is pressed. */
protected Color selectColor;
/** The color for disabled button labels. */
protected Color disabledTextColor;
/**
- * Creates a new instance of MetalButtonUI.
+ * Creates a new instance.
*/
public MetalButtonUI()
{
super();
- focusColor = getFocusColor();
- selectColor = getSelectColor();
- disabledTextColor = getDisabledTextColor();
+ UIDefaults def = UIManager.getLookAndFeelDefaults();
+ focusColor = def.getColor(getPropertyPrefix() + "focus");
+ selectColor = def.getColor(getPropertyPrefix() + "select");
+ disabledTextColor = def.getColor(getPropertyPrefix() + "disabledText");
}
/**
@@ -88,8 +91,7 @@ public class MetalButtonUI
*/
protected Color getFocusColor()
{
- UIDefaults def = UIManager.getLookAndFeelDefaults();
- return def.getColor(getPropertyPrefix() + ".focus");
+ return focusColor;
}
/**
@@ -99,8 +101,7 @@ public class MetalButtonUI
*/
protected Color getSelectColor()
{
- UIDefaults def = UIManager.getLookAndFeelDefaults();
- return def.getColor(getPropertyPrefix() + ".select");
+ return selectColor;
}
/**
@@ -110,36 +111,123 @@ public class MetalButtonUI
*/
protected Color getDisabledTextColor()
{
- UIDefaults def = UIManager.getLookAndFeelDefaults();
- return def.getColor(getPropertyPrefix() + ".disabledText");
+ return disabledTextColor;
}
/**
- * Returns an instance of MetalButtonUI.
- *
- * @param component a button for which a UI instance should be returned
+ * Returns a UI delegate for the specified component.
+ *
+ * @param c the component (should be a subclass of {@link AbstractButton}).
+ *
+ * @return A new instance of <code>MetalButtonUI</code>.
*/
- public static ComponentUI createUI(JComponent component)
- {
- if (instance == null)
- instance = new MetalButtonUI();
- return instance;
+ public static ComponentUI createUI(JComponent c) {
+ return new MetalButtonUI();
}
/**
- * Install the Look &amp; Feel defaults for Buttons.
- *
- * @param button the button for which to install the Look &amp; Feel
+ * Installs the default settings for the specified button.
+ *
+ * @param button the button.
+ *
+ * @see #uninstallDefaults(AbstractButton)
*/
public void installDefaults(AbstractButton button)
{
super.installDefaults(button);
+ if (button.isRolloverEnabled())
+ {
+ if (button.getBorder() instanceof UIResource)
+ button.setBorder(MetalBorders.getRolloverBorder());
+ }
+ }
+
+ /**
+ * Removes the defaults added by {@link #installDefaults(AbstractButton)}.
+ */
+ public void uninstallDefaults(AbstractButton button)
+ {
+ super.uninstallDefaults(button);
+ if (button.getBorder() instanceof UIResource)
+ button.setBorder(null);
+ }
- UIDefaults defaults = UIManager.getLookAndFeelDefaults();
- button.setFont(defaults.getFont("Button.font"));
+ /**
+ * Returns a button listener for the specified button.
+ *
+ * @param button the button.
+ *
+ * @return A button listener.
+ */
+ protected BasicButtonListener createButtonListener(AbstractButton button)
+ {
+ return new MetalButtonListener(button);
+ }
- if (button.getParent() instanceof JToolBar)
- button.setBorder(MetalBorders.getToolbarButtonBorder());
+ /**
+ * Paints the background of the button to indicate that it is in the "pressed"
+ * state.
+ *
+ * @param g the graphics context.
+ * @param b the button.
+ */
+ protected void paintButtonPressed(Graphics g, AbstractButton b)
+ {
+ if (b.isContentAreaFilled())
+ {
+ Rectangle area = b.getVisibleRect();
+ g.setColor(selectColor);
+ g.fillRect(area.x, area.y, area.width, area.height);
+ }
+ }
+
+ /**
+ * Paints the focus rectangle around the button text and/or icon.
+ *
+ * @param g the graphics context.
+ * @param b the button.
+ * @param viewRect the button bounds.
+ * @param textRect the text bounds.
+ * @param iconRect the icon bounds.
+ */
+ protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect,
+ Rectangle textRect, Rectangle iconRect) {
+ if (b.isEnabled() && b.hasFocus() && b.isFocusPainted())
+ {
+ Color savedColor = g.getColor();
+ g.setColor(getFocusColor());
+ Rectangle focusRect = iconRect.union(textRect);
+ g.drawRect(focusRect.x - 1, focusRect.y,
+ focusRect.width + 1, focusRect.height);
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * Paints the button text.
+ *
+ * @param g the graphics context.
+ * @param c the button.
+ * @param textRect the text bounds.
+ * @param text the text to display.
+ */
+ protected void paintText(Graphics g, JComponent c, Rectangle textRect,
+ String text)
+ {
+ AbstractButton b = (AbstractButton) c;
+ Font f = b.getFont();
+ g.setFont(f);
+ FontMetrics fm = g.getFontMetrics(f);
+
+ if (b.isEnabled())
+ {
+ g.setColor(b.getForeground());
+ g.drawString(text, textRect.x, textRect.y + fm.getAscent());
+ }
+ else
+ {
+ g.setColor(getDisabledTextColor());
+ g.drawString(text, textRect.x, textRect.y + fm.getAscent());
+ }
}
-
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java
index 3f3c9ce58b3..6b9f31b85b6 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java
@@ -38,10 +38,8 @@ exception statement from your version. */
package javax.swing.plaf.metal;
-import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
-
import java.io.Serializable;
import javax.swing.Icon;
@@ -49,8 +47,7 @@ import javax.swing.JCheckBox;
import javax.swing.plaf.UIResource;
/**
- * An {@link Icon} implementation for {@link JCheckBox}es in the
- * Metal Look &amp; Feel.
+ * An {@link Icon} used by the {@link MetalCheckBoxUI} class.
*
* @author Roman Kennke (roman@kennke.org)
*/
@@ -79,7 +76,10 @@ public class MetalCheckBoxIcon
*/
protected void drawCheck(Component c, Graphics g, int x, int y)
{
- g.setColor(Color.BLACK);
+ if (c.isEnabled())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
g.drawLine(3 + x, 5 + y, 3 + x, 9 + y);
g.drawLine(4 + x, 5 + y, 4 + x, 9 + y);
g.drawLine(5 + x, 7 + y, 9 + x, 3 + y);
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java
index c46cb5f2fb1..b4f6f0a56cd 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java
@@ -44,8 +44,7 @@ import javax.swing.UIDefaults;
import javax.swing.plaf.ComponentUI;
/**
- * A UI delegate for the {@link JCheckBox} component under the
- * {@link MetalLookAndFeel}.
+ * A UI delegate for the {@link JCheckBox} component.
*/
public class MetalCheckBoxUI
extends MetalRadioButtonUI
@@ -64,11 +63,11 @@ public class MetalCheckBoxUI
}
/**
- * Returns an instance of MetalCheckBoxUI.
+ * Returns a shared instance of <code>MetalCheckBoxUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalCheckBoxUI
+ * @return A shared instance of <code>MetalCheckBoxUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java
new file mode 100644
index 00000000000..6993e18e9b9
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java
@@ -0,0 +1,241 @@
+/* MetalComboBoxButton.java
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.plaf.metal;
+
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+
+import javax.swing.CellRendererPane;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JList;
+import javax.swing.SwingUtilities;
+
+/**
+ * A button used by the {@link MetalComboBoxUI} class.
+ */
+public class MetalComboBoxButton extends JButton {
+
+ /** A reference to the JComboBox that the button belongs to. */
+ protected JComboBox comboBox;
+
+ /** A reference to the JList. */
+ protected JList listBox;
+
+ /** ??? */
+ protected CellRendererPane rendererPane;
+
+ /** The button icon. */
+ protected Icon comboIcon;
+
+ /** Display just the icon, or the icon plus the label. */
+ protected boolean iconOnly;
+
+ /**
+ * Creates a new button.
+ *
+ * @param cb the combo that the button is used for (<code>null</code> not
+ * permitted).
+ * @param i the icon displayed on the button.
+ * @param pane the rendering pane.
+ * @param list the list.
+ */
+ public MetalComboBoxButton(JComboBox cb, Icon i, CellRendererPane pane,
+ JList list)
+ {
+ this(cb, i, cb.isEditable(), pane, list);
+ }
+
+ /**
+ * Creates a new button.
+ *
+ * @param cb the combo that the button is used for (<code>null</code> not
+ * permitted).
+ * @param i the icon displayed on the button.
+ * @parma onlyIcon a flag that specifies whether the button displays only an
+ * icon, or text as well.
+ * @param pane the rendering pane.
+ * @param list the list.
+ */
+ public MetalComboBoxButton(JComboBox cb, Icon i, boolean onlyIcon,
+ CellRendererPane pane, JList list)
+ {
+ super();
+ if (cb == null)
+ throw new NullPointerException("Null 'cb' argument");
+ comboBox = cb;
+ comboIcon = i;
+ iconOnly = onlyIcon;
+ listBox = list;
+ rendererPane = pane;
+ }
+
+ /**
+ * Returns the combo box that the button is used with.
+ *
+ * @return The combo box.
+ */
+ public final JComboBox getComboBox()
+ {
+ return comboBox;
+ }
+
+ /**
+ * Sets the combo box that the button is used with.
+ *
+ * @param cb the combo box.
+ */
+ public final void setComboBox(JComboBox cb)
+ {
+ comboBox = cb;
+ }
+
+ /**
+ * Returns the icon displayed by the button. By default, this will be an
+ * instance of {@link MetalComboBoxIcon}.
+ *
+ * @return The icon displayed by the button.
+ */
+ public final Icon getComboIcon()
+ {
+ return comboIcon;
+ }
+
+ /**
+ * Sets the icon displayed by the button.
+ *
+ * @param i the icon.
+ */
+ public final void setComboIcon(Icon i)
+ {
+ comboIcon = i;
+ }
+
+ /**
+ * Returns a flag that controls whether the button displays an icon only,
+ * or text as well.
+ *
+ * @return A boolean.
+ */
+ public final boolean isIconOnly()
+ {
+ return iconOnly;
+ }
+
+ /**
+ * Sets the flag that controls whether the button displays an icon only,
+ * or text as well.
+ *
+ * @param isIconOnly the flag.
+ */
+ public final void setIconOnly(boolean isIconOnly)
+ {
+ iconOnly = isIconOnly;
+ }
+
+ /**
+ * Returns <code>false</code>, to indicate that this component is not part
+ * of the focus traversal group.
+ *
+ * @return <code>false</code>
+ */
+ public boolean isFocusTraversable()
+ {
+ return false;
+ }
+
+ /**
+ * Enables or disables the button.
+ *
+ * @param enabled the new status.
+ */
+ public void setEnabled(boolean enabled)
+ {
+ super.setEnabled(enabled);
+ // TODO: figure out what this might need to be used for
+ // perhaps it has something to do with the button's icon and/or border?
+ }
+
+ /**
+ * Paints the component.
+ *
+ * @param g the graphics device.
+ */
+ public void paintComponent(Graphics g)
+ {
+ super.paintComponent(g);
+ if (iconOnly)
+ {
+ Rectangle bounds = getBounds();
+ int x = (bounds.width - comboIcon.getIconWidth()) / 2;
+ int y = (bounds.height - comboIcon.getIconHeight()) / 2;
+ comboIcon.paintIcon(comboBox, g, x, y);
+ }
+ else
+ {
+ Object selected = comboBox.getModel().getSelectedItem();
+ if (selected == null)
+ selected = "";
+ Rectangle bounds = comboBox.getBounds();
+ Rectangle innerArea = SwingUtilities.calculateInnerArea(this, null);
+ Insets insets = comboBox.getInsets();
+ Rectangle renderArea = new Rectangle(innerArea.x, innerArea.y,
+ innerArea.width - comboIcon.getIconWidth() - 4, innerArea.height);
+ Component cellRenderer
+ = comboBox.getRenderer().getListCellRendererComponent(this.listBox,
+ selected, comboBox.getSelectedIndex(), false, false);
+ cellRenderer.setBackground(comboBox.getBackground());
+ cellRenderer.setEnabled(comboBox.isEnabled());
+ rendererPane.paintComponent(g, cellRenderer, this, renderArea);
+ if (comboBox.hasFocus())
+ {
+ g.setColor(MetalLookAndFeel.getFocusColor());
+ g.drawRect(innerArea.x, innerArea.y - 1, innerArea.width - 1,
+ innerArea.height);
+ }
+ int iconX = bounds.width - insets.right - comboIcon.getIconWidth() - 7;
+ int iconY = insets.top
+ + (bounds.height - comboIcon.getIconHeight()) / 2;
+ comboIcon.paintIcon(comboBox, g, iconX, iconY);
+ }
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java
new file mode 100644
index 00000000000..a531079cb1d
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java
@@ -0,0 +1,143 @@
+/* MetalComboBoxEditor.java
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.plaf.metal;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Insets;
+
+import javax.swing.JTextField;
+import javax.swing.plaf.basic.BasicComboBoxEditor;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+import javax.swing.plaf.metal.MetalBorders.Flush3DBorder;
+
+/**
+ * An editor used by the {@link MetalComboBoxUI} class.
+ */
+public class MetalComboBoxEditor extends BasicComboBoxEditor
+{
+ /**
+ * A border used for the {@link JTextField} component.
+ */
+ static class MetalComboBoxEditorBorder extends Flush3DBorder
+ {
+ /**
+ * Creates a new border instance.
+ */
+ public MetalComboBoxEditorBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Paints the border for the specified component.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param w the width.
+ * @param h the height.
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+ Color savedColor = g.getColor();
+ if (c.isEnabled())
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y, x, y + h - 2);
+ g.drawLine(x + 2, y + h - 2, x + w - 1, y + h - 2);
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+ g.setColor(savedColor);
+ }
+
+ /**
+ * Measures the width of this border.
+ *
+ * @param c the component whose border is to be measured.
+ *
+ * @return an Insets object whose <code>left</code>, <code>right</code>,
+ * <code>top</code> and <code>bottom</code> fields indicate the
+ * width of the border at the respective edge, which is zero
+ * for the default implementation provided by AbstractButton.
+ *
+ * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return editorBorderInsets;
+ }
+ }
+
+ /**
+ * A subclass of {@link MetalComboBoxEditor} that implements the
+ * {@link javax.swing.plaf.UIResource} interface.
+ */
+ public static class UIResource extends MetalComboBoxEditor
+ implements javax.swing.plaf.UIResource
+ {
+ /**
+ * Creates a new instance.
+ */
+ public UIResource()
+ {
+ // Nothing to do here.
+ }
+ }
+
+ /** The editor's border insets. */
+ protected static Insets editorBorderInsets = new Insets(4, 2, 4, 0);
+
+ /**
+ * Creates a new editor.
+ */
+ public MetalComboBoxEditor()
+ {
+ super();
+ editor.setBorder(new MetalComboBoxEditorBorder());
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java
index ce4fa7d32ce..f21c5af6136 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java
@@ -1,4 +1,4 @@
-/* MetalComboBoxButton.java
+/* MetalComboBoxIcon.java
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -88,10 +88,11 @@ public class MetalComboBoxIcon implements Icon, Serializable {
*/
public void paintIcon(Component c, Graphics g, int x, int y)
{
- // TODO: work out whether/how the icon changes with different component
- // states (and also different metal themes)
Color savedColor = g.getColor();
- g.setColor(Color.black);
+ if (c.isEnabled())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
for (int i = 0; i < 5; i++)
g.drawLine(x + i, y + i, x + 9 - i, y + i);
g.setColor(savedColor);
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java
index 28c279d8ed6..a43ee3cb04f 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java
@@ -38,20 +38,134 @@ exception statement from your version. */
package javax.swing.plaf.metal;
-import java.util.HashMap;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.awt.Rectangle;
+import java.awt.event.MouseEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.swing.CellRendererPane;
+import javax.swing.ComboBoxEditor;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicComboBoxUI;
+import javax.swing.plaf.basic.BasicComboPopup;
+import javax.swing.plaf.basic.ComboPopup;
-public class MetalComboBoxUI
- extends BasicComboBoxUI
-{
- /** The UI instances for JComboBoxes. */
- private static HashMap instances = null;
+/**
+ * A UI delegate for the {@link JComboBox} component.
+ */
+public class MetalComboBoxUI extends BasicComboBoxUI
+{
+ /**
+ * A layout manager that arranges the editor component (if active) and the
+ * button that make up the combo box.
+ */
+ public class MetalComboBoxLayoutManager
+ extends BasicComboBoxUI.ComboBoxLayoutManager
+ {
+ /**
+ * Creates a new instance of the layout manager.
+ */
+ public MetalComboBoxLayoutManager()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Arranges the editor (if visible) and button that comprise the combo
+ * box.
+ *
+ * @param parent the parent.
+ */
+ public void layoutContainer(Container parent)
+ {
+ JComboBox cb = (JComboBox) parent;
+ if (!cb.isEditable())
+ {
+ Rectangle bounds = parent.getBounds();
+ arrowButton.setBounds(0, 0, bounds.width, bounds.height);
+ }
+ else
+ superLayout(parent);
+ }
+
+ /**
+ * Calls the <code>layoutContainer(Container)</code> method in the super
+ * class.
+ *
+ * @param parent the container.
+ */
+ public void superLayout(Container parent)
+ {
+ super.layoutContainer(parent);
+ }
+ }
+
+ /**
+ * A listener used to handle property changes in the {@link JComboBox}
+ * component, to ensure that the UI delegate accurately reflects the current
+ * state in the rendering onscreen.
+ */
+ public class MetalPropertyChangeListener
+ extends BasicComboBoxUI.PropertyChangeHandler
+ {
+ /**
+ * Creates a new listener.
+ */
+ public MetalPropertyChangeListener()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Handles a property change event, updating the UI components as
+ * appropriate.
+ *
+ * @param e the event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals("editable"))
+ editablePropertyChanged(e);
+ super.propertyChange(e);
+ }
+ }
/**
+ * A popup menu for the combo-box.
+ *
+ * @see #createPopup()
+ *
+ * @deprecated 1.4
+ */
+ public class MetalComboPopup extends BasicComboPopup
+ {
+ /**
+ * Creates a new popup.
+ *
+ * @param cBox the combo box.
+ */
+ public MetalComboPopup(JComboBox cBox)
+ {
+ super(cBox);
+ }
+
+ public void delegateFocus(MouseEvent e)
+ {
+ super.delegateFocus(e);
+ }
+ }
+
+ /**
* Constructs a new instance of MetalComboBoxUI.
*/
public MetalComboBoxUI()
@@ -68,19 +182,135 @@ public class MetalComboBoxUI
*/
public static ComponentUI createUI(JComponent component)
{
- if (instances == null)
- instances = new HashMap();
-
- Object o = instances.get(component);
- MetalComboBoxUI instance;
- if (o == null)
+ return new MetalComboBoxUI();
+ }
+
+ /**
+ * Creates an editor for the combo box.
+ *
+ * @return An editor.
+ */
+ protected ComboBoxEditor createEditor()
+ {
+ return new MetalComboBoxEditor.UIResource();
+ }
+
+ /**
+ * Creates a popup for the combo box.
+ *
+ * @return A popup.
+ */
+ protected ComboPopup createPopup()
+ {
+ return new MetalComboPopup(comboBox);
+ }
+
+ /**
+ * Creates a new button for use in rendering the JComboBox.
+ *
+ * @return A button.
+ */
+ protected JButton createArrowButton()
+ {
+ JButton button = new MetalComboBoxButton(comboBox, new MetalComboBoxIcon(),
+ new CellRendererPane(), listBox);
+ button.setMargin(new Insets(0, 1, 1, 3));
+ return button;
+ }
+
+ /**
+ * Creates a new property change listener.
+ *
+ * @return A new property change listener.
+ */
+ public PropertyChangeListener createPropertyChangeListener()
+ {
+ return new MetalPropertyChangeListener();
+ }
+
+ public void paint(Graphics g, JComponent c)
+ {
+ // do nothing, the button and text field are painted elsewhere
+ }
+
+ /**
+ * Updates the button and text field to reflect a change in the 'editable'
+ * property.
+ *
+ * @param e the event.
+ *
+ * @deprecated 1.4
+ */
+ protected void editablePropertyChanged(PropertyChangeEvent e)
+ {
+ if (arrowButton instanceof MetalComboBoxButton)
+ {
+ MetalComboBoxButton b = (MetalComboBoxButton) arrowButton;
+ b.setIconOnly(comboBox.isEditable());
+ }
+ if (comboBox.isEditable())
{
- instance = new MetalComboBoxUI();
- instances.put(component, instance);
+ arrowButton.setText(null);
+ if (editor != null)
+ editor.setVisible(true);
}
else
- instance = (MetalComboBoxUI) o;
-
- return instance;
+ {
+ String text = "";
+ Object selected = comboBox.getSelectedItem();
+ if (selected != null)
+ text = selected.toString();
+ arrowButton.setText(text);
+ if (editor != null)
+ editor.setVisible(true);
+ }
+ }
+
+ /**
+ * Creates a new layout manager for the UI delegate.
+ *
+ * @return A new layout manager.
+ */
+ protected LayoutManager createLayoutManager()
+ {
+ return new MetalComboBoxLayoutManager();
+ }
+
+ /**
+ * Not used in Classpath.
+ *
+ * @deprecated 1.4
+ */
+ protected void removeListeners()
+ {
+ // no longer used in JDK 1.4
+ }
+
+ /**
+ * Returns the minimum size for the combo.
+ *
+ * @param c the component
+ *
+ * @return The minimum size for the combo box.
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ Dimension d = getDisplaySize();
+ MetalComboBoxButton b = (MetalComboBoxButton) arrowButton;
+ Insets insets = b.getInsets();
+ int insetsH = insets.top + insets.bottom;
+ int insetsW = insets.left + insets.right;
+ if (!comboBox.isEditable())
+ {
+ Icon icon = b.getComboIcon();
+ int iconWidth = icon.getIconWidth() + 6;
+ return new Dimension(d.width + insetsW + iconWidth, d.height + insetsH);
+ }
+ else
+ // FIXME: the following dimensions pass most of the Mauve tests, but
+ // I don't yet understand the logic behind this...it is probably wrong
+ return new Dimension(d.width + insetsW + (d.height + insetsH) - 4,
+ d.height + insetsH + 1);
}
+
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java
index 00870545bc6..ecbb76e6e7a 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java
@@ -39,9 +39,13 @@ exception statement from your version. */
package javax.swing.plaf.metal;
import javax.swing.JComponent;
+import javax.swing.JInternalFrame;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicDesktopIconUI;
+/**
+ * A UI delegate for the {@link JInternalFrame.JDesktopIcon} component.
+ */
public class MetalDesktopIconUI
extends BasicDesktopIconUI
{
@@ -51,7 +55,7 @@ public class MetalDesktopIconUI
private static MetalDesktopIconUI instance = null;
/**
- * Constructs a new instance of MetalDesktopIconUI.
+ * Constructs a new instance of <code>MetalDesktopIconUI</code>.
*/
public MetalDesktopIconUI()
{
@@ -59,11 +63,11 @@ public class MetalDesktopIconUI
}
/**
- * Returns an instance of MetalDesktopIconUI.
+ * Returns a shared instance of <code>MetalDesktopIconUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalDesktopIconUI
+ * @return A shared instance of <code>MetalDesktopIconUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java
new file mode 100644
index 00000000000..3a2e1c13508
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java
@@ -0,0 +1,430 @@
+/* MetalFileChooserUI.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.plaf.metal;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.util.List;
+
+import javax.swing.AbstractAction;
+import javax.swing.AbstractListModel;
+import javax.swing.ComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JList;
+import javax.swing.UIManager;
+import javax.swing.filechooser.FileFilter;
+import javax.swing.filechooser.FileSystemView;
+import javax.swing.filechooser.FileView;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicFileChooserUI;
+
+
+/**
+ * A UI delegate for the {@link JFileChooser} component. This class is only
+ * partially implemented and is not usable yet.
+ */
+public class MetalFileChooserUI extends BasicFileChooserUI
+{
+ /**
+ * A combo box model containing the selected directory and all its parent
+ * directories.
+ */
+ protected class DirectoryComboBoxModel extends AbstractListModel
+ implements ComboBoxModel
+ {
+ /** Storage for the items in the model. */
+ private List items;
+
+ /** The index of the selected item. */
+ private int selectedIndex;
+
+ /**
+ * Creates a new model.
+ */
+ public DirectoryComboBoxModel()
+ {
+ items = new java.util.ArrayList();
+ selectedIndex = -1;
+ }
+
+ /**
+ * Returns the number of items in the model.
+ *
+ * @return The number of items in the model.
+ */
+ public int getSize()
+ {
+ return items.size();
+ }
+
+ /**
+ * Returns the item at the specified index.
+ *
+ * @param index the item index.
+ *
+ * @return The item.
+ */
+ public Object getElementAt(int index)
+ {
+ return items.get(index);
+ }
+
+ /**
+ * Returns the depth of the item at the given <code>index</code>.
+ *
+ * @param index the item index.
+ *
+ * @return The depth.
+ */
+ public int getDepth(int index)
+ {
+ return Math.max(index, 0);
+ }
+
+ /**
+ * Returns the selected item, or <code>null</code> if no item is selected.
+ *
+ * @return The selected item, or <code>null</code>.
+ */
+ public Object getSelectedItem()
+ {
+ if (selectedIndex >= 0)
+ return items.get(selectedIndex);
+ else
+ return null;
+ }
+
+ /**
+ * Sets the selected item. This clears all the directories from the
+ * existing list, and repopulates it with the new selected directory
+ * and all its parent directories.
+ *
+ * @param selectedDirectory the selected directory.
+ */
+ public void setSelectedItem(Object selectedDirectory)
+ {
+ items.clear();
+ FileSystemView fsv = getFileChooser().getFileSystemView();
+ File parent = (File) selectedDirectory;
+ while (parent != null)
+ {
+ items.add(0, parent);
+ parent = fsv.getParentDirectory(parent);
+ }
+ selectedIndex = items.indexOf(selectedDirectory);
+ fireContentsChanged(this, 0, items.size() - 1);
+ }
+
+ }
+
+ /**
+ * Handles changes to the selection in the directory combo box.
+ */
+ protected class DirectoryComboBoxAction extends AbstractAction
+ {
+ /**
+ * Creates a new action.
+ */
+ protected DirectoryComboBoxAction()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Handles the action event.
+ *
+ * @param e the event.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ JFileChooser fc = getFileChooser();
+ fc.setCurrentDirectory((File) directoryModel.getSelectedItem());
+ }
+ }
+
+ /**
+ * A renderer for the files and directories in the file chooser.
+ */
+ protected class FileRenderer extends DefaultListCellRenderer
+ {
+
+ /**
+ * Creates a new renderer.
+ */
+ protected FileRenderer()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns a component that can render the specified value.
+ *
+ * @param list the list.
+ * @param value the value (a {@link File}).
+ * @param index the index.
+ * @param isSelected is the item selected?
+ * @param cellHasFocus does the item have the focus?
+ *
+ * @return The renderer.
+ */
+ public Component getListCellRendererComponent(JList list, Object value,
+ int index, boolean isSelected, boolean cellHasFocus)
+ {
+ FileView v = getFileView(getFileChooser());
+ File f = (File) value;
+ setText(v.getName(f));
+ setIcon(v.getIcon(f));
+ if (isSelected)
+ {
+ setBackground(list.getSelectionBackground());
+ setForeground(list.getSelectionForeground());
+ }
+ else
+ {
+ setBackground(list.getBackground());
+ setForeground(list.getForeground());
+ }
+
+ setEnabled(list.isEnabled());
+ setFont(list.getFont());
+
+ if (cellHasFocus)
+ setBorder(UIManager.getBorder("List.focusCellHighlightBorder"));
+ else
+ setBorder(noFocusBorder);
+ return this;
+ }
+ }
+
+ /**
+ * A combo box model for the file selection filters.
+ */
+ protected class FilterComboBoxModel
+ extends AbstractListModel
+ implements ComboBoxModel, PropertyChangeListener
+ {
+
+ /** Storage for the filters in the model. */
+ protected FileFilter[] filters;
+
+ /** The index of the selected file filter. */
+ private int selectedIndex;
+
+ /**
+ * Creates a new model.
+ */
+ protected FilterComboBoxModel()
+ {
+ filters = new FileFilter[1];
+ filters[0] = getAcceptAllFileFilter(getFileChooser());
+ selectedIndex = 0;
+ }
+
+ /**
+ * Handles property changes.
+ *
+ * @param e the property change event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
+ {
+ selectedIndex = -1;
+ FileFilter selected = (FileFilter) e.getNewValue();
+ for (int i = 0; i < filters.length; i++)
+ if (filters[i].equals(selected))
+ selectedIndex = i;
+ fireContentsChanged(this, -1, -1);
+ }
+ else if (e.getPropertyName().equals(
+ JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY))
+ {
+ // repopulate list
+ JFileChooser fc = getFileChooser();
+ FileFilter[] choosableFilters = fc.getChoosableFileFilters();
+ filters = choosableFilters;
+ fireContentsChanged(this, 0, filters.length);
+ }
+ }
+
+ /**
+ * Sets the selected filter.
+ *
+ * @param filter the filter.
+ */
+ public void setSelectedItem(Object filter)
+ {
+ // change the filter in the file chooser and let the property change
+ // event trigger the change to the selected item
+ getFileChooser().setFileFilter((FileFilter) filter);
+ }
+
+ /**
+ * Returns the selected file filter.
+ *
+ * @return The selected file filter.
+ */
+ public Object getSelectedItem()
+ {
+ if (selectedIndex >= 0)
+ return filters[selectedIndex];
+ return null;
+ }
+
+ /**
+ * Returns the number of items in the model.
+ *
+ * @return The number of items in the model.
+ */
+ public int getSize()
+ {
+ return filters.length;
+ }
+
+ /**
+ * Returns the item at the specified index.
+ *
+ * @param index the item index.
+ *
+ * @return The item at the specified index.
+ */
+ public Object getElementAt(int index)
+ {
+ return filters[index];
+ }
+
+ }
+
+ /**
+ * A renderer for the items in the file filter combo box.
+ */
+ public class FilterComboBoxRenderer extends DefaultListCellRenderer
+ {
+ /**
+ * Creates a new renderer.
+ */
+ public FilterComboBoxRenderer()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns a component that can be used to paint the given value within
+ * the list.
+ *
+ * @param list the list.
+ * @param value the value (a {@link FileFilter}).
+ * @param index the item index.
+ * @param isSelected is the item selected?
+ * @param cellHasFocus does the list cell have focus?
+ *
+ * @return A component.
+ */
+ public Component getListCellRendererComponent(JList list, Object value,
+ int index, boolean isSelected, boolean cellHasFocus)
+ {
+ FileFilter filter = (FileFilter) value;
+ return super.getListCellRendererComponent(list, filter.getDescription(),
+ index, isSelected, cellHasFocus);
+ }
+ }
+
+ /** The model for the directory combo box. */
+ DirectoryComboBoxModel directoryModel;
+
+ /**
+ * A factory method that returns a UI delegate for the specified
+ * component.
+ *
+ * @param c the component (which should be a {@link JFileChooser}).
+ */
+ public static ComponentUI createUI(JComponent c)
+ {
+ JFileChooser chooser = (JFileChooser) c;
+ return new MetalFileChooserUI(chooser);
+ }
+
+ /**
+ * Creates a new instance of this UI delegate.
+ *
+ * @param filechooser the file chooser component.
+ */
+ public MetalFileChooserUI(JFileChooser filechooser)
+ {
+ super(filechooser);
+ }
+
+ /**
+ * Creates and returns a new instance of {@link DirectoryComboBoxModel}.
+ *
+ * @return A new instance of {@link DirectoryComboBoxModel}.
+ */
+ protected MetalFileChooserUI.DirectoryComboBoxModel
+ createDirectoryComboBoxModel(JFileChooser fc)
+ {
+ return new DirectoryComboBoxModel();
+ }
+
+ /**
+ * Creates and returns a new instance of {@link FilterComboBoxModel}.
+ *
+ * @return A new instance of {@link FilterComboBoxModel}.
+ */
+ protected FilterComboBoxModel createFilterComboBoxModel()
+ {
+ return new FilterComboBoxModel();
+ }
+
+ /**
+ * Creates and returns a new instance of {@link FilterComboBoxRenderer}.
+ *
+ * @return A new instance of {@link FilterComboBoxRenderer}.
+ */
+ protected MetalFileChooserUI.FilterComboBoxRenderer
+ createFilterComboBoxRenderer()
+ {
+ return new FilterComboBoxRenderer();
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java
index d8c77432653..6f4feccfc37 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java
@@ -43,9 +43,11 @@ import java.awt.Component;
import java.awt.Graphics;
import java.io.Serializable;
+import javax.swing.AbstractButton;
import javax.swing.Icon;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JFileChooser;
import javax.swing.JInternalFrame;
import javax.swing.JRadioButton;
import javax.swing.JRadioButtonMenuItem;
@@ -75,6 +77,7 @@ public class MetalIconFactory implements Serializable
*/
public CheckBoxMenuItemIcon()
{
+ // Nothing to do here.
}
/**
@@ -137,6 +140,385 @@ public class MetalIconFactory implements Serializable
}
/**
+ * An icon used for the "detail view" button on a {@link JFileChooser} under
+ * the {@link MetalLookAndFeel}.
+ *
+ * @see MetalIconFactory#getFileChooserDetailViewIcon()
+ */
+ private static class FileChooserDetailViewIcon implements Icon, Serializable
+ {
+
+ /**
+ * Creates a new icon.
+ */
+ public FileChooserDetailViewIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 18;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 18;
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ g.setColor(MetalLookAndFeel.getBlack());
+
+ // file 1 outline
+ g.drawLine(x + 2, y + 2, x + 5, y + 2);
+ g.drawLine(x + 6, y + 3, x + 6, y + 7);
+ g.drawLine(x + 2, y + 7, x + 6, y + 7);
+ g.drawLine(x + 2, y + 2, x + 2, y + 7);
+
+ // file 2 outline
+ g.drawLine(x + 2, y + 10, x + 5, y + 10);
+ g.drawLine(x + 6, y + 11, x + 6, y + 15);
+ g.drawLine(x + 2, y + 15, x + 6, y + 15);
+ g.drawLine(x + 2, y + 10, x + 2, y + 15);
+
+ // detail lines
+ g.drawLine(x + 8, y + 5, x + 15, y + 5);
+ g.drawLine(x + 8, y + 13, x + 15, y + 13);
+
+ // fill files
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 3, y + 3, 3, 4);
+ g.fillRect(x + 3, y + 11, 3, 4);
+
+ // highlight files
+ g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
+ g.drawLine(x + 4, y + 4, x + 4, y + 5);
+ g.drawLine(x + 4, y + 12, x + 4, y + 13);
+
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon used for the "home folder" button on a {@link JFileChooser} under
+ * the {@link MetalLookAndFeel}.
+ *
+ * @see MetalIconFactory#getFileChooserHomeFolderIcon()
+ */
+ private static class FileChooserHomeFolderIcon implements Icon, Serializable
+ {
+
+ /**
+ * Creates a new icon.
+ */
+ public FileChooserHomeFolderIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 18;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 18;
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ g.setColor(MetalLookAndFeel.getBlack());
+
+ // roof
+ g.drawLine(x + 1, y + 8, x + 8, y + 1);
+ g.drawLine(x + 8, y + 1, x + 15, y + 8);
+
+ // base of house
+ g.drawLine(x + 3, y + 6, x + 3, y + 15);
+ g.drawLine(x + 3, y + 15, x + 13, y + 15);
+ g.drawLine(x + 13, y + 6, x + 13, y + 15);
+
+ // door frame
+ g.drawLine(x + 6, y + 9, x + 6, y + 15);
+ g.drawLine(x + 6, y + 9, x + 10, y + 9);
+ g.drawLine(x + 10, y + 9, x + 10, y + 15);
+
+ // chimney
+ g.drawLine(x + 11, y + 2, x + 11, y + 4);
+ g.drawLine(x + 12, y + 2, x + 12, y + 5);
+
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+
+ // roof paint
+ int xx = x + 8;
+ for (int i = 0; i < 4; i++)
+ g.drawLine(xx - i, y + 2 + i, xx + i, y + 2 + i);
+ g.fillRect(x + 4, y + 6, 9, 2);
+
+ // door knob
+ g.drawLine(x + 9, y + 12, x + 9, y + 12);
+
+ // house paint
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.drawLine(x + 4, y + 8, x + 12, y + 8);
+ g.fillRect(x + 4, y + 9, 2, 6);
+ g.fillRect(x + 11, y + 9, 2, 6);
+
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon used for the "list view" button on a {@link JFileChooser} under
+ * the {@link MetalLookAndFeel}.
+ *
+ * @see MetalIconFactory#getFileChooserListViewIcon()
+ */
+ private static class FileChooserListViewIcon implements Icon, Serializable
+ {
+ /**
+ * Creates a new icon.
+ */
+ public FileChooserListViewIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 18;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 18;
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ g.setColor(MetalLookAndFeel.getBlack());
+
+ // file 1 outline
+ g.drawLine(x + 2, y + 2, x + 5, y + 2);
+ g.drawLine(x + 6, y + 3, x + 6, y + 7);
+ g.drawLine(x + 2, y + 7, x + 6, y + 7);
+ g.drawLine(x + 2, y + 2, x + 2, y + 7);
+
+ // file 2 outline
+ g.drawLine(x + 2, y + 10, x + 5, y + 10);
+ g.drawLine(x + 6, y + 11, x + 6, y + 15);
+ g.drawLine(x + 2, y + 15, x + 6, y + 15);
+ g.drawLine(x + 2, y + 10, x + 2, y + 15);
+
+ // file 3 outline
+ g.drawLine(x + 10, y + 2, x + 13, y + 2);
+ g.drawLine(x + 14, y + 3, x + 14, y + 7);
+ g.drawLine(x + 10, y + 7, x + 14, y + 7);
+ g.drawLine(x + 10, y + 2, x + 10, y + 7);
+
+ // file 4 outline
+ g.drawLine(x + 10, y + 10, x + 13, y + 10);
+ g.drawLine(x + 14, y + 11, x + 14, y + 15);
+ g.drawLine(x + 10, y + 15, x + 14, y + 15);
+ g.drawLine(x + 10, y + 10, x + 10, y + 15);
+
+ g.drawLine(x + 8, y + 5, x + 8, y + 5);
+ g.drawLine(x + 8, y + 13, x + 8, y + 13);
+ g.drawLine(x + 16, y + 5, x + 16, y + 5);
+ g.drawLine(x + 16, y + 13, x + 16, y + 13);
+
+ // fill files
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 3, y + 3, 3, 4);
+ g.fillRect(x + 3, y + 11, 3, 4);
+ g.fillRect(x + 11, y + 3, 3, 4);
+ g.fillRect(x + 11, y + 11, 3, 4);
+
+ // highlight files
+ g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
+ g.drawLine(x + 4, y + 4, x + 4, y + 5);
+ g.drawLine(x + 4, y + 12, x + 4, y + 13);
+ g.drawLine(x + 12, y + 4, x + 12, y + 5);
+ g.drawLine(x + 12, y + 12, x + 12, y + 13);
+
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon used for the "new folder" button on a {@link JFileChooser} under
+ * the {@link MetalLookAndFeel}.
+ *
+ * @see MetalIconFactory#getFileChooserNewFolderIcon()
+ */
+ private static class FileChooserNewFolderIcon implements Icon, Serializable
+ {
+ /**
+ * Creates a new icon.
+ */
+ public FileChooserNewFolderIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 18;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 18;
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ g.setColor(MetalLookAndFeel.getBlack());
+
+ g.drawLine(x + 2, y + 5, x + 9, y + 5);
+ g.drawLine(x + 10, y + 6, x + 15, y + 6);
+ g.drawLine(x + 15, y + 5, x + 15, y + 14);
+ g.drawLine(x + 2, y + 14, x + 15, y + 14);
+ g.drawLine(x + 1, y + 6, x + 1, y + 14);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ g.drawLine(x + 11, y + 3, x + 15, y + 3);
+ g.drawLine(x + 10, y + 4, x + 15, y + 4);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 3, y + 7, 7, 7);
+ g.fillRect(x + 10, y + 8, 5, 6);
+ g.drawLine(x + 10, y + 5, x + 14, y + 5);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
+ g.drawLine(x + 10, y + 7, x + 14, y + 7);
+ g.drawLine(x + 2, y + 6, x + 9, y + 6);
+ g.drawLine(x + 2, y + 6, x + 2, y + 13);
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon used for the "up folder" button on a {@link JFileChooser} under
+ * the {@link MetalLookAndFeel}.
+ *
+ * @see MetalIconFactory#getFileChooserNewFolderIcon()
+ */
+ private static class FileChooserUpFolderIcon extends FileChooserNewFolderIcon
+ implements Icon, Serializable
+ {
+ /**
+ * Creates a new icon.
+ */
+ public FileChooserUpFolderIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+
+ // draw the folder
+ super.paintIcon(c, g, x, y);
+
+ // now draw the up arrow
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 8, y + 9, x + 8, y + 16);
+ int xx = x + 8;
+ for (int i = 0; i < 4; i++)
+ g.drawLine(xx - i, y + 9 + i, xx + i, y + 9 + i);
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
* An icon representing a file (drawn as a piece of paper with the top-right
* corner turned down).
*/
@@ -153,13 +535,15 @@ public class MetalIconFactory implements Serializable
}
/**
- * Returns the height of the icon, in pixels.
+ * Returns the height of the icon, in pixels. The height returned is
+ * <code>16</code> plus the value returned by
+ * {@link #getAdditionalHeight()}.
*
* @return The height of the icon.
*/
public int getIconHeight()
{
- return 16;
+ return 16 + getAdditionalHeight();
}
/**
@@ -192,9 +576,11 @@ public class MetalIconFactory implements Serializable
}
/**
- * Returns the additional height (???).
+ * Returns the additional height for the icon. The
+ * {@link #getIconHeight()} method adds this value to the icon height it
+ * returns. Subclasses can override this method to adjust the icon height.
*
- * @return The additional height.
+ * @return The additional height (<code>0</code> unless overridden).
*/
public int getAdditionalHeight()
{
@@ -228,13 +614,15 @@ public class MetalIconFactory implements Serializable
}
/**
- * Returns the height of the icon, in pixels.
+ * Returns the height of the icon, in pixels. The height returned is
+ * <code>16</code> plus the value returned by
+ * {@link #getAdditionalHeight()}.
*
* @return The height of the icon.
*/
public int getIconHeight()
{
- return 16;
+ return 16 + getAdditionalHeight();
}
/**
@@ -265,9 +653,11 @@ public class MetalIconFactory implements Serializable
}
/**
- * Returns the additional height (???).
+ * Returns the additional height for the icon. The
+ * {@link #getIconHeight()} method adds this value to the icon height it
+ * returns. Subclasses can override this method to adjust the icon height.
*
- * @return The additional height.
+ * @return The additional height (<code>0</code> unless overridden).
*/
public int getAdditionalHeight()
{
@@ -285,29 +675,77 @@ public class MetalIconFactory implements Serializable
}
}
-
+
/**
- * An {@link Icon} implementation for {@link JCheckBox}es in the
- * Metal Look &amp; Feel.
- *
- * @author Roman Kennke (roman@kennke.org)
+ * An icon used by the {@link MetalInternalFrameUI} class when the frame
+ * is displayed as a palette.
+ *
+ * @since 1.3
*/
- static class RadioButtonIcon
- implements Icon, UIResource, Serializable
+ public static class PaletteCloseIcon
+ implements Icon, Serializable, UIResource
{
/**
- * Draws the check in the RadioButton.
- *
- * @param c the component to draw on
- * @param g the Graphics context to draw with
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
*/
- protected void drawCheck(Component c, Graphics g)
+ public int getIconWidth()
{
- g.setColor(MetalLookAndFeel.getBlack());
- g.fillRect(4, 3, 4, 6);
- g.drawLine(3, 4, 3, 7);
- g.drawLine(8, 4, 8, 7);
+ return 7;
}
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 7;
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ AbstractButton button = (AbstractButton) c;
+ if (button.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.fillRect(x + 2, y + 2, 3, 3);
+ g.drawLine(x + 1, y, x + 1, y + 2);
+ g.drawLine(x, y + 1, x + 2, y + 1);
+ g.drawLine(x + 5, y, x + 5, y + 2);
+ g.drawLine(x + 4, y + 1, x + 6, y + 1);
+ g.drawLine(x + 1, y + 4, x + 1, y + 6);
+ g.drawLine(x, y + 5, x + 2, y + 5);
+ g.drawLine(x + 5, y + 4, x + 5, y + 6);
+ g.drawLine(x + 4, y + 5, x + 6, y + 5);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(x + 2, y + 6, x + 3, y + 5);
+ g.drawLine(x + 5, y + 3, x + 6, y + 2);
+ g.drawLine(x + 6, y + 6, x + 6, y + 6);
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An {@link Icon} implementation for {@link JCheckBox}es in the
+ * Metal Look &amp; Feel.
+ *
+ * @author Roman Kennke (roman@kennke.org)
+ */
+ static class RadioButtonIcon implements Icon, UIResource, Serializable
+ {
/**
* Returns the width of the icon in pixels.
@@ -330,70 +768,104 @@ public class MetalIconFactory implements Serializable
}
/**
- * Paints the icon. This first paints the border of the RadioButton and
- * if the CheckBox is selected it calls {@link #drawCheck} to draw
- * the check.
+ * Paints the icon, taking into account whether or not the component is
+ * enabled, selected and/or armed.
*
- * @param c the Component to draw on (gets casted to JCheckBox)
+ * @param c the Component to draw on (must be an instance of
+ * {@link JRadioButton})
* @param g the Graphics context to draw with
* @param x the X position
* @param y the Y position
*/
- public void paintIcon(Component c, Graphics g, int x, int y)
- {
- Color dark = MetalLookAndFeel.getControlDarkShadow();
- Color light = MetalLookAndFeel.getWhite();
- g.translate(x, y);
-
- // The light 'circle'
- g.setColor(light);
- g.drawLine(4, 1, 10, 1);
- g.drawLine(2, 2, 3, 2);
- g.drawLine(8, 2, 11, 2);
- g.drawLine(2, 3, 2, 3);
- g.drawLine(11, 2, 11, 9);
- g.drawLine(1, 4, 1, 7);
- g.drawLine(12, 4, 12, 7);
- g.drawLine(2, 8, 2, 11);
- g.drawLine(11, 8, 11, 9);
- g.drawLine(10, 10, 10, 10);
- g.drawLine(2, 11, 9, 11);
- g.drawLine(4, 12, 7, 12);
-
- // The dark 'circle'
- g.setColor(dark);
- g.drawLine(4, 0, 7, 0);
- g.drawLine(2, 1, 3, 1);
- g.drawLine(8, 1, 9, 1);
- g.drawLine(1, 2, 1, 3);
- g.drawLine(10, 2, 10, 3);
- g.drawLine(0, 4, 0, 7);
- g.drawLine(11, 4, 11, 7);
- g.drawLine(1, 8, 1, 9);
- g.drawLine(10, 8, 10, 9);
- g.drawLine(2, 10, 3, 10);
- g.drawLine(8, 10, 9, 10);
- g.drawLine(4, 11, 7, 11);
-
- JRadioButton rb = (JRadioButton) c;
- if (rb.isSelected())
- drawCheck(c, g);
-
- g.translate(-x, -y);
- }
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ JRadioButton b = (JRadioButton) c;
+
+ // draw outer circle
+ if (b.isEnabled())
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(x + 2, y + 1, x + 3, y + 1);
+ g.drawLine(x + 4, y, x + 7, y);
+ g.drawLine(x + 8, y + 1, x + 9, y + 1);
+ g.drawLine(x + 10, y + 2, x + 10, y + 3);
+ g.drawLine(x + 11, y + 4, x + 11, y + 7);
+ g.drawLine(x + 10, y + 8, x + 10, y + 9);
+ g.drawLine(x + 8, y + 10, x + 9, y + 10);
+ g.drawLine(x + 4, y + 11, x + 7, y + 11);
+ g.drawLine(x + 2, y + 10, x + 3, y + 10);
+ g.drawLine(x + 1, y + 9, x + 1, y + 8);
+ g.drawLine(x, y + 7, x, y + 4);
+ g.drawLine(x + 1, y + 2, x + 1, y + 3);
+
+ if (b.getModel().isArmed())
+ {
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(x + 4, y + 1, x + 7, y + 1);
+ g.drawLine(x + 4, y + 10, x + 7, y + 10);
+ g.drawLine(x + 1, y + 4, x + 1, y + 7);
+ g.drawLine(x + 10, y + 4, x + 10, y + 7);
+ g.fillRect(x + 2, y + 2, 8, 8);
+ }
+ else
+ {
+ // only draw inner highlight if not filled
+ if (b.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getWhite());
+
+ g.drawLine(x + 2, y + 8, x + 2, y + 9);
+ g.drawLine(x + 1, y + 4, x + 1, y + 7);
+ g.drawLine(x + 2, y + 2, x + 2, y + 3);
+ g.drawLine(x + 3, y + 2, x + 3, y + 2);
+ g.drawLine(x + 4, y + 1, x + 7, y + 1);
+ g.drawLine(x + 8, y + 2, x + 9, y + 2);
+ }
+ }
+
+ // draw outer highlight
+ if (b.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getWhite());
+
+ // outer
+ g.drawLine(x + 10, y + 1, x + 10, y + 1);
+ g.drawLine(x + 11, y + 2, x + 11, y + 3);
+ g.drawLine(x + 12, y + 4, x + 12, y + 7);
+ g.drawLine(x + 11, y + 8, x + 11, y + 9);
+ g.drawLine(x + 10, y + 10, x + 10, y + 10);
+ g.drawLine(x + 8, y + 11, x + 9, y + 11);
+ g.drawLine(x + 4, y + 12, x + 7, y + 12);
+ g.drawLine(x + 2, y + 11, x + 3, y + 11);
+ }
+
+ if (b.isSelected())
+ {
+ if (b.isEnabled())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(x + 4, y + 3, x + 7, y + 3);
+ g.fillRect(x + 3, y + 4, 6, 4);
+ g.drawLine(x + 4, y + 8, x + 7, y + 8);
+ }
+ g.setColor(savedColor);
+ }
}
/**
* An icon displayed for {@link JRadioButtonMenuItem} components.
*/
- private static class RadioButtonMenuItemIcon
- implements Icon, Serializable
+ private static class RadioButtonMenuItemIcon implements Icon, Serializable
{
/**
* Creates a new icon instance.
*/
public RadioButtonMenuItemIcon()
- {
+ {
+ // Nothing to do here.
}
/**
@@ -463,8 +935,7 @@ public class MetalIconFactory implements Serializable
* The icon used to display the thumb control on a horizontally oriented
* {@link JSlider} component.
*/
- private static class HorizontalSliderThumbIcon
- implements Icon, Serializable
+ private static class HorizontalSliderThumbIcon implements Icon, Serializable
{
/**
@@ -472,6 +943,7 @@ public class MetalIconFactory implements Serializable
*/
public HorizontalSliderThumbIcon()
{
+ // Nothing to do here.
}
/**
@@ -505,13 +977,19 @@ public class MetalIconFactory implements Serializable
*/
public void paintIcon(Component c, Graphics g, int x, int y)
{
+ boolean enabled = false;
boolean focus = false;
- if (c != null)
- focus = c.hasFocus();
- // TODO: pick up the colors from the look and feel
+ if (c != null)
+ {
+ enabled = c.isEnabled();
+ focus = c.hasFocus();
+ }
// draw the outline
- g.setColor(Color.black);
+ if (enabled)
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
g.drawLine(x + 1, y, x + 13, y);
g.drawLine(x + 14, y + 1, x + 14, y + 7);
g.drawLine(x + 14, y + 8, x + 7, y + 15);
@@ -519,8 +997,11 @@ public class MetalIconFactory implements Serializable
g.drawLine(x, y + 7, x, y + 1);
// fill the icon
- g.setColor(focus ? new Color(153, 153, 204) : new Color(204, 204, 204)); // medium
- g.fillRect(x + 2, y + 2, 12, 7);
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControl());
+ g.fillRect(x + 1, y + 2, 13, 7);
g.drawLine(x + 2, y + 9, x + 12, y + 9);
g.drawLine(x + 3, y + 10, x + 11, y + 10);
g.drawLine(x + 4, y + 11, x + 10, y + 11);
@@ -528,33 +1009,42 @@ public class MetalIconFactory implements Serializable
g.drawLine(x + 6, y + 13, x + 8, y + 13);
g.drawLine(x + 7, y + 14, x + 7, y + 14);
- // draw highlights
- g.setColor(focus ? new Color(204, 204, 255) : new Color(255, 255, 255)); // light
- g.drawLine(x + 1, y + 1, x + 13, y + 1);
- g.drawLine(x + 1, y + 2, x + 1, y + 8);
- g.drawLine(x + 2, y + 2, x + 2, y + 2);
- g.drawLine(x + 6, y + 2, x + 6, y + 2);
- g.drawLine(x + 10, y + 2, x + 10, y + 2);
-
- g.drawLine(x + 4, y + 4, x + 4, y + 4);
- g.drawLine(x + 8, y + 4, x + 8, y + 4);
+ // if the slider is enabled, draw dots and highlights
+ if (c.isEnabled())
+ {
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ else
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 3, y + 3, x + 3, y + 3);
+ g.drawLine(x + 7, y + 3, x + 7, y + 3);
+ g.drawLine(x + 11, y + 3, x + 11, y + 3);
- g.drawLine(x + 2, y + 6, x + 2, y + 6);
- g.drawLine(x + 6, y + 6, x + 6, y + 6);
- g.drawLine(x + 10, y + 6, x + 10, y + 6);
+ g.drawLine(x + 5, y + 5, x + 5, y + 5);
+ g.drawLine(x + 9, y + 5, x + 9, y + 5);
- // draw dots
- g.setColor(focus ? new Color(102, 102, 153) : Color.black); // dark
- g.drawLine(x + 3, y + 3, x + 3, y + 3);
- g.drawLine(x + 7, y + 3, x + 7, y + 3);
- g.drawLine(x + 11, y + 3, x + 11, y + 3);
+ g.drawLine(x + 3, y + 7, x + 3, y + 7);
+ g.drawLine(x + 7, y + 7, x + 7, y + 7);
+ g.drawLine(x + 11, y + 7, x + 11, y + 7);
- g.drawLine(x + 5, y + 5, x + 5, y + 5);
- g.drawLine(x + 9, y + 5, x + 9, y + 5);
+ // draw highlights
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ else
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x + 1, y + 1, x + 13, y + 1);
+ g.drawLine(x + 1, y + 2, x + 1, y + 8);
+ g.drawLine(x + 2, y + 2, x + 2, y + 2);
+ g.drawLine(x + 6, y + 2, x + 6, y + 2);
+ g.drawLine(x + 10, y + 2, x + 10, y + 2);
+
+ g.drawLine(x + 4, y + 4, x + 4, y + 4);
+ g.drawLine(x + 8, y + 4, x + 8, y + 4);
- g.drawLine(x + 3, y + 7, x + 3, y + 7);
- g.drawLine(x + 7, y + 7, x + 7, y + 7);
- g.drawLine(x + 11, y + 7, x + 11, y + 7);
+ g.drawLine(x + 2, y + 6, x + 2, y + 6);
+ g.drawLine(x + 6, y + 6, x + 6, y + 6);
+ g.drawLine(x + 10, y + 6, x + 10, y + 6);
+ }
}
}
@@ -563,7 +1053,7 @@ public class MetalIconFactory implements Serializable
* An icon used for the 'close' button in the title frame of a
* {@link JInternalFrame}.
*/
- private static class InternalFrameCloseIcon implements Icon, Serializable
+ private static class InternalFrameCloseIcon implements Icon, Serializable
{
/** The icon size in pixels. */
private int size;
@@ -601,25 +1091,53 @@ public class MetalIconFactory implements Serializable
/**
* Paints the icon.
*
- * @param c the component.
+ * @param c the component (an {@link JInternalFrame} is expected).
* @param g the graphics device.
* @param x the x-coordinate.
* @param y the y-coordinate.
*/
public void paintIcon(Component c, Graphics g, int x, int y)
{
- // draw the gray areas first
- g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ Color savedColor = g.getColor();
+ AbstractButton b = (AbstractButton) c;
+
+ // fill the interior
+ if (b.getModel().isPressed())
+ // FIXME: also need to take into account whether the internal frame is
+ // selected
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 2, y + 2, 10, 10);
+
+ // draw the outline box and the cross
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ {
+ // FIXME: also need to take into account whether the internal frame is
+ // selected
+ boolean selected = true;
+ if (selected)
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ }
g.drawLine(x + 1, y + 1, x + 13, y + 1);
g.drawLine(x + 1, y + 2, x + 1, y + 12);
g.drawLine(x + 1, y + 13, x + 13, y + 13);
g.drawLine(x + 13, y + 2, x + 13, y + 12);
+ g.drawLine(x + 2, y + 12, x + 2, y + 12);
+ g.drawLine(x + 12, y + 2, x + 12, y + 2);
g.fillRect(x + 4, y + 4, 2, 2);
- g.fillRect(x + 4, y + 9, 2, 2);
- g.fillRect(x + 9, y + 4, 2, 2);
- g.fillRect(x + 9, y + 9, 2, 2);
- g.fillRect(x + 5, y + 5, 5, 5);
+ g.fillRect(x + 5, y + 5, 4, 4);
+ g.drawLine(x + 9, y + 4, x + 10, y + 4);
+ g.drawLine(x + 9, y + 4, x + 9, y + 5);
+ g.drawLine(x + 4, y + 9, x + 4, y + 10);
+ g.drawLine(x + 4, y + 9, x + 5, y + 9);
+ g.drawLine(x + 9, y + 8, x + 9, y + 10);
+ g.drawLine(x + 8, y + 9, x + 10, y + 9);
g.setColor(MetalLookAndFeel.getBlack());
g.drawLine(x, y, x + 13, y);
@@ -635,20 +1153,24 @@ public class MetalIconFactory implements Serializable
g.drawLine(x + 1, y + 14, x + 14, y + 14);
g.drawLine(x + 14, y + 1, x + 14, y + 14);
- g.drawLine(x + 5, y + 10, x + 5, y + 10);
- g.drawLine(x + 6, y + 9, x + 7, y + 9);
- g.drawLine(x + 10, y + 5, x + 10, y + 5);
- g.drawLine(x + 9, y + 6, x + 9, y + 7);
- g.drawLine(x + 10, y + 10, x + 11, y + 10);
- g.drawLine(x + 10, y + 11, x + 10, y + 11);
+ if (!b.getModel().isPressed())
+ {
+ g.drawLine(x + 5, y + 10, x + 5, y + 10);
+ g.drawLine(x + 6, y + 9, x + 7, y + 9);
+ g.drawLine(x + 10, y + 5, x + 10, y + 5);
+ g.drawLine(x + 9, y + 6, x + 9, y + 7);
+ g.drawLine(x + 10, y + 10, x + 11, y + 10);
+ g.drawLine(x + 10, y + 11, x + 10, y + 11);
+ }
+ g.setColor(savedColor);
}
}
/**
* The icon displayed at the top-left corner of a {@link JInternalFrame}.
*/
- private static class InternalFrameDefaultMenuIcon
- implements Icon, Serializable
+ private static class InternalFrameDefaultMenuIcon
+ implements Icon, Serializable
{
/**
@@ -656,6 +1178,7 @@ public class MetalIconFactory implements Serializable
*/
public InternalFrameDefaultMenuIcon()
{
+ // Nothing to do here.
}
/**
@@ -718,8 +1241,8 @@ public class MetalIconFactory implements Serializable
* maximise an internal frame, this icon will replace the 'maximise' icon to
* provide a 'restore' option.
*/
- private static class InternalFrameAltMaximizeIcon
- implements Icon, Serializable
+ private static class InternalFrameAltMaximizeIcon
+ implements Icon, Serializable
{
/** The icon size in pixels. */
private int size;
@@ -764,14 +1287,23 @@ public class MetalIconFactory implements Serializable
*/
public void paintIcon(Component c, Graphics g, int x, int y)
{
- Color color = MetalLookAndFeel.getControlDarkShadow();
- if (c instanceof JInternalFrame)
- {
- JInternalFrame f = (JInternalFrame) c;
- if (f.isSelected())
- color = MetalLookAndFeel.getPrimaryControlShadow();
- }
- g.setColor(color);
+ Color savedColor = g.getColor();
+
+ AbstractButton b = (AbstractButton) c;
+
+ // fill the small box interior
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 2, y + 6, 7, 7);
+
+
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+
g.drawLine(x + 12, y + 1, x + 13, y + 1);
g.drawLine(x + 11, y + 2, x + 12, y + 2);
g.drawLine(x + 10, y + 3, x + 11, y + 3);
@@ -803,10 +1335,16 @@ public class MetalIconFactory implements Serializable
g.drawLine(x + 13, y + 6, x + 13, y + 6);
g.drawLine(x + 8, y + 7, x + 13, y + 7);
g.drawLine(x + 6, y + 5, x + 6, y + 5);
- g.drawLine(x + 2, y + 6, x + 6, y + 6);
- g.drawLine(x + 2, y + 6, x + 2, y + 11);
g.drawLine(x + 10, y + 8, x + 10, y + 13);
g.drawLine(x + 1, y + 14, x + 10, y + 14);
+
+ if (!b.getModel().isPressed())
+ {
+ g.drawLine(x + 2, y + 6, x + 6, y + 6);
+ g.drawLine(x + 2, y + 6, x + 2, y + 11);
+ }
+
+ g.setColor(savedColor);
}
}
@@ -814,8 +1352,7 @@ public class MetalIconFactory implements Serializable
* An icon used for the 'maximize' button in the title frame of a
* {@link JInternalFrame}.
*/
- private static class InternalFrameMaximizeIcon
- implements Icon, Serializable
+ private static class InternalFrameMaximizeIcon implements Icon, Serializable
{
/**
@@ -823,6 +1360,7 @@ public class MetalIconFactory implements Serializable
*/
public InternalFrameMaximizeIcon()
{
+ // Nothing to do here.
}
/**
@@ -855,14 +1393,22 @@ public class MetalIconFactory implements Serializable
*/
public void paintIcon(Component c, Graphics g, int x, int y)
{
- Color color = MetalLookAndFeel.getControlDarkShadow();
- if (c instanceof JInternalFrame)
- {
- JInternalFrame f = (JInternalFrame) c;
- if (f.isSelected())
- color = MetalLookAndFeel.getPrimaryControlShadow();
- }
- g.setColor(color);
+ Color savedColor = g.getColor();
+
+ AbstractButton b = (AbstractButton) c;
+
+ // fill the interior
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 2, y + 6, 7, 7);
+
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+
g.drawLine(x + 9, y + 1, x + 10, y + 1);
g.fillRect(x + 11, y + 1, 3, 3);
g.fillRect(x + 12, y + 4, 2, 2);
@@ -897,9 +1443,12 @@ public class MetalIconFactory implements Serializable
// draw white
g.setColor(MetalLookAndFeel.getWhite());
- g.drawLine(x + 2, y + 6, x + 5, y + 6);
- g.drawLine(x + 2, y + 7, x + 2, y + 9);
- g.drawLine(x + 4, y + 11, x + 7, y + 8);
+ if (!b.getModel().isPressed())
+ {
+ g.drawLine(x + 2, y + 6, x + 5, y + 6);
+ g.drawLine(x + 2, y + 7, x + 2, y + 9);
+ g.drawLine(x + 4, y + 11, x + 7, y + 8);
+ }
g.drawLine(x + 1, y + 14, x + 10, y + 14);
g.drawLine(x + 10, y + 5, x + 10, y + 13);
@@ -908,14 +1457,14 @@ public class MetalIconFactory implements Serializable
g.drawLine(x + 11, y + 4, x + 11, y + 5);
g.drawLine(x + 13, y + 6, x + 14, y + 6);
g.drawLine(x + 14, y + 1, x + 14, y + 5);
+ g.setColor(savedColor);
}
}
/**
* An icon used in the title frame of a {@link JInternalFrame}.
*/
- private static class InternalFrameMinimizeIcon
- implements Icon, Serializable
+ private static class InternalFrameMinimizeIcon implements Icon, Serializable
{
/**
@@ -923,6 +1472,7 @@ public class MetalIconFactory implements Serializable
*/
public InternalFrameMinimizeIcon()
{
+ // Nothing to do here.
}
/**
@@ -955,14 +1505,17 @@ public class MetalIconFactory implements Serializable
*/
public void paintIcon(Component c, Graphics g, int x, int y)
{
- Color color = MetalLookAndFeel.getControlDarkShadow();
- if (c instanceof JInternalFrame)
- {
- JInternalFrame f = (JInternalFrame) c;
- if (f.isSelected())
- color = MetalLookAndFeel.getPrimaryControlShadow();
- }
- g.setColor(color);
+ Color savedColor = g.getColor();
+
+ AbstractButton b = (AbstractButton) c;
+
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ // FIXME: here the color depends on whether or not the internal frame
+ // is selected
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+
g.drawLine(x + 12, y + 1, x + 13, y + 1);
g.drawLine(x + 11, y + 2, x + 12, y + 2);
g.drawLine(x + 10, y + 3, x + 11, y + 3);
@@ -993,10 +1546,21 @@ public class MetalIconFactory implements Serializable
g.drawLine(x + 11, y + 4, x + 13, y + 2);
g.drawLine(x + 13, y + 6, x + 13, y + 6);
g.drawLine(x + 8, y + 7, x + 13, y + 7);
- g.drawLine(x + 2, y + 9, x + 4, y + 9);
- g.drawLine(x + 2, y + 10, x + 2, y + 11);
g.drawLine(x + 7, y + 9, x + 7, y + 13);
g.drawLine(x + 1, y + 14, x + 7, y + 14);
+
+ if (b.getModel().isPressed())
+ {
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ g.fillRect(x + 2, y + 9, 3, 3);
+ }
+ else
+ {
+ g.drawLine(x + 2, y + 9, x + 4, y + 9);
+ g.drawLine(x + 2, y + 10, x + 2, y + 11);
+ }
+
+ g.setColor(savedColor);
}
}
@@ -1004,13 +1568,14 @@ public class MetalIconFactory implements Serializable
* The icon used to display the thumb control on a horizontally oriented
* {@link JSlider} component.
*/
- private static class VerticalSliderThumbIcon implements Icon, Serializable
+ private static class VerticalSliderThumbIcon implements Icon, Serializable
{
/**
* Creates a new instance.
*/
public VerticalSliderThumbIcon()
{
+ // Nothing to do here.
}
/**
@@ -1045,13 +1610,19 @@ public class MetalIconFactory implements Serializable
*/
public void paintIcon(Component c, Graphics g, int x, int y)
{
+ boolean enabled = false;
boolean focus = false;
- if (c != null)
- focus = c.hasFocus();
- // TODO: pick up the colors from the look and feel
+ if (c != null)
+ {
+ enabled = c.isEnabled();
+ focus = c.hasFocus();
+ }
// draw the outline
- g.setColor(Color.black);
+ if (enabled)
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
g.drawLine(x + 1, y, x + 7, y);
g.drawLine(x + 8, y, x + 15, y + 7);
g.drawLine(x + 14, y + 8, x + 8, y + 14);
@@ -1059,8 +1630,11 @@ public class MetalIconFactory implements Serializable
g.drawLine(x, y + 13, x, y + 1);
// fill the icon
- g.setColor(focus ? new Color(153, 153, 204) : new Color(204, 204, 204)); // medium
- g.fillRect(x + 2, y + 2, 7, 12);
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControl());
+ g.fillRect(x + 2, y + 1, 7, 13);
g.drawLine(x + 9, y + 2, x + 9, y + 12);
g.drawLine(x + 10, y + 3, x + 10, y + 11);
g.drawLine(x + 11, y + 4, x + 11, y + 10);
@@ -1068,41 +1642,51 @@ public class MetalIconFactory implements Serializable
g.drawLine(x + 13, y + 6, x + 13, y + 8);
g.drawLine(x + 14, y + 7, x + 14, y + 7);
- // draw highlights
- g.setColor(focus ? new Color(204, 204, 255) : new Color(255, 255, 255)); // light
- g.drawLine(x + 1, y + 1, x + 8, y + 1);
- g.drawLine(x + 1, y + 2, x + 1, y + 13);
- g.drawLine(x + 2, y + 2, x + 2, y + 2);
- g.drawLine(x + 2, y + 6, x + 2, y + 6);
- g.drawLine(x + 2, y + 10, x + 2, y + 10);
+ // if the slider is enabled, draw dots and highlights
+ if (enabled)
+ {
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ else
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 3, y + 3, x + 3, y + 3);
+ g.drawLine(x + 3, y + 7, x + 3, y + 7);
+ g.drawLine(x + 3, y + 11, x + 3, y + 11);
- g.drawLine(x + 4, y + 4, x + 4, y + 4);
- g.drawLine(x + 4, y + 8, x + 4, y + 8);
+ g.drawLine(x + 5, y + 5, x + 5, y + 5);
+ g.drawLine(x + 5, y + 9, x + 5, y + 9);
- g.drawLine(x + 6, y + 2, x + 6, y + 2);
- g.drawLine(x + 6, y + 6, x + 6, y + 6);
- g.drawLine(x + 6, y + 10, x + 6, y + 10);
+ g.drawLine(x + 7, y + 3, x + 7, y + 3);
+ g.drawLine(x + 7, y + 7, x + 7, y + 7);
+ g.drawLine(x + 7, y + 11, x + 7, y + 11);
- // draw dots
- g.setColor(focus ? new Color(102, 102, 153) : Color.black); // dark
- g.drawLine(x + 3, y + 3, x + 3, y + 3);
- g.drawLine(x + 3, y + 7, x + 3, y + 7);
- g.drawLine(x + 3, y + 11, x + 3, y + 11);
+ // draw highlights
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ else
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x + 1, y + 1, x + 8, y + 1);
+ g.drawLine(x + 1, y + 2, x + 1, y + 13);
+ g.drawLine(x + 2, y + 2, x + 2, y + 2);
+ g.drawLine(x + 2, y + 6, x + 2, y + 6);
+ g.drawLine(x + 2, y + 10, x + 2, y + 10);
- g.drawLine(x + 5, y + 5, x + 5, y + 5);
- g.drawLine(x + 5, y + 9, x + 5, y + 9);
+ g.drawLine(x + 4, y + 4, x + 4, y + 4);
+ g.drawLine(x + 4, y + 8, x + 4, y + 8);
- g.drawLine(x + 7, y + 3, x + 7, y + 3);
- g.drawLine(x + 7, y + 7, x + 7, y + 7);
- g.drawLine(x + 7, y + 11, x + 7, y + 11);
+ g.drawLine(x + 6, y + 2, x + 6, y + 2);
+ g.drawLine(x + 6, y + 6, x + 6, y + 6);
+ g.drawLine(x + 6, y + 10, x + 6, y + 10);
+
+ }
}
}
-
+
/**
* A tree control icon. This icon can be in one of two states: expanded and
* collapsed.
*/
- public static class TreeControlIcon implements Icon, Serializable
+ public static class TreeControlIcon implements Icon, Serializable
{
/** ???. */
@@ -1235,19 +1819,21 @@ public class MetalIconFactory implements Serializable
/**
* A tree folder icon.
*/
- public static class TreeFolderIcon extends FolderIcon16
+ public static class TreeFolderIcon extends FolderIcon16
{
/**
* Creates a new instance.
*/
public TreeFolderIcon()
- {
+ {
+ // Nothing to do here.
}
/**
- * Returns the additional height (???).
+ * Returns the additional height for this icon, in this case <code>2</code>
+ * pixels.
*
- * @return The additional height.
+ * @return <code>2</code>.
*/
public int getAdditionalHeight()
{
@@ -1268,19 +1854,21 @@ public class MetalIconFactory implements Serializable
/**
* A tree leaf icon.
*/
- public static class TreeLeafIcon extends FileIcon16
+ public static class TreeLeafIcon extends FileIcon16
{
/**
* Creates a new instance.
*/
public TreeLeafIcon()
{
+ // Nothing to do here.
}
/**
- * Returns the additional height (???).
+ * Returns the additional height for this icon, in this case <code>4</code>
+ * pixels.
*
- * @return The additional height.
+ * @return <code>4</code>.
*/
public int getAdditionalHeight()
{
@@ -1297,16 +1885,310 @@ public class MetalIconFactory implements Serializable
return 2;
}
}
+
+ /**
+ * An icon representing a hard disk.
+ *
+ * @see MetalIconFactory#getTreeHardDriveIcon()
+ */
+ private static class TreeHardDriveIcon implements Icon, Serializable
+ {
+
+ /**
+ * Creates a new icon instance.
+ */
+ public TreeHardDriveIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconHeight()
+ {
+ return 16;
+ }
+
+ /**
+ * Paints the icon at the specified location, using colors from the
+ * current theme.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color saved = g.getColor();
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 1, y + 4, x + 1, y + 5);
+ g.drawLine(x + 14, y + 4, x + 14, y + 5);
+ g.drawLine(x + 1, y + 7, x + 1, y + 8);
+ g.drawLine(x + 14, y + 7, x + 14, y + 8);
+ g.drawLine(x + 1, y + 10, x + 1, y + 11);
+ g.drawLine(x + 14, y + 10, x + 14, y + 11);
+
+ g.drawLine(x + 2, y + 3, x + 3, y + 3);
+ g.drawLine(x + 12, y + 3, x + 13, y + 3);
+ g.drawLine(x + 2, y + 6, x + 3, y + 6);
+ g.drawLine(x + 12, y + 6, x + 13, y + 6);
+ g.drawLine(x + 2, y + 9, x + 3, y + 9);
+ g.drawLine(x + 12, y + 9, x + 13, y + 9);
+ g.drawLine(x + 2, y + 12, x + 3, y + 12);
+ g.drawLine(x + 12, y + 12, x + 13, y + 12);
+
+ g.drawLine(x + 4, y + 2, x + 11, y + 2);
+ g.drawLine(x + 4, y + 7, x + 11, y + 7);
+ g.drawLine(x + 4, y + 10, x + 11, y + 10);
+ g.drawLine(x + 4, y + 13, x + 11, y + 13);
+
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.fillRect(x + 4, y + 3, 2, 2);
+ g.drawLine(x + 6, y + 4, x + 6, y + 4);
+ g.drawLine(x + 7, y + 3, x + 9, y + 3);
+ g.drawLine(x + 8, y + 4, x + 8, y + 4);
+ g.drawLine(x + 11, y + 3, x + 11, y + 3);
+ g.fillRect(x + 2, y + 4, 2, 2);
+ g.fillRect(x + 2, y + 7, 2, 2);
+ g.fillRect(x + 2, y + 10, 2, 2);
+ g.drawLine(x + 4, y + 6, x + 4, y + 6);
+ g.drawLine(x + 4, y + 9, x + 4, y + 9);
+ g.drawLine(x + 4, y + 12, x + 4, y + 12);
+
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(x + 13, y + 4, x + 13, y + 4);
+ g.drawLine(x + 12, y + 5, x + 13, y + 5);
+ g.drawLine(x + 13, y + 7, x + 13, y + 7);
+ g.drawLine(x + 12, y + 8, x + 13, y + 8);
+ g.drawLine(x + 13, y + 10, x + 13, y + 10);
+ g.drawLine(x + 12, y + 11, x + 13, y + 11);
+
+ g.drawLine(x + 10, y + 5, x + 10, y + 5);
+ g.drawLine(x + 7, y + 6, x + 7, y + 6);
+ g.drawLine(x + 9, y + 6, x + 9, y + 6);
+ g.drawLine(x + 11, y + 6, x + 11, y + 6);
+
+ g.drawLine(x + 10, y + 8, x + 10, y + 8);
+ g.drawLine(x + 7, y + 9, x + 7, y + 9);
+ g.drawLine(x + 9, y + 9, x + 9, y + 9);
+ g.drawLine(x + 11, y + 9, x + 11, y + 9);
+
+ g.drawLine(x + 10, y + 11, x + 10, y + 11);
+ g.drawLine(x + 7, y + 12, x + 7, y + 12);
+ g.drawLine(x + 9, y + 12, x + 9, y + 12);
+ g.drawLine(x + 11, y + 12, x + 11, y + 12);
+
+ g.setColor(saved);
+ }
+ }
+
+ /**
+ * An icon representing a floppy disk.
+ *
+ * @see MetalIconFactory#getTreeFloppyDriveIcon()
+ */
+ private static class TreeFloppyDriveIcon implements Icon, Serializable
+ {
+
+ /**
+ * Creates a new icon instance.
+ */
+ public TreeFloppyDriveIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconHeight()
+ {
+ return 16;
+ }
+
+ /**
+ * Paints the icon at the specified location, using colors from the
+ * current theme.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color saved = g.getColor();
+
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 1, y + 1, x + 13, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + 14);
+ g.drawLine(x + 1, y + 14, x + 14, y + 14);
+ g.drawLine(x + 14, y + 2, x + 14, y + 14);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 2, y + 2, 12, 12);
+
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.fillRect(x + 5, y + 2, 6, 5);
+ g.drawLine(x + 4, y + 8, x + 11, y + 8);
+ g.drawLine(x + 3, y + 9, x + 3, y + 13);
+ g.drawLine(x + 12, y + 9, x + 12, y + 13);
+
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.fillRect(x + 8, y + 3, 2, 3);
+ g.fillRect(x + 4, y + 9, 8, 5);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ g.drawLine(x + 5, y + 10, x + 9, y + 10);
+ g.drawLine(x + 5, y + 12, x + 8, y + 12);
+
+ g.setColor(saved);
+ }
+ }
+
+ /**
+ * An icon representing a computer.
+ *
+ * @see MetalIconFactory#getTreeComputerIcon()
+ */
+ private static class TreeComputerIcon implements Icon, Serializable
+ {
+
+ /**
+ * Creates a new icon instance.
+ */
+ public TreeComputerIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconHeight()
+ {
+ return 16;
+ }
+
+ /**
+ * Paints the icon at the specified location, using colors from the
+ * current theme.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color saved = g.getColor();
+
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 3, y + 1, x + 12, y + 1);
+ g.drawLine(x + 2, y + 2, x + 2, y + 8);
+ g.drawLine(x + 13, y + 2, x + 13, y + 8);
+ g.drawLine(x + 3, y + 9, x + 3, y + 9);
+ g.drawLine(x + 12, y + 9, x + 12, y + 9);
+ g.drawRect(x + 1, y + 10, 13, 4);
+ g.drawLine(x + 5, y + 3, x + 10, y + 3);
+ g.drawLine(x + 5, y + 8, x + 10, y + 8);
+ g.drawLine(x + 4, y + 4, x + 4, y + 7);
+ g.drawLine(x + 11, y + 4, x + 11, y + 7);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 5, y + 4, 6, 4);
+
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(x + 6, y + 12, x + 8, y + 12);
+ g.drawLine(x + 10, y + 12, x + 12, y + 12);
+ g.setColor(saved);
+ }
+ }
+ /** The icon returned by {@link #getCheckBoxIcon()}. */
+ private static Icon checkBoxIcon;
+
+ /** The icon returned by {@link #getCheckBoxMenuItemIcon()}. */
+ private static Icon checkBoxMenuItemIcon;
+
+ /** The icon returned by {@link #getFileChooserDetailViewIcon()}. */
+ private static Icon fileChooserDetailViewIcon;
+
+ /** The icon returned by {@link #getFileChooserHomeFolderIcon()}. */
+ private static Icon fileChooserHomeFolderIcon;
+
+ /** The icon returned by {@link #getFileChooserListViewIcon()}. */
+ private static Icon fileChooserListViewIcon;
+
+ /** The icon returned by {@link #getFileChooserNewFolderIcon()}. */
+ private static Icon fileChooserNewFolderIcon;
+
+ /** The icon returned by {@link #getFileChooserUpFolderIcon()}. */
+ private static Icon fileChooserUpFolderIcon;
+
/** The cached RadioButtonIcon instance. */
private static RadioButtonIcon radioButtonIcon;
+ /** The icon returned by {@link #getRadioButtonMenuItemIcon()}. */
+ private static Icon radioButtonMenuItemIcon;
+
+ /** The icon returned by {@link #getInternalFrameDefaultMenuIcon()}. */
+ private static Icon internalFrameDefaultMenuIcon;
+
+ /** The icon returned by {@link #getTreeComputerIcon()}. */
+ private static Icon treeComputerIcon;
+
+ /** The icon instance returned by {@link #getTreeFloppyDriveIcon()}. */
+ private static Icon treeFloppyDriveIcon;
+
+ /** The icon instance returned by {@link #getTreeHardDriveIcon()}. */
+ private static Icon treeHardDriveIcon;
+
/**
* Creates a new instance. All the methods are static, so creating an
* instance isn't necessary.
*/
public MetalIconFactory()
- {
+ {
+ // Nothing to do here.
}
/**
@@ -1318,7 +2200,9 @@ public class MetalIconFactory implements Serializable
*/
public static Icon getCheckBoxIcon()
{
- return new MetalCheckBoxIcon();
+ if (checkBoxIcon == null)
+ checkBoxIcon = new MetalCheckBoxIcon();
+ return checkBoxIcon;
}
/**
@@ -1329,7 +2213,69 @@ public class MetalIconFactory implements Serializable
*/
public static Icon getCheckBoxMenuItemIcon()
{
- return new CheckBoxMenuItemIcon();
+ if (checkBoxMenuItemIcon == null)
+ checkBoxMenuItemIcon = new CheckBoxMenuItemIcon();
+ return checkBoxMenuItemIcon;
+ }
+
+ /**
+ * Returns an icon for use by the {@link JFileChooser} component.
+ *
+ * @return An icon.
+ */
+ public static Icon getFileChooserDetailViewIcon()
+ {
+ if (fileChooserDetailViewIcon == null)
+ fileChooserDetailViewIcon = new FileChooserDetailViewIcon();
+ return fileChooserDetailViewIcon;
+ }
+
+ /**
+ * Returns an icon for use by the {@link JFileChooser} component.
+ *
+ * @return An icon.
+ */
+ public static Icon getFileChooserHomeFolderIcon()
+ {
+ if (fileChooserHomeFolderIcon == null)
+ fileChooserHomeFolderIcon = new FileChooserHomeFolderIcon();
+ return fileChooserHomeFolderIcon;
+ }
+
+ /**
+ * Returns an icon for use by the {@link JFileChooser} component.
+ *
+ * @return An icon.
+ */
+ public static Icon getFileChooserListViewIcon()
+ {
+ if (fileChooserListViewIcon == null)
+ fileChooserListViewIcon = new FileChooserListViewIcon();
+ return fileChooserListViewIcon;
+ }
+
+ /**
+ * Returns an icon for use by the {@link JFileChooser} component.
+ *
+ * @return An icon.
+ */
+ public static Icon getFileChooserNewFolderIcon()
+ {
+ if (fileChooserNewFolderIcon == null)
+ fileChooserNewFolderIcon = new FileChooserNewFolderIcon();
+ return fileChooserNewFolderIcon;
+ }
+
+ /**
+ * Returns an icon for use by the {@link JFileChooser} component.
+ *
+ * @return An icon.
+ */
+ public static Icon getFileChooserUpFolderIcon()
+ {
+ if (fileChooserUpFolderIcon == null)
+ fileChooserUpFolderIcon = new FileChooserUpFolderIcon();
+ return fileChooserUpFolderIcon;
}
/**
@@ -1351,7 +2297,9 @@ public class MetalIconFactory implements Serializable
*/
public static Icon getRadioButtonMenuItemIcon()
{
- return new RadioButtonMenuItemIcon();
+ if (radioButtonMenuItemIcon == null)
+ radioButtonMenuItemIcon = new RadioButtonMenuItemIcon();
+ return radioButtonMenuItemIcon;
}
/**
@@ -1386,7 +2334,9 @@ public class MetalIconFactory implements Serializable
*/
public static Icon getInternalFrameDefaultMenuIcon()
{
- return new InternalFrameDefaultMenuIcon();
+ if (internalFrameDefaultMenuIcon == null)
+ internalFrameDefaultMenuIcon = new InternalFrameDefaultMenuIcon();
+ return internalFrameDefaultMenuIcon;
}
/**
@@ -1475,4 +2425,40 @@ public class MetalIconFactory implements Serializable
return new TreeControlIcon(isCollapsed);
}
+ /**
+ * Returns a <code>16x16</code> icon representing a computer.
+ *
+ * @return The icon.
+ */
+ public static Icon getTreeComputerIcon()
+ {
+ if (treeComputerIcon == null)
+ treeComputerIcon = new TreeComputerIcon();
+ return treeComputerIcon;
+ }
+
+ /**
+ * Returns a <code>16x16</code> icon representing a floppy disk.
+ *
+ * @return The icon.
+ */
+ public static Icon getTreeFloppyDriveIcon()
+ {
+ if (treeFloppyDriveIcon == null)
+ treeFloppyDriveIcon = new TreeFloppyDriveIcon();
+ return treeFloppyDriveIcon;
+ }
+
+ /**
+ * Returns a <code>16x16</code> icon representing a hard disk.
+ *
+ * @return The icon.
+ */
+ public static Icon getTreeHardDriveIcon()
+ {
+ if (treeHardDriveIcon == null)
+ treeHardDriveIcon = new TreeHardDriveIcon();
+ return treeHardDriveIcon;
+ }
+
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java
index 20526eba8cd..33eb3491ad0 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java
@@ -38,30 +38,208 @@ exception statement from your version. */
package javax.swing.plaf.metal;
+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.Rectangle;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import javax.swing.Icon;
import javax.swing.JInternalFrame;
+import javax.swing.JLabel;
import javax.swing.JMenu;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
+
/**
- * The title pane for a {@link JInternalFrame}.
+ * The title pane for a {@link JInternalFrame} (see
+ * {@link MetalInternalFrameUI#createNorthPane(JInternalFrame)}). This can
+ * be displayed in two styles: one for regular internal frames, and the other
+ * for "palette" style internal frames.
*/
public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane
{
+ /**
+ * A property change handler that listens for changes to the
+ * <code>JInternalFrame.isPalette</code> property and updates the title
+ * pane as appropriate.
+ */
+ class MetalInternalFrameTitlePanePropertyChangeHandler
+ extends PropertyChangeHandler
+ {
+ /**
+ * Creates a new handler.
+ */
+ public MetalInternalFrameTitlePanePropertyChangeHandler()
+ {
+ super();
+ }
+
+ /**
+ * Handles <code>JInternalFrame.isPalette</code> property changes, with all
+ * other property changes being passed to the superclass.
+ *
+ * @param e the event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ String propName = e.getPropertyName();
+ if (propName.equals("JInternalFrame.isPalette"))
+ {
+ if (e.getNewValue().equals(Boolean.TRUE))
+ setPalette(true);
+ else
+ setPalette(false);
+ }
+ else
+ super.propertyChange(e);
+ }
+ }
+
+ /**
+ * A layout manager for the title pane.
+ *
+ * @see #createLayout()
+ */
+ private class MetalTitlePaneLayout implements LayoutManager
+ {
+ /**
+ * Creates a new <code>TitlePaneLayout</code> object.
+ */
+ public MetalTitlePaneLayout()
+ {
+ // Do nothing.
+ }
+
+ /**
+ * Adds a Component to the Container.
+ *
+ * @param name The name to reference the added Component by.
+ * @param c The Component to add.
+ */
+ public void addLayoutComponent(String name, Component c)
+ {
+ // Do nothing.
+ }
+
+ /**
+ * This method is called to lay out the children of the Title Pane.
+ *
+ * @param c The Container to lay out.
+ */
+ public void layoutContainer(Container c)
+ {
+
+ Dimension size = c.getSize();
+ Insets insets = c.getInsets();
+ int width = size.width - insets.left - insets.right;
+ int height = size.height - insets.top - insets.bottom;
+
+
+ int loc = width - insets.right - 1;
+ int top = insets.top + 2;
+ int buttonHeight = height - 4;
+ if (closeButton.isVisible())
+ {
+ int buttonWidth = closeIcon.getIconWidth();
+ loc -= buttonWidth + 2;
+ closeButton.setBounds(loc, top, buttonWidth, buttonHeight);
+ loc -= 6;
+ }
+
+ if (maxButton.isVisible())
+ {
+ int buttonWidth = maxIcon.getIconWidth();
+ loc -= buttonWidth + 4;
+ maxButton.setBounds(loc, top, buttonWidth, buttonHeight);
+ }
+
+ if (iconButton.isVisible())
+ {
+ int buttonWidth = minIcon.getIconWidth();
+ loc -= buttonWidth + 4;
+ iconButton.setBounds(loc, top, buttonWidth, buttonHeight);
+ loc -= 2;
+ }
+
+ Dimension titlePreferredSize = title.getPreferredSize();
+ title.setBounds(insets.left + 5, insets.top,
+ Math.min(titlePreferredSize.width, loc - insets.left - 10),
+ height);
+
+ }
+
+ /**
+ * This method returns the minimum size of the given Container given the
+ * children that it has.
+ *
+ * @param c The Container to get a minimum size for.
+ *
+ * @return The minimum size of the Container.
+ */
+ public Dimension minimumLayoutSize(Container c)
+ {
+ return preferredLayoutSize(c);
+ }
+
+ /**
+ * Returns the preferred size of the given Container taking
+ * into account the children that it has.
+ *
+ * @param c The Container to lay out.
+ *
+ * @return The preferred size of the Container.
+ */
+ public Dimension preferredLayoutSize(Container c)
+ {
+ if (isPalette)
+ return new Dimension(paletteTitleHeight, paletteTitleHeight);
+ else
+ return new Dimension(22, 22);
+ }
+
+ /**
+ * Removes a Component from the Container.
+ *
+ * @param c The Component to remove.
+ */
+ public void removeLayoutComponent(Component c)
+ {
+ // Nothing to do here.
+ }
+ }
+
+ /** A flag indicating whether the title pane uses the palette style. */
protected boolean isPalette;
- protected Icon paletteCloseIcon = MetalIconFactory.getInternalFrameCloseIcon(16);
+ /**
+ * The icon used for the close button - this is fetched from the look and
+ * feel defaults using the key <code>InternalFrame.paletteCloseIcon</code>.
+ */
+ protected Icon paletteCloseIcon;
+
+ /**
+ * The height of the title pane when <code>isPalette</code> is
+ * <code>true</code>. This value is fetched from the look and feel defaults
+ * using the key <code>InternalFrame.paletteTitleHeight</code>.
+ */
+ protected int paletteTitleHeight;
+
+ /** The label used to display the title for the internal frame. */
+ JLabel title;
- protected int paletteTitleHeight = 12;
-
/**
- * Creates a new title pane.
+ * Creates a new title pane for the specified frame.
*
* @param f the internal frame.
*/
@@ -81,6 +259,15 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane
selectedTitleColor = MetalLookAndFeel.getWindowTitleBackground();
notSelectedTextColor = MetalLookAndFeel.getInactiveControlTextColor();
notSelectedTitleColor = MetalLookAndFeel.getWindowTitleInactiveBackground();
+
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ paletteTitleHeight = defaults.getInt("InternalFrame.paletteTitleHeight");
+ paletteCloseIcon = defaults.getIcon("InternalFrame.paletteCloseIcon");
+ minIcon = MetalIconFactory.getInternalFrameAltMaximizeIcon(16);
+
+ title = new JLabel(frame.getTitle(),
+ MetalIconFactory.getInternalFrameDefaultMenuIcon(),
+ SwingConstants.LEFT);
}
/**
@@ -93,6 +280,9 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane
selectedTitleColor = null;
notSelectedTextColor = null;
notSelectedTitleColor = null;
+ paletteCloseIcon = null;
+ minIcon = null;
+ title = null;
}
/**
@@ -128,44 +318,123 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane
}
/**
- * Creates a layout manager for the components in the title pane.
+ * Adds the sub components of the title pane.
+ */
+ protected void addSubComponents()
+ {
+ // FIXME: this method is probably overridden to only add the required
+ // buttons
+ add(title);
+ add(closeButton);
+ add(iconButton);
+ add(maxButton);
+ }
+
+ /**
+ * Creates a new instance of {@link MetalTitlePaneLayout}.
*
- * @return A layout manager.
- */
+ * @return A new instance of {@link MetalTitlePaneLayout}.
+ */
protected LayoutManager createLayout()
{
- return new TitlePaneLayout()
- {
- public Dimension preferredLayoutSize(Container c)
- {
- return new Dimension(24, 24);
- }
- };
+ return new MetalTitlePaneLayout();
}
+ /**
+ * Draws the title pane in the palette style.
+ *
+ * @param g the graphics device.
+ *
+ * @see #paintComponent(Graphics)
+ */
public void paintPalette(Graphics g)
{
- // FIXME: needs implementing
- // most likely this is equivalent to paintComponent(g) when the isPalette
- // flag is true
+ Color savedColor = g.getColor();
+ Rectangle b = SwingUtilities.getLocalBounds(this);
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ g.fillRect(b.x, b.y, b.width, b.height);
+ MetalUtils.fillMetalPattern(this, g, b.x + 4, b.y + 2, b.width
+ - paletteCloseIcon.getIconWidth() - 13, b.height - 5,
+ MetalLookAndFeel.getPrimaryControlHighlight(),
+ MetalLookAndFeel.getBlack());
+
+ // draw a line separating the title pane from the frame content
+ Dimension d = getSize();
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ g.drawLine(0, d.height - 1, d.width - 1, d.height - 1);
+
+ g.setColor(savedColor);
}
-
+
+ /**
+ * Paints a representation of the current state of the internal frame.
+ *
+ * @param g the graphics device.
+ */
public void paintComponent(Graphics g)
{
- // probably need to check the isPalette flag here, if true pass over to
- // paintPalette(Graphics)
- super.paintComponent(g);
- Dimension d = getSize();
- if (frame.isSelected())
- g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ Color savedColor = g.getColor();
+ if (isPalette)
+ paintPalette(g);
else
- g.setColor(MetalLookAndFeel.getControlDarkShadow());
- g.drawLine(0, d.height - 1, d.width - 1, d.height - 1);
+ {
+ paintTitleBackground(g);
+ paintChildren(g);
+ Dimension d = getSize();
+ if (frame.isSelected())
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+
+ // put a dot in each of the top corners
+ g.drawLine(0, 0, 0, 0);
+ g.drawLine(d.width - 1, 0, d.width - 1, 0);
+
+ g.drawLine(0, d.height - 1, d.width - 1, d.height - 1);
+
+ // draw the metal pattern
+ Rectangle b = title.getBounds();
+ int startX = b.x + b.width + 5;
+ int endX = startX;
+ if (iconButton.isVisible())
+ endX = Math.max(iconButton.getX(), endX);
+ else if (maxButton.isVisible())
+ endX = Math.max(maxButton.getX(), endX);
+ else if (closeButton.isVisible())
+ endX = Math.max(closeButton.getX(), endX);
+ endX -= 7;
+ if (endX > startX)
+ MetalUtils.fillMetalPattern(this, g, startX, 3, endX - startX, getHeight() - 6, Color.white, Color.gray);
+ }
+ g.setColor(savedColor);
}
+ /**
+ * Sets the flag that controls whether the title pane is drawn in the
+ * palette style or the regular style.
+ *
+ * @param b the new value of the flag.
+ */
public void setPalette(boolean b)
{
- isPalette = b;
+ isPalette = b;
+ title.setVisible(!isPalette);
+ iconButton.setVisible(!isPalette && frame.isIconifiable());
+ maxButton.setVisible(!isPalette && frame.isMaximizable());
+ if (isPalette)
+ closeButton.setIcon(paletteCloseIcon);
+ else
+ closeButton.setIcon(closeIcon);
+ }
+
+ /**
+ * Creates and returns a property change handler for the title pane.
+ *
+ * @return The property change handler.
+ */
+ protected PropertyChangeListener createPropertyChangeListener()
+ {
+ return new MetalInternalFrameTitlePanePropertyChangeHandler();
}
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java
index 7c7cb92e549..6be573f4bac 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java
@@ -38,24 +38,31 @@ exception statement from your version. */
package javax.swing.plaf.metal;
-import java.util.HashMap;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JInternalFrame;
-import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicInternalFrameUI;
-
+/**
+ * A UI delegate for the {@link JInternalFrame} component.
+ */
public class MetalInternalFrameUI
extends BasicInternalFrameUI
{
-
- /** The instances of MetalInternalFrameUI*/
- private static HashMap instances;
+ /**
+ * The key (<code>JInternalFrame.isPalette</code>) for the client property
+ * that controls whether the internal frame is displayed using the palette
+ * style.
+ */
+ protected static String IS_PALETTE = "JInternalFrame.isPalette";
/**
- * Constructs a new instance of MetalInternalFrameUI.
+ * Constructs a new instance of <code>MetalInternalFrameUI</code>.
+ *
+ * @param frame the frame.
*/
public MetalInternalFrameUI(JInternalFrame frame)
{
@@ -63,37 +70,96 @@ public class MetalInternalFrameUI
}
/**
- * Returns an instance of MetalInternalFrameUI.
+ * Returns an instance of <code>MetalInternalFrameUI</code>.
*
- * @param component the component for which we return an UI instance
+ * @param component the internal frame.
*
- * @return an instance of MetalInternalFrameUI
+ * @return an instance of <code>MetalInternalFrameUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
- if (instances == null)
- instances = new HashMap();
-
-
- Object o = instances.get(component);
- MetalInternalFrameUI instance;
- if (o == null)
- {
- instance = new MetalInternalFrameUI((JInternalFrame) component);
- instances.put(component, instance);
- }
- else
- instance = (MetalInternalFrameUI) o;
-
- return instance;
+ return new MetalInternalFrameUI((JInternalFrame) component);
}
+ /**
+ * Sets the fields and properties for the component.
+ *
+ * @param c the component.
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ JInternalFrame f = (JInternalFrame) c;
+ boolean isPalette = false;
+ Boolean p = (Boolean) f.getClientProperty(IS_PALETTE);
+ if (p != null)
+ isPalette = p.booleanValue();
+ setPalette(isPalette);
+ }
+
+ /**
+ * Creates and returns the component that will be used for the north pane
+ * of the {@link JInternalFrame}.
+ *
+ * @param w the internal frame.
+ *
+ * @return A new instance of {@link MetalInternalFrameTitlePane}.
+ */
protected JComponent createNorthPane(JInternalFrame w)
{
titlePane = new MetalInternalFrameTitlePane(w);
- titlePane.setBorder(new EmptyBorder(2, 2, 2, 2));
return titlePane;
}
-
+ /**
+ * Sets the state of the {@link JInternalFrame} to reflect whether or not
+ * it is using the palette style. When a frame is displayed as a palette,
+ * it uses a different border and the title pane is drawn differently.
+ *
+ * @param isPalette use the palette style?
+ */
+ public void setPalette(boolean isPalette)
+ {
+ MetalInternalFrameTitlePane title = (MetalInternalFrameTitlePane) northPane;
+ title.setPalette(isPalette);
+ if (isPalette)
+ frame.setBorder(new MetalBorders.PaletteBorder());
+ else
+ frame.setBorder(new MetalBorders.InternalFrameBorder());
+ }
+
+ /** A listener that is used to handle IS_PALETTE property changes. */
+ private PropertyChangeListener paletteListener;
+
+ /**
+ * Adds the required listeners.
+ */
+ protected void installListeners()
+ {
+ super.installListeners();
+ paletteListener = new PropertyChangeListener()
+ {
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals(IS_PALETTE))
+ {
+ if (Boolean.TRUE.equals(e.getNewValue()))
+ setPalette(true);
+ else
+ setPalette(false);
+ }
+ }
+ };
+ frame.addPropertyChangeListener(paletteListener);
+ }
+
+ /**
+ * Removes the listeners used.
+ */
+ protected void uninstallListeners()
+ {
+ super.uninstallListeners();
+ frame.removePropertyChangeListener(IS_PALETTE, paletteListener);
+ paletteListener = null;
+ }
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java
index fe8a9e4e4ea..e4eaa71724d 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java
@@ -50,17 +50,17 @@ import javax.swing.plaf.basic.BasicGraphicsUtils;
import javax.swing.plaf.basic.BasicLabelUI;
/**
- * A UI delegate used for {@link JLabel}s in the {@link MetalLookAndFeel}.
+ * A UI delegate for the {@link JLabel} component.
*/
public class MetalLabelUI
extends BasicLabelUI
{
- /** The shared UI instance for JLabels. */
+ /** The shared instance of the UI delegate. */
protected static MetalLabelUI metalLabelUI;
/**
- * Constructs a new instance of MetalLabelUI.
+ * Constructs a new instance of <code>MetalLabelUI</code>.
*/
public MetalLabelUI()
{
@@ -68,11 +68,11 @@ public class MetalLabelUI
}
/**
- * Returns an instance of MetalLabelUI.
+ * Returns a shared instance of <code>MetalLabelUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalLabelUI
+ * @return A shared instance of <code>MetalLabelUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java
index d9cf7c6220c..ec8014b17b3 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java
@@ -42,11 +42,14 @@ import java.awt.Color;
import java.awt.Font;
import java.awt.Insets;
+import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;
+import javax.swing.UIManager;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.InsetsUIResource;
+import javax.swing.plaf.BorderUIResource.LineBorderUIResource;
import javax.swing.plaf.basic.BasicLookAndFeel;
@@ -69,7 +72,8 @@ public class MetalLookAndFeel extends BasicLookAndFeel
*/
public MetalLookAndFeel()
{
- createDefaultTheme();
+ if (theme == null)
+ createDefaultTheme();
}
/**
@@ -601,12 +605,21 @@ public class MetalLookAndFeel extends BasicLookAndFeel
}
/**
- * Sets the current theme for the look and feel.
+ * Sets the current theme for the look and feel. Note that the theme must be
+ * set <em>before</em> the look and feel is installed. To change the theme
+ * for an already running application that is using the
+ * {@link MetalLookAndFeel}, first set the theme with this method, then
+ * create a new instance of {@link MetalLookAndFeel} and install it in the
+ * usual way (see {@link UIManager#setLookAndFeel(LookAndFeel)}).
*
- * @param theme the theme.
+ * @param theme the theme (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>theme</code> is <code>null</code>.
*/
public static void setCurrentTheme(MetalTheme theme)
{
+ if (theme == null)
+ throw new NullPointerException("Null 'theme' not permitted.");
MetalLookAndFeel.theme = theme;
}
@@ -759,62 +772,206 @@ public class MetalLookAndFeel extends BasicLookAndFeel
{
super.initComponentDefaults(defaults);
Object[] myDefaults = new Object[] {
- "Button.background", new ColorUIResource(getControl()),
+ "Button.background", getControl(),
"Button.border", MetalBorders.getButtonBorder(),
- "Button.darkShadow", new ColorUIResource(getControlDarkShadow()),
- "Button.disabledText", new ColorUIResource(getControlDisabled()),
- "Button.focus", new ColorUIResource(getFocusColor()),
+ "Button.darkShadow", getControlDarkShadow(),
+ "Button.disabledText", getInactiveControlTextColor(),
+ "Button.focus", getFocusColor(),
"Button.font", getControlTextFont(),
- "Button.foreground", new ColorUIResource(getSystemTextColor()),
- "Button.highlight", new ColorUIResource(getControlHighlight()),
- "Button.light", new ColorUIResource(getControlHighlight()),
- "Button.margin", new Insets(2, 14, 2, 14),
- "Button.select", new ColorUIResource(getPrimaryControlShadow()),
- "Button.shadow", new ColorUIResource(getPrimaryControlShadow()),
- "CheckBox.background", new ColorUIResource(getControl()),
+ "Button.foreground", getControlTextColor(),
+ "Button.highlight", getControlHighlight(),
+ "Button.light", getControlHighlight(),
+ "Button.margin", new InsetsUIResource(2, 14, 2, 14),
+ "Button.select", getControlShadow(),
+ "Button.shadow", getControlShadow(),
+
+ "CheckBox.background", getControl(),
"CheckBox.border", MetalBorders.getButtonBorder(),
+ "CheckBox.disabledText", getInactiveControlTextColor(),
+ "CheckBox.focus", getFocusColor(),
+ "CheckBox.font", new FontUIResource("Dialog", Font.BOLD, 12),
+ "CheckBox.foreground", getControlTextColor(),
"CheckBox.icon",
new UIDefaults.ProxyLazyValue
("javax.swing.plaf.metal.MetalCheckBoxIcon"),
"CheckBox.checkIcon",
new UIDefaults.ProxyLazyValue
("javax.swing.plaf.metal.MetalCheckBoxIcon"),
- "CheckBoxMenuItem.background", new ColorUIResource(getControl()),
+ "Checkbox.select", getControlShadow(),
+
+ "CheckBoxMenuItem.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 10),
+ "CheckBoxMenuItem.acceleratorForeground", getAcceleratorForeground(),
+ "CheckBoxMenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(),
+ "CheckBoxMenuItem.background", getMenuBackground(),
+ "CheckBoxMenuItem.borderPainted", new Boolean(true),
+ "CheckBoxMenuItem.commandSound", "sounds/MenuItemCommand.wav",
"CheckBoxMenuItem.checkIcon", MetalIconFactory.getCheckBoxMenuItemIcon(),
- "ToolBar.background", new ColorUIResource(getControl()),
- "Panel.background", new ColorUIResource(getControl()),
- "Slider.background", new ColorUIResource(getControl()),
- "OptionPane.background", new ColorUIResource(getControl()),
- "ProgressBar.background", new ColorUIResource(getControl()),
- "ScrollPane.border", new MetalBorders.ScrollPaneBorder(),
- "TabbedPane.background", new ColorUIResource(getControl()),
+ "CheckBoxMenuItem.disabledForeground", getMenuDisabledForeground(),
+ "CheckBoxMenuItem.font", new FontUIResource("Dialog", Font.BOLD, 12),
+ "CheckBoxMenuItem.foreground", getMenuForeground(),
+ "CheckBoxMenuItem.selectionBackground", getMenuSelectedBackground(),
+ "CheckBoxMenuItem.selectionForeground", getMenuSelectedForeground(),
+
+ "ColorChooser.background", getControl(),
+ "ColorChooser.foreground", getControlTextColor(),
+ "ColorChooser.rgbBlueMnemonic", new Integer(0),
+ "ColorChooser.rgbGreenMnemonic", new Integer(0),
+ "ColorChooser.rgbRedMnemonic", new Integer(0),
+ "ColorChooser.swatchesDefaultRecentColor", getControl(),
+
+ "ComboBox.background", getControl(),
+ "ComboBox.buttonBackground", getControl(),
+ "ComboBox.buttonDarkShadow", getControlDarkShadow(),
+ "ComboBox.buttonHighlight", getControlHighlight(),
+ "ComboBox.buttonShadow", getControlShadow(),
+ "ComboBox.disabledBackground", getControl(),
+ "ComboBox.disabledForeground", getInactiveSystemTextColor(),
+ "ComboBox.font", new FontUIResource("Dialog", Font.BOLD, 12),
+ "ComboBox.foreground", getControlTextColor(),
+ "ComboBox.selectionBackground", getPrimaryControlShadow(),
+ "ComboBox.selectionForeground", getControlTextColor(),
+
+ "Desktop.background", getDesktopColor(),
+
+ "DesktopIcon.background", getControl(),
+ "DesktopIcon.foreground", getControlTextColor(),
+ "DesktopIcon.width", new Integer(160),
+ "DesktopIcon.border", MetalBorders.getDesktopIconBorder(),
+
+ "EditorPane.background", getWindowBackground(),
+ "EditorPane.caretForeground", getUserTextColor(),
+ "EditorPane.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "EditorPane.foreground", getUserTextColor(),
+ "EditorPane.inactiveForeground", getInactiveSystemTextColor(),
+ "EditorPane.selectionBackground", getTextHighlightColor(),
+ "EditorPane.selectionForeground", getHighlightedTextColor(),
+
+ "FormattedTextField.background", getWindowBackground(),
+ "FormattedTextField.border",
+ new BorderUIResource(MetalBorders.getTextFieldBorder()),
+ "FormattedTextField.caretForeground", getUserTextColor(),
+ "FormattedTextField.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "FormattedTextField.foreground", getUserTextColor(),
+ "FormattedTextField.inactiveBackground", getControl(),
+ "FormattedTextField.inactiveForeground", getInactiveSystemTextColor(),
+ "FormattedTextField.selectionBackground", getTextHighlightColor(),
+ "FormattedTextField.selectionForeground", getHighlightedTextColor(),
+
+ "FileView.computerIcon", MetalIconFactory.getTreeComputerIcon(),
+ "FileView.directoryIcon", MetalIconFactory.getTreeFolderIcon(),
+ "FileView.fileIcon", MetalIconFactory.getTreeLeafIcon(),
+ "FileView.floppyDriveIcon", MetalIconFactory.getTreeFloppyDriveIcon(),
+ "FileView.hardDriveIcon", MetalIconFactory.getTreeHardDriveIcon(),
+
+ "InternalFrame.activeTitleBackground", getWindowTitleBackground(),
+ "InternalFrame.activeTitleForeground", getWindowTitleForeground(),
"InternalFrame.border", new MetalBorders.InternalFrameBorder(),
+ "InternalFrame.borderColor", getControl(),
+ "InternalFrame.borderDarkShadow", getControlDarkShadow(),
+ "InternalFrame.borderHighlight", getControlHighlight(),
+ "InternalFrame.borderLight", getControlHighlight(),
+ "InternalFrame.borderShadow", getControlShadow(),
"InternalFrame.icon", MetalIconFactory.getInternalFrameDefaultMenuIcon(),
"InternalFrame.closeIcon",
MetalIconFactory.getInternalFrameCloseIcon(16),
+ "InternalFrame.inactiveTitleBackground", getWindowTitleInactiveBackground(),
+ "InternalFrame.inactiveTitleForeground", getWindowTitleInactiveForeground(),
"InternalFrame.maximizeIcon",
MetalIconFactory.getInternalFrameMaximizeIcon(16),
"InternalFrame.iconifyIcon",
MetalIconFactory.getInternalFrameMinimizeIcon(16),
- "Label.background", new ColorUIResource(getControl()),
+ "InternalFrame.paletteBorder", new MetalBorders.PaletteBorder(),
+ "InternalFrame.paletteCloseIcon", new MetalIconFactory.PaletteCloseIcon(),
+ "InternalFrame.paletteTitleHeight", new Integer(11),
+
+ "Label.background", getControl(),
+ "Label.disabledForeground", getInactiveSystemTextColor(),
+ "Label.disabledShadow", getControlShadow(),
"Label.font", getControlTextFont(),
- "Label.disabledForeground", new ColorUIResource(getInactiveControlTextColor()),
- "Label.foreground", new ColorUIResource(getControlTextColor()),
- "Menu.background", new ColorUIResource(getControl()),
+ "Label.foreground", getSystemTextColor(),
+
+ "List.font", getControlTextFont(),
+ "List.background", getWindowBackground(),
+ "List.foreground", getUserTextColor(),
+ "List.selectionBackground", getTextHighlightColor(),
+ "List.selectionForeground", getHighlightedTextColor(),
+ "List.focusCellHighlightBorder",
+ new LineBorderUIResource(MetalLookAndFeel.getFocusColor()),
+
+ "Menu.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 10),
+ "Menu.acceleratorForeground", getAcceleratorForeground(),
+ "Menu.acceleratorSelectionForeground", getAcceleratorSelectedForeground(),
+ "Menu.background", getMenuBackground(),
"Menu.border", new MetalBorders.MenuItemBorder(),
"Menu.borderPainted", Boolean.TRUE,
+ "Menu.disabledForeground", getMenuDisabledForeground(),
"Menu.font", getControlTextFont(),
+ "Menu.foreground", getMenuForeground(),
"Menu.selectionBackground", getMenuSelectedBackground(),
"Menu.selectionForeground", getMenuSelectedForeground(),
- "MenuBar.background", new ColorUIResource(getControl()),
+
+ "MenuBar.background", getMenuBackground(),
"MenuBar.border", new MetalBorders.MenuBarBorder(),
"MenuBar.font", getControlTextFont(),
- "MenuItem.background", new ColorUIResource(getControl()),
+ "MenuBar.foreground", getMenuForeground(),
+ "MenuBar.highlight", getControlHighlight(),
+ "MenuBar.shadow", getControlShadow(),
+
+ "MenuItem.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 10),
+ "MenuItem.acceleratorForeground", getAcceleratorForeground(),
+ "MenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(),
+ "MenuItem.background", getMenuBackground(),
"MenuItem.border", new MetalBorders.MenuItemBorder(),
+ "MenuItem.disabledForeground", getMenuDisabledForeground(),
"MenuItem.font", getControlTextFont(),
+ "MenuItem.foreground", getMenuForeground(),
"MenuItem.selectionBackground", getMenuSelectedBackground(),
"MenuItem.selectionForeground", getMenuSelectedForeground(),
- "Panel.background", new ColorUIResource(getControl()),
+
+ "OptionPane.background", getControl(),
+ "OptionPane.errorDialog.border.background", new ColorUIResource(153, 51, 51),
+ "OptionPane.errorDialog.titlePane.background", new ColorUIResource(255, 153, 153),
+ "OptionPane.errorDialog.titlePane.foreground", new ColorUIResource(51, 0, 0),
+ "OptionPane.errorDialog.titlePane.shadow", new ColorUIResource(204, 102, 102),
+ "OptionPane.foreground", getControlTextColor(),
+ "OptionPane.messageForeground", getControlTextColor(),
+ "OptionPane.questionDialog.border.background", new ColorUIResource(51, 102, 51),
+ "OptionPane.questionDialog.titlePane.background", new ColorUIResource(153, 204, 153),
+ "OptionPane.questionDialog.titlePane.foreground", new ColorUIResource(0, 51, 0),
+ "OptionPane.questionDialog.titlePane.shadow", new ColorUIResource(102, 153, 102),
+ "OptionPane.warningDialog.border.background", new ColorUIResource(153, 102, 51),
+ "OptionPane.warningDialog.titlePane.background", new ColorUIResource(255, 204, 153),
+ "OptionPane.warningDialog.titlePane.foreground", new ColorUIResource(102, 51, 0),
+ "OptionPane.warningDialog.titlePane.shadow", new ColorUIResource(204, 153, 102),
+
+ "Panel.background", getControl(),
+ "Panel.foreground", getUserTextColor(),
+
+ "PasswordField.background", getWindowBackground(),
+ "PasswordField.border",
+ new BorderUIResource(MetalBorders.getTextFieldBorder()),
+ "PasswordField.caretForeground", getUserTextColor(),
+ "PasswordField.foreground", getUserTextColor(),
+ "PasswordField.inactiveBackground", getControl(),
+ "PasswordField.inactiveForeground", getInactiveSystemTextColor(),
+ "PasswordField.selectionBackground", getTextHighlightColor(),
+ "PasswordField.selectionForeground", getHighlightedTextColor(),
+
+ "PopupMenu.background", getMenuBackground(),
+ "PopupMenu.border", new MetalBorders.PopupMenuBorder(),
+ "PopupMenu.font", new FontUIResource("Dialog", Font.BOLD, 12),
+ "PopupMenu.foreground", getMenuForeground(),
+
+ "ProgressBar.background", getControl(),
+ "ProgressBar.border", new BorderUIResource.LineBorderUIResource(getControlDarkShadow(), 1),
+ "ProgressBar.font", new FontUIResource("Dialog", Font.BOLD, 12),
+ "ProgressBar.foreground", getPrimaryControlShadow(),
+ "ProgressBar.selectionBackground", getPrimaryControlDarkShadow(),
+ "ProgressBar.selectionForeground", getControl(),
+
+ "RadioButton.background", getControl(),
+ "RadioButton.darkShadow", getControlDarkShadow(),
+ "RadioButton.disabledText", getInactiveControlTextColor(),
"RadioButton.icon",
new UIDefaults.LazyValue()
{
@@ -823,80 +980,199 @@ public class MetalLookAndFeel extends BasicLookAndFeel
return MetalIconFactory.getRadioButtonIcon();
}
},
-
+ "RadioButton.focus", MetalLookAndFeel.getFocusColor(),
+ "RadioButton.font", MetalLookAndFeel.getControlTextFont(),
+ "RadioButton.foreground", getControlTextColor(),
+ "RadioButton.highlight", getControlHighlight(),
+ "RadioButton.light", getControlHighlight(),
+ "RadioButton.select", getControlShadow(),
+ "RadioButton.shadow", getControlShadow(),
+
+ "RadioButtonMenuItem.acceleratorFont", new Font("Dialog", Font.PLAIN, 10),
+ "RadioButtonMenuItem.acceleratorForeground", getAcceleratorForeground(),
+ "RadioButtonMenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(),
+ "RadioButtonMenuItem.background", getMenuBackground(),
"RadioButtonMenuItem.border", new MetalBorders.MenuItemBorder(),
"RadioButtonMenuItem.borderPainted", Boolean.TRUE,
"RadioButtonMenuItem.checkIcon",
MetalIconFactory.getRadioButtonMenuItemIcon(),
+ "RadioButtonMenuItem.disabledForeground", getMenuDisabledForeground(),
"RadioButtonMenuItem.font", MetalLookAndFeel.getControlTextFont(),
+ "RadioButtonMenuItem.foreground", getMenuForeground(),
"RadioButtonMenuItem.margin", new InsetsUIResource(2, 2, 2, 2),
"RadioButtonMenuItem.selectionBackground",
MetalLookAndFeel.getMenuSelectedBackground(),
"RadioButtonMenuItem.selectionForeground",
MetalLookAndFeel.getMenuSelectedForeground(),
- "ScrollBar.background", new ColorUIResource(getControl()),
- "ScrollBar.shadow", new ColorUIResource(getControlShadow()),
- "ScrollBar.thumb", new ColorUIResource(getPrimaryControlShadow()),
- "ScrollBar.thumbDarkShadow",
- new ColorUIResource(getPrimaryControlDarkShadow()),
- "ScrollBar.thumbHighlight",
- new ColorUIResource(getPrimaryControl()),
+ "ScrollBar.background", getControl(),
+ "ScrollBar.darkShadow", getControlDarkShadow(),
+ "ScrollBar.foreground", getControl(),
+ "ScrollBar.highlight", getControlHighlight(),
+ "ScrollBar.shadow", getControlShadow(),
+ "ScrollBar.thumb", getPrimaryControlShadow(),
+ "ScrollBar.thumbDarkShadow", getControlDarkShadow(),
+ "ScrollBar.thumbHighlight", getPrimaryControl(),
+ "ScrollBar.thumbShadow", getPrimaryControlDarkShadow(),
+ "ScrollBar.track", getControl(),
+ "ScrollBar.trackHighlight", getControlDarkShadow(),
+ "ScrollBar.width", new Integer(17),
+
+ "ScrollPane.background", getControl(),
+ "ScrollPane.border", new MetalBorders.ScrollPaneBorder(),
+ "ScrollPane.foreground", getControlTextColor(),
- "SplitPane.darkShadow",
- new ColorUIResource(getControlDarkShadow()),
- "SplitPane.highlight",
- new ColorUIResource(getControlHighlight()),
+ "Separator.background", getSeparatorBackground(),
+ "Separator.foreground", getSeparatorForeground(),
+ "Separator.highlight", getControlHighlight(),
+ "Separator.shadow", getControlShadow(),
+ "Slider.background", getControl(),
+ "Slider.focus", getFocusColor(),
"Slider.focusInsets", new InsetsUIResource(0, 0, 0, 0),
+ "Slider.foreground", getPrimaryControlShadow(),
+ "Slider.highlight", getControlHighlight(),
"Slider.horizontalThumbIcon",
MetalIconFactory.getHorizontalSliderThumbIcon(),
+ "Slider.majorTickLength", new Integer(6),
+ "Slider.shadow", getControlShadow(),
+ "Slider.trackWidth", new Integer(7),
"Slider.verticalThumbIcon",
MetalIconFactory.getVerticalSliderThumbIcon(),
- "Slider.trackWidth", new Integer(7),
- "Slider.majorTickLength", new Integer(6),
-
+
+ "Spinner.background", getControl(),
+ "Spinner.font", new FontUIResource("Dialog", Font.BOLD, 12),
+ "Spinner.foreground", getControl(),
+
+ "SplitPane.background", getControl(),
+ "SplitPane.darkShadow", getControlDarkShadow(),
+ "SplitPane.dividerFocusColor", getPrimaryControl(),
+ "SplitPane.highlight", getControlHighlight(),
+ "SplitPane.shadow", getControlShadow(),
+
+ "SplitPaneDivider.draggingColor", Color.DARK_GRAY,
+
+ "TabbedPane.background", getControlShadow(),
+ "TabbedPane.darkShadow", getControlDarkShadow(),
+ "TabbedPane.focus", getPrimaryControlDarkShadow(),
"TabbedPane.font", new FontUIResource("Dialog", Font.BOLD, 12),
- "TabbedPane.tabInsets", new InsetsUIResource(0, 9, 1, 9),
+ "TabbedPane.foreground", getControlTextColor(),
+ "TabbedPane.highlight", getControlHighlight(),
+ "TabbedPane.light", getControl(),
+ "TabbedPane.selected", getControl(),
+ "TabbedPane.selectHighlight", getControlHighlight(),
"TabbedPane.selectedTabPadInsets", new InsetsUIResource(2, 2, 2, 1),
+ "TabbedPane.shadow", getControlShadow(),
+ "TabbedPane.tabAreaBackground", getControl(),
"TabbedPane.tabAreaInsets", new InsetsUIResource(4, 2, 0, 6),
-
- "ToggleButton.background", new ColorUIResource(getControl()),
- "ToggleButton.border", MetalBorders.getButtonBorder(),
- "ToggleButton.darkShadow", new ColorUIResource(getControlDarkShadow()),
- "ToggleButton.disabledText", new ColorUIResource(getControlDisabled()),
- "ToggleButton.focus", new ColorUIResource(getFocusColor()),
+ "TabbedPane.tabInsets", new InsetsUIResource(0, 9, 1, 9),
+
+ "Table.background", getWindowBackground(),
+ "Table.focusCellBackground", getWindowBackground(),
+ "Table.focusCellForeground", getControlTextColor(),
+ "Table.foreground", getControlTextColor(),
+ "Table.focusCellHighlightBorder",
+ new BorderUIResource.LineBorderUIResource(getControlShadow()),
+ "Table.focusCellBackground", getWindowBackground(),
+ "Table.gridColor", getControlDarkShadow(),
+ "Table.selectionBackground", new ColorUIResource(204, 204, 255),
+ "Table.selectionForeground", new ColorUIResource(0, 0, 0),
+
+ "TableHeader.background", getControl(),
+ "TableHeader.cellBorder", new MetalBorders.TableHeaderBorder(),
+ "TableHeader.foreground", getControlTextColor(),
+
+ "TextArea.background", getWindowBackground(),
+ "TextArea.caretForeground", getUserTextColor(),
+ "TextArea.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "TextArea.foreground", getUserTextColor(),
+ "TextArea.inactiveForeground", getInactiveSystemTextColor(),
+ "TextArea.selectionBackground", getTextHighlightColor(),
+ "TextArea.selectionForeground", getHighlightedTextColor(),
+
+ "TextField.background", getWindowBackground(),
+ "TextField.border",
+ new BorderUIResource(MetalBorders.getTextFieldBorder()),
+ "TextField.caretForeground", getUserTextColor(),
+ "TextField.darkShadow", getControlDarkShadow(),
+ "TextField.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "TextField.foreground", getUserTextColor(),
+ "TextField.highlight", getControlHighlight(),
+ "TextField.inactiveBackground", getControl(),
+ "TextField.inactiveForeground", getInactiveSystemTextColor(),
+ "TextField.light", getControlHighlight(),
+ "TextField.selectionBackground", getTextHighlightColor(),
+ "TextField.selectionForeground", getHighlightedTextColor(),
+ "TextField.shadow", getControlShadow(),
+
+ "TextPane.background", getWindowBackground(),
+ "TextPane.caretForeground", getUserTextColor(),
+ "TextPane.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "TextPane.foreground", getUserTextColor(),
+ "TextPane.inactiveForeground", getInactiveSystemTextColor(),
+ "TextPane.selectionBackground", getTextHighlightColor(),
+ "TextPane.selectionForeground", getHighlightedTextColor(),
+
+ "TitledBorder.font", new FontUIResource("Dialog", Font.BOLD, 12),
+ "TitledBorder.titleColor", getSystemTextColor(),
+
+ "ToggleButton.background", getControl(),
+ "ToggleButton.border", MetalBorders.getToggleButtonBorder(),
+ "ToggleButton.darkShadow", getControlDarkShadow(),
+ "ToggleButton.disabledText", getInactiveControlTextColor(),
+ "ToggleButton.focus", getFocusColor(),
"ToggleButton.font", getControlTextFont(),
- "ToggleButton.foreground", new ColorUIResource(getSystemTextColor()),
- "ToggleButton.highlight", new ColorUIResource(getControlHighlight()),
- "ToggleButton.light", new ColorUIResource(getControlHighlight()),
- "ToggleButton.margin", new Insets(2, 14, 2, 14),
- "ToggleButton.select", new ColorUIResource(getPrimaryControlShadow()),
- "ToggleButton.shadow", new ColorUIResource(getPrimaryControlShadow()),
-
- "Tree.openIcon", MetalIconFactory.getTreeFolderIcon(),
+ "ToggleButton.foreground", getControlTextColor(),
+ "ToggleButton.highlight", getControlHighlight(),
+ "ToggleButton.light", getControlHighlight(),
+ "ToggleButton.margin", new InsetsUIResource(2, 14, 2, 14),
+ "ToggleButton.select", getControlShadow(),
+ "ToggleButton.shadow", getControlShadow(),
+
+ "ToolBar.background", getMenuBackground(),
+ "ToolBar.darkShadow", getControlDarkShadow(),
+ "ToolBar.dockingBackground", getMenuBackground(),
+ "ToolBar.dockingForeground", getPrimaryControlDarkShadow(),
+ "ToolBar.floatingBackground", getMenuBackground(),
+ "ToolBar.floatingForeground", getPrimaryControl(),
+ "ToolBar.font", new FontUIResource("Dialog", Font.BOLD, 12),
+ "ToolBar.foreground", getMenuForeground(),
+ "ToolBar.highlight", getControlHighlight(),
+ "ToolBar.light", getControlHighlight(),
+ "ToolBar.shadow", getControlShadow(),
+ "ToolBar.border", new MetalBorders.ToolBarBorder(),
+
+ "ToolTip.background", getPrimaryControl(),
+ "ToolTip.backgroundInactive", getControl(),
+ "ToolTip.border", new BorderUIResource.LineBorderUIResource(getPrimaryControlDarkShadow(), 1),
+ "ToolTip.borderInactive", new BorderUIResource.LineBorderUIResource(getControlDarkShadow(), 1),
+ "ToolTip.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "ToolTip.foreground", getPrimaryControlInfo(),
+ "ToolTip.foregroundInactive", getControlDarkShadow(),
+
+ "Tree.background", getWindowBackground(),
"Tree.closedIcon", MetalIconFactory.getTreeFolderIcon(),
- "Tree.leafIcon", MetalIconFactory.getTreeLeafIcon(),
"Tree.collapsedIcon", MetalIconFactory.getTreeControlIcon(true),
"Tree.expandedIcon", MetalIconFactory.getTreeControlIcon(false),
- "Tree.font", new FontUIResource(new Font("Helvetica", Font.PLAIN, 12)),
- "Tree.background", new ColorUIResource(Color.white),
- "Tree.foreground", new ColorUIResource(new Color(204, 204, 255)),
- "Tree.hash", new ColorUIResource(new Color(204, 204, 255)),
+ "Tree.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "Tree.foreground", getUserTextColor(),
+ "Tree.hash", getPrimaryControl(),
+ "Tree.leafIcon", MetalIconFactory.getTreeLeafIcon(),
"Tree.leftChildIndent", new Integer(7),
+ "Tree.line", getPrimaryControl(),
+ "Tree.openIcon", MetalIconFactory.getTreeFolderIcon(),
"Tree.rightChildIndent", new Integer(13),
"Tree.rowHeight", new Integer(20),
"Tree.scrollsOnExpand", Boolean.TRUE,
- "Tree.selectionBackground", new ColorUIResource(new Color(204, 204, 255)),
- "Tree.nonSelectionBackground", new ColorUIResource(Color.white),
- "Tree.selectionBorderColor", new ColorUIResource(new Color(102, 102, 153)),
+ "Tree.selectionBackground", getTextHighlightColor(),
"Tree.selectionBorder", new BorderUIResource.LineBorderUIResource(new Color(102, 102, 153)),
- "Tree.nonSelectionBorder", new BorderUIResource.LineBorderUIResource(Color.white),
- "Tree.selectionForeground", new ColorUIResource(Color.black),
- "Tree.textBackground", new ColorUIResource(new Color(204, 204, 255)),
- "Tree.textForeground", new ColorUIResource(Color.black),
- "Tree.selectionForeground", new ColorUIResource(Color.black),
- "PopupMenu.border", new MetalBorders.PopupMenuBorder()
+ "Tree.selectionBorderColor", getFocusColor(),
+ "Tree.selectionForeground", getHighlightedTextColor(),
+ "Tree.textBackground", getWindowBackground(),
+ "Tree.textForeground", getUserTextColor(),
+
+ "Viewport.background", getControl(),
+ "Viewport.foreground", getUserTextColor()
};
defaults.putDefaults(myDefaults);
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java
index ec9bf2b5586..44a2d3bcd6a 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java
@@ -39,8 +39,12 @@ exception statement from your version. */
package javax.swing.plaf.metal;
import javax.swing.JComponent;
+import javax.swing.JPopupMenu;
import javax.swing.plaf.ComponentUI;
+/**
+ * A UI delegate for the {@link JPopupMenu.Separator} component.
+ */
public class MetalPopupMenuSeparatorUI
extends MetalSeparatorUI
{
@@ -50,7 +54,7 @@ public class MetalPopupMenuSeparatorUI
private static MetalPopupMenuSeparatorUI instance = null;
/**
- * Constructs a new instance of MetalPopupMenuSeparatorUI.
+ * Constructs a new instance of <code>MetalPopupMenuSeparatorUI</code>.
*/
public MetalPopupMenuSeparatorUI()
{
@@ -58,11 +62,11 @@ public class MetalPopupMenuSeparatorUI
}
/**
- * Returns an instance of MetalPopupMenuSeparatorUI.
+ * Returns a shared instance of <code>MetalPopupMenuSeparatorUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalPopupMenuSeparatorUI
+ * @return A shared instance of <code>MetalPopupMenuSeparatorUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java
index 96d1988fd3d..0f28818b96c 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java
@@ -38,20 +38,22 @@ exception statement from your version. */
package javax.swing.plaf.metal;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Insets;
+
import javax.swing.JComponent;
+import javax.swing.JProgressBar;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicProgressBarUI;
-public class MetalProgressBarUI
- extends BasicProgressBarUI
-{
-
- // FIXME: maybe replace by a Map of instances when this becomes stateful
- /** The shared UI instance for MetalProgressBarUIs */
- private static MetalProgressBarUI instance = null;
-
+/**
+ * A UI delegate for the {@link JProgressBar} component.
+ */
+public class MetalProgressBarUI extends BasicProgressBarUI
+{
/**
- * Constructs a new instance of MetalProgressBarUI.
+ * Constructs a new instance of <code>MetalProgressBarUI</code>.
*/
public MetalProgressBarUI()
{
@@ -59,16 +61,87 @@ public class MetalProgressBarUI
}
/**
- * Returns an instance of MetalProgressBarUI.
+ * Returns a new instance of <code>MetalProgressBarUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalProgressBarUI
+ * @return A new instance of <code>MetalProgressBarUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
- if (instance == null)
- instance = new MetalProgressBarUI();
- return instance;
+ return new MetalProgressBarUI();
+ }
+
+ /**
+ * Performs the painting for determinate progress bars. This calls the
+ * superclass behaviour and then adds some highlighting to the upper and left
+ * edge of the progress bar.
+ *
+ * @param g the graphics context
+ * @param c not used here
+ */
+ public void paintDeterminate(Graphics g, JComponent c)
+ {
+ super.paintDeterminate(g, c);
+ Color saved = g.getColor();
+ Insets i = progressBar.getInsets();
+ int w = progressBar.getWidth();
+ int h = progressBar.getHeight();
+ int orientation = progressBar.getOrientation();
+
+ Color shadow = MetalLookAndFeel.getControlShadow();
+ g.setColor(shadow);
+
+ g.drawLine(i.left, i.top, w - i.right, i.top);
+ g.drawLine(i.left, i.top, i.left, h - i.bottom);
+ int full = getAmountFull(i, w, h);
+ if (full > 0)
+ {
+ Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
+ g.setColor(darkShadow);
+ if (orientation == JProgressBar.HORIZONTAL)
+ {
+ g.drawLine(i.left, i.top, i.left, h - i.bottom);
+ g.drawLine(i.left, i.top, i.left + full - 1, i.top);
+ }
+ else
+ {
+ if (full >= (h - i.top - i.bottom))
+ g.drawLine(i.left, i.top, w - i.right, i.top);
+ g.drawLine(i.left, h - i.bottom, i.left, h - i.bottom - full);
+ }
+ }
+ g.setColor(saved);
+ }
+
+ /**
+ * Performs the painting for indeterminate progress bars. This calls the
+ * superclass behaviour and then adds some highlighting to the upper and left
+ * edge of the progress bar.
+ *
+ * @param g the graphics context
+ * @param c not used here
+ */
+ public void paintIndeterminate(Graphics g, JComponent c)
+ {
+ super.paintIndeterminate(g, c);
+ Color saved = g.getColor();
+ Insets i = progressBar.getInsets();
+ int w = progressBar.getWidth();
+ int h = progressBar.getHeight();
+ Color shadow = MetalLookAndFeel.getControlShadow();
+ g.setColor(shadow);
+ g.drawLine(i.left, i.top, w - i.right, i.top);
+ g.drawLine(i.left, i.top, i.left, h - i.bottom);
+
+ boxRect = getBox(boxRect);
+ Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
+ g.setColor(darkShadow);
+ int orientation = progressBar.getOrientation();
+ if (orientation == JProgressBar.HORIZONTAL)
+ g.drawLine(boxRect.x, i.top, boxRect.x + boxRect.width - 1, i.top);
+ else
+ g.drawLine(i.left, boxRect.y, i.left, boxRect.y + boxRect.height - 1);
+ g.setColor(saved);
}
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java
index a668f914e43..f37626e630f 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java
@@ -38,20 +38,38 @@ exception statement from your version. */
package javax.swing.plaf.metal;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import javax.swing.AbstractButton;
import javax.swing.JComponent;
+import javax.swing.JRadioButton;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicRadioButtonUI;
+
+/**
+ * A UI delegate for the {@link JRadioButton} component.
+ */
public class MetalRadioButtonUI
extends BasicRadioButtonUI
{
- // FIXME: maybe replace by a Map of instances when this becomes stateful
- /** The shared UI instance for JRadioButtons. */
- private static MetalRadioButtonUI instance = null;
-
+ /** Used to draw the focus rectangle. */
+ protected Color focusColor;
+
+ /** Used to fill the icon when the button is pressed. */
+ protected Color selectColor;
+
+ /** Used to draw disabled text. */
+ protected Color disabledTextColor;
+
/**
- * Constructs a new instance of MetalRadioButtonUI.
+ * Constructs a new instance of <code>MetalRadioButtonUI</code>.
*/
public MetalRadioButtonUI()
{
@@ -59,16 +77,108 @@ public class MetalRadioButtonUI
}
/**
- * Returns an instance of MetalRadioButtonUI.
+ * Returns a new instance of <code>MetalRadioButtonUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalRadioButtonUI
+ * @return A new instance of <code>MetalRadioButtonUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
- if (instance == null)
- instance = new MetalRadioButtonUI();
- return instance;
+ return new MetalRadioButtonUI();
+ }
+
+ /**
+ * Sets the default values for the specified button.
+ *
+ * @param b the button.
+ */
+ public void installDefaults(AbstractButton b)
+ {
+ super.installDefaults(b);
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ disabledTextColor = defaults.getColor("RadioButton.disabledText");
+ focusColor = defaults.getColor("RadioButton.focus");
+ selectColor = defaults.getColor("RadioButton.select");
+ }
+
+ /**
+ * Clears any defaults set in the installDefaults() method.
+ *
+ * @param b the {@link JRadioButton}.
+ */
+ protected void uninstallDefaults(AbstractButton b)
+ {
+ super.uninstallDefaults(b);
+ disabledTextColor = null;
+ focusColor = null;
+ selectColor = null;
+ }
+
+ /**
+ * Returns the color used to fill the {@link JRadioButton}'s icon when the
+ * button is pressed. The default color is obtained from the
+ * {@link UIDefaults} via an entry with the key
+ * <code>RadioButton.select</code>.
+ *
+ * @return The select color.
+ */
+ protected Color getSelectColor()
+ {
+ return selectColor;
+ }
+
+ /**
+ * Returns the color for the {@link JRadioButton}'s text when the button is
+ * disabled. The default color is obtained from the {@link UIDefaults} via
+ * an entry with the key <code>RadioButton.disabledText</code>.
+ *
+ * @return The disabled text color.
+ */
+ protected Color getDisabledTextColor()
+ {
+ return disabledTextColor;
+ }
+
+ /**
+ * Returns the color used to draw the focus rectangle when the
+ * {@link JRadioButton} has the focus. The default color is obtained from
+ * the {@link UIDefaults} via an entry with the key
+ * <code>RadioButton.focus</code>.
+ *
+ * @return The color used to draw the focus rectangle.
+ *
+ * @see #paintFocus(Graphics, Rectangle, Dimension)
+ */
+ protected Color getFocusColor()
+ {
+ return focusColor;
+ }
+
+ /**
+ * Paints the {@link JRadioButton}.
+ *
+ * @param g the graphics device.
+ * @param c the component (an instance of {@link JRadioButton}).
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ super.paint(g, c);
+ // FIXME: disabled text isn't being drawn correctly, it's possible that
+ // it could be done here...
+ }
+
+ /**
+ * Paints the focus rectangle for the {@link JRadioButton}.
+ *
+ * @param g the graphics device.
+ * @param t the bounding rectangle for the text.
+ * @param d ???
+ */
+ protected void paintFocus(Graphics g, Rectangle t, Dimension d)
+ {
+ g.setColor(focusColor);
+ g.drawRect(t.x - 1, t.y + 2, t.width + 2, t.height - 4);
}
+
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java
index 4196a4e477c..faed80382d0 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java
@@ -39,9 +39,16 @@ exception statement from your version. */
package javax.swing.plaf.metal;
import javax.swing.JComponent;
+import javax.swing.JRootPane;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicRootPaneUI;
+/**
+ * A UI delegate for the {@link JRootPane} component. This class is not fully
+ * implemented.
+ *
+ * @since 1.4
+ */
public class MetalRootPaneUI
extends BasicRootPaneUI
{
@@ -51,7 +58,7 @@ public class MetalRootPaneUI
private static MetalRootPaneUI instance = null;
/**
- * Constructs a new instance of MetalRootPaneUI.
+ * Constructs a shared instance of <code>MetalRootPaneUI</code>.
*/
public MetalRootPaneUI()
{
@@ -59,11 +66,11 @@ public class MetalRootPaneUI
}
/**
- * Returns an instance of MetalRootPaneUI.
+ * Returns a shared instance of <code>MetalRootPaneUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalRootPaneUI
+ * @return A shared instance of <code>MetalRootPaneUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java
index 526dfb50ae2..9602ade9947 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java
@@ -38,30 +38,106 @@ exception statement from your version. */
package javax.swing.plaf.metal;
+import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
-import java.util.HashMap;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.swing.JButton;
import javax.swing.JComponent;
+import javax.swing.JScrollBar;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicScrollBarUI;
-public class MetalScrollBarUI
- extends BasicScrollBarUI
+/**
+ * A UI delegate for the {@link JScrollBar} component.
+ */
+public class MetalScrollBarUI extends BasicScrollBarUI
{
+
+ /**
+ * A property change handler for the UI delegate that monitors for
+ * changes to the "JScrollBar.isFreeStanding" property, and updates
+ * the buttons and track rendering as appropriate.
+ */
+ class MetalScrollBarPropertyChangeHandler
+ extends BasicScrollBarUI.PropertyChangeHandler
+ {
+ /**
+ * Creates a new handler.
+ *
+ * @see #createPropertyChangeListener()
+ */
+ public MetalScrollBarPropertyChangeHandler()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Handles a property change event. If the event name is
+ * <code>JSlider.isFreeStanding</code>, this method updates the
+ * delegate, otherwise the event is passed up to the super class.
+ *
+ * @param e the property change event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals(FREE_STANDING_PROP))
+ {
+ Boolean prop = (Boolean) e.getNewValue();
+ isFreeStanding = (prop == null ? true : prop.booleanValue());
+ if (increaseButton != null)
+ increaseButton.setFreeStanding(isFreeStanding);
+ if (decreaseButton != null)
+ decreaseButton.setFreeStanding(isFreeStanding);
+ }
+ else
+ super.propertyChange(e);
+ }
+ }
+
+ /** The name for the 'free standing' property. */
+ public static final String FREE_STANDING_PROP = "JScrollBar.isFreeStanding";
- /** The minimum thumb size */
- private static final Dimension MIN_THUMB_SIZE = new Dimension(18, 18);
-
- // FIXME: maybe replace by a Map of instances when this becomes stateful
- /** The shared UI instance for JScrollBars. */
- private static HashMap instances = null;
+ /** The minimum thumb size for a scroll bar that is not free standing. */
+ private static final Dimension MIN_THUMB_SIZE = new Dimension(15, 15);
+ /** The minimum thumb size for a scroll bar that is free standing. */
+ private static final Dimension MIN_THUMB_SIZE_FREE_STANDING
+ = new Dimension(17, 17);
+
+ /** The button that increases the value in the scroll bar. */
+ protected MetalScrollButton increaseButton;
+
+ /** The button that decreases the value in the scroll bar. */
+ protected MetalScrollButton decreaseButton;
+
+ /**
+ * The scroll bar width.
+ */
+ protected int scrollBarWidth;
+
+ /**
+ * A flag that indicates whether the scroll bar is "free standing", which
+ * means it has complete borders and can be used anywhere in the UI. A
+ * scroll bar which is not free standing has borders missing from one
+ * side, and relies on being part of another container with its own borders
+ * to look right visually. */
+ protected boolean isFreeStanding = true;
+
+ /**
+ * The color for the scroll bar shadow (this is read from the UIDefaults in
+ * the installDefaults() method).
+ */
+ Color scrollBarShadowColor;
+
/**
- * Constructs a new instance of MetalScrollBarUI.
+ * Constructs a new instance of <code>MetalScrollBarUI</code>, with no
+ * specific initialisation.
*/
public MetalScrollBarUI()
{
@@ -69,28 +145,192 @@ public class MetalScrollBarUI
}
/**
- * Returns an instance of MetalScrollBarUI.
+ * Returns a new instance of <code>MetalScrollBarUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalScrollBarUI
+ * @return An instance of MetalScrollBarUI
*/
public static ComponentUI createUI(JComponent component)
{
- if (instances == null)
- instances = new HashMap();
+ return new MetalScrollBarUI();
+ }
+
+ /**
+ * Installs the defaults.
+ */
+ protected void installDefaults()
+ {
+ // need to initialise isFreeStanding before calling the super class,
+ // so that the value is set when createIncreaseButton() and
+ // createDecreaseButton() are called (unless there is somewhere earlier
+ // that we can do this).
+ Boolean prop = (Boolean) scrollbar.getClientProperty(FREE_STANDING_PROP);
+ isFreeStanding = (prop == null ? true : prop.booleanValue());
+ scrollBarShadowColor = UIManager.getColor("ScrollBar.shadow");
+ super.installDefaults();
+ }
+
+ /**
+ * Creates a property change listener for the delegate to use. This
+ * overrides the method to provide a custom listener for the
+ * {@link MetalLookAndFeel} that can handle the
+ * <code>JScrollBar.isFreeStanding</code> property.
+ *
+ * @return A property change listener.
+ */
+ protected PropertyChangeListener createPropertyChangeListener()
+ {
+ return new MetalScrollBarPropertyChangeHandler();
+ }
+
+ /**
+ * Creates a new button to use as the control at the lower end of the
+ * {@link JScrollBar}.
+ *
+ * @param orientation the orientation of the button ({@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} or {@link #WEST}).
+ *
+ * @return The button.
+ */
+ protected JButton createDecreaseButton(int orientation)
+ {
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ scrollBarWidth = defaults.getInt("ScrollBar.width");
+ decreaseButton = new MetalScrollButton(orientation, scrollBarWidth,
+ isFreeStanding);
+ return decreaseButton;
+ }
- Object o = instances.get(component);
- MetalScrollBarUI instance;
- if (o == null)
+ /**
+ * Creates a new button to use as the control at the upper end of the
+ * {@link JScrollBar}.
+ *
+ * @param orientation the orientation of the button ({@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} or {@link #WEST}).
+ *
+ * @return The button.
+ */
+ protected JButton createIncreaseButton(int orientation)
+ {
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ scrollBarWidth = defaults.getInt("ScrollBar.width");
+ increaseButton = new MetalScrollButton(orientation, scrollBarWidth,
+ isFreeStanding);
+ return increaseButton;
+ }
+
+ /**
+ * Paints the track for the scrollbar.
+ *
+ * @param g the graphics device.
+ * @param c the component.
+ * @param trackBounds the track bounds.
+ */
+ protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds)
+ {
+ g.setColor(MetalLookAndFeel.getControl());
+ g.fillRect(trackBounds.x, trackBounds.y, trackBounds.width,
+ trackBounds.height);
+ if (scrollbar.getOrientation() == HORIZONTAL)
+ paintTrackHorizontal(g, c, trackBounds.x, trackBounds.y,
+ trackBounds.width, trackBounds.height);
+ else
+ paintTrackVertical(g, c, trackBounds.x, trackBounds.y,
+ trackBounds.width, trackBounds.height);
+
+ }
+
+ /**
+ * Paints the track for a horizontal scrollbar.
+ *
+ * @param g the graphics device.
+ * @param c the component.
+ * @param x the x-coordinate for the track bounds.
+ * @param y the y-coordinate for the track bounds.
+ * @param w the width for the track bounds.
+ * @param h the height for the track bounds.
+ */
+ private void paintTrackHorizontal(Graphics g, JComponent c,
+ int x, int y, int w, int h)
+ {
+ if (c.isEnabled())
{
- instance = new MetalScrollBarUI();
- instances.put(component, instance);
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+
+ g.setColor(scrollBarShadowColor);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 1);
+ g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
+
+ if (isFreeStanding)
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x, y + h - 2, x + w - 1, y + h - 2);
+ g.setColor(scrollBarShadowColor);
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+ }
}
else
- instance = (MetalScrollBarUI) o;
-
- return instance;
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ if (isFreeStanding)
+ g.drawRect(x, y, w - 1, h - 1);
+ else
+ {
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+ }
+ }
+ }
+
+ /**
+ * Paints the track for a vertical scrollbar.
+ *
+ * @param g the graphics device.
+ * @param c the component.
+ * @param x the x-coordinate for the track bounds.
+ * @param y the y-coordinate for the track bounds.
+ * @param w the width for the track bounds.
+ * @param h the height for the track bounds.
+ */
+ private void paintTrackVertical(Graphics g, JComponent c,
+ int x, int y, int w, int h)
+ {
+ if (c.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+
+ g.setColor(scrollBarShadowColor);
+ g.drawLine(x + 1, y + 1, x + w - 1, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
+
+ if (isFreeStanding)
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x + w - 2, y, x + w - 2, y + h - 1);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+ }
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ if (isFreeStanding)
+ g.drawRect(x, y, w - 1, h - 1);
+ else
+ {
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+ }
+ }
}
/**
@@ -102,45 +342,139 @@ public class MetalScrollBarUI
*/
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds)
{
- // first we fill the background
- g.setColor(thumbColor);
- g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width,
- thumbBounds.height);
+ // a disabled scrollbar has no thumb in the metal look and feel
+ if (!c.isEnabled())
+ return;
+ if (scrollbar.getOrientation() == HORIZONTAL)
+ paintThumbHorizontal(g, c, thumbBounds);
+ else
+ paintThumbVertical(g, c, thumbBounds);
- // draw the outer dark line
- g.setColor(thumbDarkShadowColor);
- g.drawRect(thumbBounds.x, thumbBounds.y, thumbBounds.width - 1,
- thumbBounds.height - 1);
+ // draw the pattern
+ MetalUtils.fillMetalPattern(c, g, thumbBounds.x + 3, thumbBounds.y + 3,
+ thumbBounds.width - 6, thumbBounds.height - 6,
+ thumbHighlightColor, thumbLightShadowColor);
+ }
- // draw the inner light line
+ /**
+ * Paints the thumb for a horizontal scroll bar.
+ *
+ * @param g the graphics device.
+ * @param c the scroll bar component.
+ * @param thumbBounds the thumb bounds.
+ */
+ private void paintThumbHorizontal(Graphics g, JComponent c,
+ Rectangle thumbBounds)
+ {
+ int x = thumbBounds.x;
+ int y = thumbBounds.y;
+ int w = thumbBounds.width;
+ int h = thumbBounds.height;
+
+ // first we fill the background
+ g.setColor(thumbColor);
+ if (isFreeStanding)
+ g.fillRect(x, y, w, h - 1);
+ else
+ g.fillRect(x, y, w, h);
+
+ // then draw the dark box
+ g.setColor(thumbLightShadowColor);
+ if (isFreeStanding)
+ g.drawRect(x, y, w - 1, h - 2);
+ else
+ {
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x + w - 1, y, x + w - 1, y + h -1);
+ }
+
+ // then the highlight
g.setColor(thumbHighlightColor);
- g.drawLine(thumbBounds.x + 1, thumbBounds.y + 1,
- thumbBounds.x + thumbBounds.width - 2,
- thumbBounds.y + 1);
- g.drawLine(thumbBounds.x + 1, thumbBounds.y + 1,
- thumbBounds.x + 1,
- thumbBounds.y + thumbBounds.height - 2);
-
+ if (isFreeStanding)
+ {
+ g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
+ }
+ else
+ {
+ g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 1);
+ }
+
// draw the shadow line
UIDefaults def = UIManager.getLookAndFeelDefaults();
g.setColor(def.getColor("ScrollBar.shadow"));
- g.drawLine(thumbBounds.x + 1, thumbBounds.y + thumbBounds.height,
- thumbBounds.x + thumbBounds.width,
- thumbBounds.y + thumbBounds.height);
+ g.drawLine(x + w, y + 1, x + w, y + h - 1);
- // draw the pattern
- MetalUtils.fillMetalPattern(g, thumbBounds.x + 3, thumbBounds.y + 3,
- thumbBounds.width - 6, thumbBounds.height - 6,
- thumbHighlightColor, thumbDarkShadowColor);
}
-
+
/**
- * This method returns the minimum thumb size.
+ * Paints the thumb for a vertical scroll bar.
+ *
+ * @param g the graphics device.
+ * @param c the scroll bar component.
+ * @param thumbBounds the thumb bounds.
+ */
+ private void paintThumbVertical(Graphics g, JComponent c,
+ Rectangle thumbBounds)
+ {
+ int x = thumbBounds.x;
+ int y = thumbBounds.y;
+ int w = thumbBounds.width;
+ int h = thumbBounds.height;
+
+ // first we fill the background
+ g.setColor(thumbColor);
+ if (isFreeStanding)
+ g.fillRect(x, y, w - 1, h);
+ else
+ g.fillRect(x, y, w, h);
+
+ // then draw the dark box
+ g.setColor(thumbLightShadowColor);
+ if (isFreeStanding)
+ g.drawRect(x, y, w - 2, h - 1);
+ else
+ {
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+ }
+
+ // then the highlight
+ g.setColor(thumbHighlightColor);
+ if (isFreeStanding)
+ {
+ g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
+ }
+ else
+ {
+ g.drawLine(x + 1, y + 1, x + w - 1, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
+ }
+
+ // draw the shadow line
+ UIDefaults def = UIManager.getLookAndFeelDefaults();
+ g.setColor(def.getColor("ScrollBar.shadow"));
+ g.drawLine(x + 1, y + h, x + w - 2, y + h);
+ }
+
+ /**
+ * Returns the minimum thumb size. For a free standing scroll bar the
+ * minimum size is <code>17 x 17</code> pixels, whereas for a non free
+ * standing scroll bar the minimum size is <code>15 x 15</code> pixels.
*
* @return The minimum thumb size.
*/
protected Dimension getMinimumThumbSize()
{
- return MIN_THUMB_SIZE;
+ if (isFreeStanding)
+ return MIN_THUMB_SIZE_FREE_STANDING;
+ else
+ return MIN_THUMB_SIZE;
}
+
}
+
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollButton.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollButton.java
new file mode 100644
index 00000000000..84f9cfe494e
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollButton.java
@@ -0,0 +1,483 @@
+/* MetalScrollButton.java
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.plaf.metal;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import javax.swing.SwingUtilities;
+import javax.swing.plaf.basic.BasicArrowButton;
+
+/**
+ * A button used by the {@link MetalScrollBarUI}. The button appearance
+ * varies according to the button direction, whether or not it is part of a
+ * "free standing" scroll bar, and the current state of the button.
+ */
+public class MetalScrollButton extends BasicArrowButton
+{
+
+ /**
+ * The maximum size for buttons.
+ * @see #getMaximumSize()
+ */
+ private static Dimension maximumSize;
+
+ /** The width of the button. */
+ private int buttonWidth;
+
+ /**
+ * A flag that indicates whether the button is part of a free standing
+ * scroll bar. This affects how the border is drawn.
+ */
+ private boolean freeStanding;
+
+ /**
+ * Creates a new button.
+ *
+ * @param direction the direction (this should be one of {@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} and {@link #WEST}, but
+ * this is not enforced).
+ * @param width the button width.
+ * @param freeStanding a flag indicating whether the scroll button is free
+ * standing or not.
+ */
+ public MetalScrollButton(int direction, int width, boolean freeStanding)
+ {
+ super(direction);
+ buttonWidth = width;
+ this.freeStanding = freeStanding;
+ }
+
+ /**
+ * Returns the button width.
+ *
+ * @return The button width.
+ */
+ public int getButtonWidth()
+ {
+ return buttonWidth;
+ }
+
+ /**
+ * Sets the free standing flag. This controls how the button border is
+ * drawn.
+ *
+ * @param freeStanding the new value of the flag.
+ */
+ public void setFreeStanding(boolean freeStanding)
+ {
+ this.freeStanding = freeStanding;
+ }
+
+ /**
+ * Paints the button.
+ *
+ * @param g the graphics device.
+ */
+ public void paint(Graphics g)
+ {
+ Rectangle bounds = SwingUtilities.getLocalBounds(this);
+
+ // fill the background
+ if (getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControl());
+ g.fillRect(0, 0, bounds.width, bounds.height);
+
+ paintArrow(g, bounds.width, bounds.height);
+
+ // paint a border manually - I tried using a real (custom) Border
+ // but couldn't get it to stay set for the button, something was
+ // overwriting it...
+ if (freeStanding)
+ {
+ if (direction == WEST)
+ paintWestBorderFreeStanding(g, bounds.width, bounds.height);
+ else if (direction == EAST)
+ paintEastBorderFreeStanding(g, bounds.width, bounds.height);
+ else if (direction == SOUTH)
+ paintSouthBorderFreeStanding(g, bounds.width, bounds.height);
+ else // asume NORTH
+ paintNorthBorderFreeStanding(g, bounds.width, bounds.height);
+ }
+ else
+ {
+ if (direction == WEST)
+ paintWestBorder(g, bounds.width, bounds.height);
+ else if (direction == EAST)
+ paintEastBorder(g, bounds.width, bounds.height);
+ else if (direction == SOUTH)
+ paintSouthBorder(g, bounds.width, bounds.height);
+ else // asume NORTH
+ paintNorthBorder(g, bounds.width, bounds.height);
+ }
+ }
+
+ private void paintArrow(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+
+ if (direction == SOUTH)
+ {
+ int x = w / 2;
+ int y = h / 2 + 2;
+ for (int i = 1; i < 5; i++)
+ g.drawLine(x - i, y - i, x + i - 1, y - i);
+ }
+ else if (direction == EAST)
+ {
+ int x = w / 2 + 2;
+ int y = h / 2;
+ for (int i = 1; i < 5; i++)
+ g.drawLine(x - i, y - i, x - i, y + i - 1);
+ }
+ else if (direction == WEST)
+ {
+ int x = w / 2 - 3;
+ int y = h / 2;
+ for (int i = 1; i < 5; i++)
+ g.drawLine(x + i, y - i, x + i, y + i - 1);
+ }
+ else // assume NORTH
+ {
+ int x = w / 2;
+ int y = h / 2 - 3;
+ for (int i = 1; i < 5; i++)
+ g.drawLine(x - i, y + i, x + i - 1, y + i);
+ }
+ }
+ /**
+ * Paints the border for a button with a {@link #NORTH} direction that
+ * belongs to a free standing scroll bar.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintNorthBorderFreeStanding(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 2, 0);
+ g.drawLine(0, 0, 0, h - 1);
+ g.drawLine(2, h - 1, w - 2, h - 1);
+ g.drawLine(w - 2, 2, w - 2, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(1, 1, 1, h - 2);
+ g.drawLine(1, 1, w - 3, 1);
+ g.drawLine(w - 1, 1, w - 1, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(1, h - 1, 1, h - 1);
+ g.drawLine(w - 2, 1, w - 2, 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(w - 1, 0, w - 1, h - 1);
+ g.drawLine(0, 0, 0, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with a {@link #SOUTH} direction that
+ * belongs to a free standing scroll bar.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintSouthBorderFreeStanding(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 2, 0);
+ g.drawLine(0, 0, 0, h - 1);
+ g.drawLine(2, h - 1, w - 2, h - 1);
+ g.drawLine(w - 2, 2, w - 2, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(1, 1, 1, h - 1);
+ g.drawLine(1, 1, w - 1, 1);
+ g.drawLine(w - 1, 1, w - 1, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(1, h - 1, 1, h - 1);
+ g.drawLine(w - 1, 1, w - 1, 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, h - 1, w - 1, h - 1);
+ g.drawLine(w - 1, 0, w - 1, h - 1);
+ g.drawLine(0, 0, 0, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with an {@link #EAST} direction that
+ * belongs to a free standing scroll bar.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintEastBorderFreeStanding(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 2, 0);
+ g.drawLine(w - 2, 0, w - 2, h - 2);
+ g.drawLine(0, h - 2, w - 2, h - 2);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(0, 1, w - 1, 1);
+ g.drawLine(w - 1, 1, w - 1, h - 1);
+ g.drawLine(0, h - 1, w - 1, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(w - 2, 1, w - 2, 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(w - 1, 0, w - 1, h - 1);
+ g.drawLine(0, h - 1, w - 1, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with a {@link #WEST} direction that
+ * belongs to a free standing scroll bar.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintWestBorderFreeStanding(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(0, 0, 0, h - 2);
+ g.drawLine(0, h - 2, w - 1, h - 2);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(1, 1, w - 1, 1);
+ g.drawLine(1, 1, 1, h - 1);
+ g.drawLine(1, h - 1, w - 1, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(1, h - 2, 1, h - 2);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(0, 0, 0, h - 1);
+ g.drawLine(0, h - 1, w - 1, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with a {@link #NORTH} direction that
+ * belongs to a scroll bar that is not free standing.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintNorthBorder(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, 0, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(1, 0, 1, h - 1);
+ g.drawLine(1, 0, w - 1, 0);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, 0, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with a {@link #SOUTH} direction that
+ * belongs to a scroll bar that is not free standing.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintSouthBorder(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, 0, h - 1);
+ g.drawLine(0, h - 1, w - 1, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(1, 0, 1, h - 1);
+ g.drawLine(1, 0, w - 1, 0);
+
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(1, h - 1, 1, h - 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, 0, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with an {@link #EAST} direction that
+ * belongs to a scroll bar that is not free standing.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintEastBorder(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(w - 1, 2, w - 1, h - 1);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(0, 1, w - 2, 1);
+ g.drawLine(0, 1, 0, h - 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, w - 1, 0);
+ }
+ }
+
+ /**
+ * Paints the border for a button with a {@link #WEST} direction that
+ * belongs to a scroll bar that is not free standing.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintWestBorder(Graphics g, int w, int h)
+ {
+ Rectangle bounds = SwingUtilities.getLocalBounds(this);
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, bounds.width - 1, 0);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(0, 1, bounds.width - 1, 1);
+ g.drawLine(0, 1, 0, bounds.height - 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, bounds.width - 1, 0);
+ }
+ }
+
+ /**
+ * Returns the preferred size for the button, which varies depending on
+ * the direction of the button and whether or not it is free standing.
+ *
+ * @return The preferred size.
+ */
+ public Dimension getPreferredSize()
+ {
+ int adj = 1;
+ if (!freeStanding)
+ adj = 2;
+
+ if (direction == EAST)
+ return new Dimension(buttonWidth - adj, buttonWidth);
+ else if (direction == WEST)
+ return new Dimension(buttonWidth - 2, buttonWidth);
+ else if (direction == SOUTH)
+ return new Dimension(buttonWidth, buttonWidth - adj);
+ else // assume NORTH
+ return new Dimension(buttonWidth, buttonWidth - 2);
+ }
+
+ /**
+ * Returns the minimum size for the button.
+ *
+ * @return The minimum size for the button.
+ */
+ public Dimension getMinimumSize()
+ {
+ return getPreferredSize();
+ }
+
+ /**
+ * Returns the maximum size for the button.
+ *
+ * @return <code>Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)</code>.
+ */
+ public Dimension getMaximumSize()
+ {
+ if (maximumSize == null)
+ maximumSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ return maximumSize;
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java
index 3e1198b398d..d5bf175f92d 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java
@@ -39,19 +39,18 @@ exception statement from your version. */
package javax.swing.plaf.metal;
import javax.swing.JComponent;
+import javax.swing.JScrollPane;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicScrollPaneUI;
+/**
+ * A UI delegate for the {@link JScrollPane} component.
+ */
public class MetalScrollPaneUI
extends BasicScrollPaneUI
{
-
- // FIXME: maybe replace by a Map of instances when this becomes stateful
- /** The shared UI instance for JScrollPanes. */
- private static MetalScrollPaneUI instance = null;
-
/**
- * Constructs a new instance of MetalScrollPaneUI.
+ * Constructs a new instance of <code>MetalScrollPaneUI</code>.
*/
public MetalScrollPaneUI()
{
@@ -59,16 +58,14 @@ public class MetalScrollPaneUI
}
/**
- * Returns an instance of MetalScrollPaneUI.
+ * Returns a shared instance of <code>MetalScrollPaneUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalScrollPaneUI
+ * @return A shared instance of <code>MetalScrollPaneUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
- if (instance == null)
- instance = new MetalScrollPaneUI();
- return instance;
+ return new MetalScrollPaneUI();
}
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java
index 6e78ccb7071..1d48e9be2b0 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java
@@ -38,10 +38,20 @@ exception statement from your version. */
package javax.swing.plaf.metal;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
import javax.swing.JComponent;
+import javax.swing.JSeparator;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSeparatorUI;
+/**
+ * A UI delegate for the {@link JSeparator} component.
+ */
public class MetalSeparatorUI
extends BasicSeparatorUI
{
@@ -51,7 +61,7 @@ public class MetalSeparatorUI
private static MetalSeparatorUI instance = null;
/**
- * Constructs a new instance of MetalSeparatorUI.
+ * Constructs a new instance of <code>MetalSeparatorUI</code>.
*/
public MetalSeparatorUI()
{
@@ -59,11 +69,11 @@ public class MetalSeparatorUI
}
/**
- * Returns an instance of MetalSeparatorUI.
+ * Returns a shared instance of <code>MetalSeparatorUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalSeparatorUI
+ * @return A shared instance of <code>MetalSeparatorUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
@@ -71,4 +81,51 @@ public class MetalSeparatorUI
instance = new MetalSeparatorUI();
return instance;
}
+
+ /**
+ * The separator is made of two lines. The top line will be
+ * the Metal theme color separatorForeground (or left line if it's vertical).
+ * The bottom or right line will be the Metal theme color
+ * separatorBackground.
+ * The two lines will
+ * be centered inside the bounds box. If the separator is horizontal,
+ * then it will be vertically centered, or if it's vertical, it will
+ * be horizontally centered.
+ *
+ * @param g The Graphics object to paint with
+ * @param c The JComponent to paint.
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ Rectangle r = new Rectangle();
+ SwingUtilities.calculateInnerArea(c, r);
+ Color saved = g.getColor();
+ Color c1 = UIManager.getColor("Separator.foreground");
+ Color c2 = UIManager.getColor("Separator.background");
+ JSeparator s;
+ if (c instanceof JSeparator)
+ s = (JSeparator) c;
+ else
+ return;
+
+ if (s.getOrientation() == JSeparator.HORIZONTAL)
+ {
+ int midAB = r.height / 2;
+ g.setColor(c1);
+ g.drawLine(r.x, r.y + midAB - 1, r.x + r.width, r.y + midAB - 1);
+
+ g.setColor(c2);
+ g.fillRect(r.x, r.y + midAB, r.x + r.width, r.y + midAB);
+ }
+ else
+ {
+ int midAD = r.height / 2 + r.y;
+ g.setColor(c1);
+ g.drawLine(r.x, r.y, r.x, r.y + r.height);
+
+ g.setColor(c2);
+ g.fillRect(r.x + midAD, r.y + r.height, r.x + midAD, r.y + r.height);
+ }
+ g.setColor(saved);
+ }
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java
index 4b52c4b0041..08fb99d216c 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java
@@ -42,8 +42,8 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
+import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
-import java.util.HashMap;
import javax.swing.Icon;
import javax.swing.JComponent;
@@ -56,16 +56,59 @@ import javax.swing.plaf.basic.BasicSliderUI;
/**
* A UI delegate for the {@link JSlider} component.
*/
-public class MetalSliderUI
- extends BasicSliderUI
+public class MetalSliderUI extends BasicSliderUI
{
- // TODO: find a use for this
+ /**
+ * A property change handler that updates the rendered component in response
+ * to specific property change events. This custom handler is used to
+ * intercept the "JSlider.isFilled" property, which is only recognised by
+ * the {@link MetalLookAndFeel}.
+ */
+ protected class MetalPropertyListener
+ extends BasicSliderUI.PropertyChangeHandler
+ {
+ /**
+ * Creates a new listener.
+ */
+ protected MetalPropertyListener()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Handles property change events. Events with the name "JSlider.isFilled"
+ * are handled here, and other events are passed to the superclass.
+ *
+ * @param e the property change event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals(SLIDER_FILL))
+ {
+ Boolean b = (Boolean) e.getNewValue();
+ if (b == null)
+ filledSlider = false;
+ else
+ filledSlider = b.booleanValue();
+ }
+ else
+ super.propertyChange(e);
+ }
+ }
+
+ /** The thumb color (unused, because an icon is used to draw the thumb). */
protected static Color thumbColor;
- // TODO: find a use for this
+ /**
+ * The highlight color used for drawing the track rect when the slider is
+ * enabled.
+ */
protected static Color highlightColor;
- // TODO: find a use for this
+ /**
+ * The shadow color used for drawing the track rect when the slider is
+ * enabled.
+ */
protected static Color darkShadowColor;
/** The track width. */
@@ -85,17 +128,14 @@ public class MetalSliderUI
/** The gap between the track and the tick marks. */
protected final int TICK_BUFFER = 4;
+ /** A key to look up the filledSlider setting in the {@link UIManager}. */
+ protected final String SLIDER_FILL = "JSlider.isFilled";
+
/**
* A flag that controls whether or not the track is filled up to the value
* of the slider.
*/
protected boolean filledSlider;
-
- /** A key to look up the filledSlider setting in the {@link UIManager}. */
- protected final String SLIDER_FILL = "JSlider.isFilled";
-
- /** The UI instances for MetalSliderUIs */
- private static HashMap instances;
/**
* Constructs a new instance.
@@ -104,33 +144,27 @@ public class MetalSliderUI
{
super(null);
filledSlider = UIManager.getBoolean(SLIDER_FILL);
+ darkShadowColor = MetalLookAndFeel.getControlDarkShadow();
+ highlightColor = MetalLookAndFeel.getControlHighlight();
}
/**
- * Returns an instance of MetalSliderUI.
+ * Returns a new instance of <code>MetalSliderUI</code>.
*
- * @param component the component for which we return an UI instance
+ * @param component the component (ignored).
*
- * @return an instance of MetalSliderUI
+ * @return A new instance of <code>MetalSliderUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
- if (instances == null)
- instances = new HashMap();
-
- Object o = instances.get(component);
- MetalSliderUI instance;
- if (o == null)
- {
- instance = new MetalSliderUI();
- instances.put(component, instance);
- }
- else
- instance = (MetalSliderUI) o;
-
- return instance;
+ return new MetalSliderUI();
}
+ /**
+ * Installs the default for this UI delegate in the supplied component.
+ *
+ * @param c the component.
+ */
public void installUI(JComponent c)
{
super.installUI(c);
@@ -140,6 +174,18 @@ public class MetalSliderUI
}
/**
+ * Creates a property change listener for the slider.
+ *
+ * @param slider the slider.
+ *
+ * @return A new instance of {@link MetalPropertyListener}.
+ */
+ protected PropertyChangeListener createPropertyChangeListener(JSlider slider)
+ {
+ return new MetalPropertyListener();
+ }
+
+ /**
* Paints the thumb icon for the slider.
*
* @param g the graphics device.
@@ -153,46 +199,79 @@ public class MetalSliderUI
}
/**
- * Creates a property change listener for the slider.
- *
- * @param slider the slider.
- */
- protected PropertyChangeListener createPropertyChangeListener(JSlider slider)
- {
- // TODO: try to figure out why it might be necessary to override this
- // method as is done in Sun's implementation
- return super.createPropertyChangeListener(slider);
- }
-
- /**
* Paints the track along which the thumb control moves.
*
* @param g the graphics device.
*/
public void paintTrack(Graphics g)
{
+ Color shadowColor = MetalLookAndFeel.getControlShadow();
if (slider.getOrientation() == JSlider.HORIZONTAL)
- {
- if (filledSlider)
{
- // TODO: fill the track
+ int trackX = trackRect.x;
+ int trackY = trackRect.y + (trackRect.height - getTrackWidth()) / 2;
+ int trackW = trackRect.width - 1;
+ int trackH = getTrackWidth();
+
+ // draw border
+ if (slider.isEnabled())
+ BasicGraphicsUtils.drawEtchedRect(g, trackX, trackY, trackW, trackH,
+ darkShadowColor, shadowColor, darkShadowColor, highlightColor);
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawRect(trackX, trackY, trackW - 2, trackH - 2);
+ }
+
+ // fill track (if required)
+ if (filledSlider)
+ {
+ int xPos = xPositionForValue(slider.getValue());
+ int x = (slider.getInverted() ? xPos : trackRect.x);
+ int w = (slider.getInverted() ? trackX + trackW - xPos
+ : xPos - trackRect.x);
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.fillRect(x + 1, trackY + 1, w - 3, getTrackWidth() - 3);
+ if (slider.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(x + 1, trackY + 1, x + w - 3, trackY + 1);
+ g.drawLine(x + 1, trackY + 1, x + 1,
+ trackY + getTrackWidth() - 3);
+ }
+ }
}
- BasicGraphicsUtils.drawEtchedRect(g, trackRect.x, trackRect.y
- + (trackRect.height - getTrackWidth()) / 2, trackRect.width - 1,
- getTrackWidth(), Color.darkGray, Color.gray, Color.darkGray,
- Color.white);
- }
else
- {
- if (filledSlider)
{
- // TODO: fill the track
+ int trackX = trackRect.x + (trackRect.width - getTrackWidth()) / 2;
+ int trackY = trackRect.y;
+ int trackW = getTrackWidth();
+ int trackH = trackRect.height - 1;
+ if (slider.isEnabled())
+ BasicGraphicsUtils.drawEtchedRect(g, trackX, trackY, trackW, trackH,
+ darkShadowColor, shadowColor, darkShadowColor, highlightColor);
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawRect(trackX, trackY, trackW - 2, trackH - 2);
+ }
+
+ if (filledSlider)
+ {
+ int yPos = yPositionForValue(slider.getValue());
+ int y = (slider.getInverted() ? trackY : yPos);
+ int h = (slider.getInverted() ? yPos - trackY
+ : trackY + trackH - yPos);
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.fillRect(trackX + 1, y + 1, getTrackWidth() - 3, h - 3);
+ if (slider.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(trackX + 1, y + 1, trackX + trackW - 3, y + 1);
+ g.drawLine(trackX + 1, y + 1, trackX + 1, y + h - 3);
+ }
+ }
}
- BasicGraphicsUtils.drawEtchedRect(g, trackRect.x + (trackRect.width
- - getTrackWidth()) / 2, trackRect.y, getTrackWidth(),
- trackRect.height - 1, Color.darkGray, Color.gray, Color.darkGray,
- Color.white);
- }
}
/**
@@ -262,12 +341,13 @@ public class MetalSliderUI
*/
protected int getThumbOverhang()
{
- // TODO: figure out what this is used for
+ // FIXME: for what might this method be used?
return 0;
}
protected void scrollDueToClickInTrack(int dir)
{
+ // FIXME: for what might this method be overridden?
super.scrollDueToClickInTrack(dir);
}
@@ -283,8 +363,10 @@ public class MetalSliderUI
{
// Note the incoming 'g' has a translation in place to get us to the
// start of the tick rect already...
- // TODO: get color from UIManager...
- g.setColor(new Color(153, 153, 204));
+ if (slider.isEnabled())
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + tickLength / 2);
}
@@ -300,8 +382,10 @@ public class MetalSliderUI
{
// Note the incoming 'g' has a translation in place to get us to the
// start of the tick rect already...
- // TODO: get color from UIManager...
- g.setColor(new Color(153, 153, 204));
+ if (slider.isEnabled())
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + tickLength);
}
@@ -317,8 +401,10 @@ public class MetalSliderUI
{
// Note the incoming 'g' has a translation in place to get us to the
// start of the tick rect already...
- // TODO: get color from UIManager...
- g.setColor(new Color(153, 153, 204));
+ if (slider.isEnabled())
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
g.drawLine(TICK_BUFFER - 1, y, TICK_BUFFER - 1 + tickLength / 2, y);
}
@@ -334,8 +420,10 @@ public class MetalSliderUI
{
// Note the incoming 'g' has a translation in place to get us to the
// start of the tick rect already...
- // TODO: get color from UIManager...
- g.setColor(new Color(153, 153, 204));
+ if (slider.isEnabled())
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
g.drawLine(TICK_BUFFER - 1, y, TICK_BUFFER - 1 + tickLength, y);
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java
index 60e9c055952..016e09557d6 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java
@@ -78,7 +78,7 @@ class MetalSplitPaneDivider extends BasicSplitPaneDivider
{
//super.paint(g);
Dimension s = getSize();
- MetalUtils.fillMetalPattern(g, 2, 2, s.width - 4, s.height - 4,
+ MetalUtils.fillMetalPattern(splitPane, g, 2, 2, s.width - 4, s.height - 4,
light, dark);
}
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java
index b7ea8984b43..b39fb23366e 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java
@@ -39,24 +39,22 @@ exception statement from your version. */
package javax.swing.plaf.metal;
import java.awt.Color;
-import java.util.HashMap;
import javax.swing.JComponent;
+import javax.swing.JSplitPane;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
-import javax.swing.plaf.basic.BasicSplitPaneUI;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
+import javax.swing.plaf.basic.BasicSplitPaneUI;
-public class MetalSplitPaneUI
- extends BasicSplitPaneUI
+/**
+ * A UI delegate for the {@link JSplitPane} component.
+ */
+public class MetalSplitPaneUI extends BasicSplitPaneUI
{
-
- /** The UI instances for MetalSplitPaneUIs */
- private static HashMap instances;
-
/**
- * Constructs a new instance of MetalSplitPaneUI.
+ * Constructs a new instance of <code>MetalSplitPaneUI</code>.
*/
public MetalSplitPaneUI()
{
@@ -64,28 +62,15 @@ public class MetalSplitPaneUI
}
/**
- * Returns an instance of MetalSplitPaneUI.
+ * Returns a new instance of <code>MetalSplitPaneUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalSplitPaneUI
+ * @return A new instance of <code>MetalSplitPaneUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
- if (instances == null)
- instances = new HashMap();
-
- Object o = instances.get(component);
- MetalSplitPaneUI instance;
- if (o == null)
- {
- instance = new MetalSplitPaneUI();
- instances.put(component, instance);
- }
- else
- instance = (MetalSplitPaneUI) o;
-
- return instance;
+ return new MetalSplitPaneUI();
}
/**
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java
index 1b5fe144f6c..b1e02c7a6b0 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java
@@ -40,7 +40,6 @@ package javax.swing.plaf.metal;
import java.awt.Graphics;
import java.awt.LayoutManager;
-import java.util.HashMap;
import javax.swing.JComponent;
import javax.swing.JTabbedPane;
@@ -48,11 +47,9 @@ import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
/**
- * A UI delegate used for the {@link JTabbedPane} component in the
- * {@link MetalLookAndFeel}.
+ * A UI delegate for the {@link JTabbedPane} component.
*/
-public class MetalTabbedPaneUI
- extends BasicTabbedPaneUI
+public class MetalTabbedPaneUI extends BasicTabbedPaneUI
{
/**
@@ -65,13 +62,14 @@ public class MetalTabbedPaneUI
* public for compatibility.
*/
public class TabbedPaneLayout
- extends BasicTabbedPaneUI.TabbedPaneLayout
+ extends BasicTabbedPaneUI.TabbedPaneLayout
{
/**
* Creates a new instance of the layout manager.
*/
public TabbedPaneLayout()
{
+ // Nothing to do here.
}
/**
@@ -102,9 +100,6 @@ public class MetalTabbedPaneUI
}
}
- /** The shared UI instance for JTabbedPanes. */
- private static HashMap instances = null;
-
/**
* Constructs a new instance of MetalTabbedPaneUI.
*/
@@ -122,20 +117,7 @@ public class MetalTabbedPaneUI
*/
public static ComponentUI createUI(JComponent component)
{
- if (instances == null)
- instances = new HashMap();
-
- Object o = instances.get(component);
- MetalTabbedPaneUI instance;
- if (o == null)
- {
- instance = new MetalTabbedPaneUI();
- instances.put(component, instance);
- }
- else
- instance = (MetalTabbedPaneUI) o;
-
- return instance;
+ return new MetalTabbedPaneUI();
}
/**
@@ -145,7 +127,7 @@ public class MetalTabbedPaneUI
*/
protected LayoutManager createLayoutManager()
{
- return new TabbedPaneLayout();
+ return super.createLayoutManager();
}
/**
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java
index d6e50e12239..6984daeccbe 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java
@@ -38,19 +38,16 @@ exception statement from your version. */
package javax.swing.plaf.metal;
-import java.util.HashMap;
-
import javax.swing.JComponent;
+import javax.swing.JTextField;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTextFieldUI;
-public class MetalTextFieldUI
- extends BasicTextFieldUI
+/**
+ * A UI delegate for the {@link JTextField} component.
+ */
+public class MetalTextFieldUI extends BasicTextFieldUI
{
-
- /** The UI instances for MetalTextFieldUIs */
- private static HashMap instances = null;
-
/**
* Constructs a new instance of MetalTextFieldUI.
*/
@@ -60,27 +57,14 @@ public class MetalTextFieldUI
}
/**
- * Returns an instance of MetalTextFieldUI.
+ * Returns a new instance of <code>MetalTextFieldUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalTextFieldUI
+ * @return A new instance of <code>MetalTextFieldUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
- if (instances == null)
- instances = new HashMap();
-
- Object o = instances.get(component);
- MetalTextFieldUI instance;
- if (o == null)
- {
- instance = new MetalTextFieldUI();
- instances.put(component, instance);
- }
- else
- instance = (MetalTextFieldUI) o;
-
- return instance;
+ return new MetalTextFieldUI();
}
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java
index be6d0c39ec8..46a19bdbe9e 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java
@@ -39,13 +39,24 @@ exception statement from your version. */
package javax.swing.plaf.metal;
import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import javax.swing.AbstractButton;
import javax.swing.JComponent;
+import javax.swing.JToggleButton;
+import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.plaf.basic.BasicToggleButtonUI;
+/**
+ * A UI delegate for the {@link JToggleButton} component.
+ */
public class MetalToggleButtonUI
extends BasicToggleButtonUI
{
@@ -59,21 +70,26 @@ public class MetalToggleButtonUI
/** The color for disabled button labels. */
protected Color disabledTextColor;
- /** The shared UI instance for MetalToggleButtonUIs */
- private static MetalToggleButtonUI instance = null;
+ /**
+ * Returns a new instance of <code>MetalToggleButtonUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A new instance of <code>MetalToggleButtonUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalToggleButtonUI();
+ }
/**
- * Constructs a new instance of MetalToggleButtonUI.
+ * Constructs a new instance of <code>MetalToggleButtonUI</code>.
*/
public MetalToggleButtonUI()
{
super();
- focusColor = getFocusColor();
- selectColor = getSelectColor();
- disabledTextColor = getDisabledTextColor();
}
-
/**
* Returns the color for the focus border.
*
@@ -81,8 +97,7 @@ public class MetalToggleButtonUI
*/
protected Color getFocusColor()
{
- UIDefaults def = UIManager.getLookAndFeelDefaults();
- return def.getColor(getPropertyPrefix() + ".focus");
+ return focusColor;
}
/**
@@ -92,32 +107,98 @@ public class MetalToggleButtonUI
*/
protected Color getSelectColor()
{
- UIDefaults def = UIManager.getLookAndFeelDefaults();
- return def.getColor(getPropertyPrefix() + ".select");
+ return selectColor;
}
/**
- * Returns the color for the text label of disabled buttons.
+ * Returns the color for the text label of disabled buttons. The value
+ * is initialised in the {@link #installDefaults(AbstractButton)} method
+ * by reading the <code>ToggleButton.disabledText</code> item from the UI
+ * defaults.
*
- * @return the color for the text label of disabled buttons
+ * @return The color for the text label of disabled buttons.
*/
protected Color getDisabledTextColor()
{
- UIDefaults def = UIManager.getLookAndFeelDefaults();
- return def.getColor(getPropertyPrefix() + ".disabledText");
+ return disabledTextColor;
}
/**
- * Returns an instance of MetalToggleButtonUI.
- *
- * @param component the component for which we return an UI instance
- *
- * @return an instance of MetalToggleButtonUI
+ * Updates the button with the defaults for this look and feel.
+ *
+ * @param b the button.
*/
- public static ComponentUI createUI(JComponent component)
+ public void installDefaults(AbstractButton b)
+ {
+ super.installDefaults(b);
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ focusColor = defaults.getColor(getPropertyPrefix() + "focus");
+ selectColor = defaults.getColor(getPropertyPrefix() + "select");
+ disabledTextColor = defaults.getColor(getPropertyPrefix() + "disabledText");
+ }
+
+ /**
+ * Paints the button background when it is pressed/selected.
+ *
+ * @param g the graphics device.
+ * @param b the button.
+ */
+ protected void paintButtonPressed(Graphics g, AbstractButton b)
+ {
+ if (b.isContentAreaFilled() && b.isOpaque())
+ {
+ Color saved = g.getColor();
+ Rectangle bounds = SwingUtilities.getLocalBounds(b);
+ g.setColor(selectColor);
+ g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
+ g.setColor(saved);
+ }
+ }
+
+ /**
+ * Paints the text for the button.
+ *
+ * @param g the graphics device.
+ * @param c the component.
+ * @param textRect the bounds for the text.
+ * @param text the text.
+ *
+ * @deprecated 1.4 Use {@link BasicButtonUI#paintText(java.awt.Graphics,
+ * javax.swing.AbstractButton, java.awt.Rectangle, java.lang.String)}.
+ */
+ protected void paintText(Graphics g, JComponent c, Rectangle textRect,
+ String text)
+ {
+ Font savedFont = g.getFont();
+ Color savedColor = g.getColor();
+ g.setFont(c.getFont());
+ if (c.isEnabled())
+ g.setColor(c.getForeground());
+ else
+ g.setColor(disabledTextColor);
+ FontMetrics fm = g.getFontMetrics(c.getFont());
+ int ascent = fm.getAscent();
+ g.drawString(text, textRect.x, textRect.y + ascent);
+ g.setFont(savedFont);
+ g.setColor(savedColor);
+ }
+
+ /**
+ * Draws the focus highlight around the text and icon.
+ *
+ * @param g the graphics device.
+ * @param b the button.
+ */
+ protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect,
+ Rectangle textRect, Rectangle iconRect)
{
- if (instance == null)
- instance = new MetalToggleButtonUI();
- return instance;
+ if (!b.hasFocus())
+ return;
+ Color saved = g.getColor();
+ g.setColor(focusColor);
+ Rectangle fr = iconRect.union(textRect);
+ g.drawRect(fr.x - 1, fr.y - 1, fr.width + 1, fr.height + 1);
+ g.setColor(saved);
}
+
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java
index 39af0011ae6..c5ca91399ab 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java
@@ -38,20 +38,73 @@ exception statement from your version. */
package javax.swing.plaf.metal;
+import java.awt.event.ContainerListener;
+import java.beans.PropertyChangeListener;
+
import javax.swing.JComponent;
+import javax.swing.JToolBar;
+import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicToolBarUI;
-public class MetalToolBarUI
- extends BasicToolBarUI
+/**
+ * A UI delegate for the {@link JToolBar} component.
+ */
+public class MetalToolBarUI extends BasicToolBarUI
{
+
+ /**
+ * A listener (no longer used) that responds when components are added to or
+ * removed from the {@link JToolBar}. The required behaviour is now
+ * handled in the super class.
+ *
+ * @see MetalToolBarUI#createContainerListener()
+ */
+ protected class MetalContainerListener
+ extends BasicToolBarUI.ToolBarContListener
+ {
+ /**
+ * Creates a new instance.
+ */
+ protected MetalContainerListener()
+ {
+ // Nothing to do here.
+ }
+ }
- // FIXME: maybe replace by a Map of instances when this becomes stateful
- /** The shared UI instance for MetalToolBarUIs */
- private static MetalToolBarUI instance = null;
+ /**
+ * A listener (no longer used) that responds to property change events in a
+ * {@link JToolBar} component. The required behaviour is now handled in the
+ * super class.
+ *
+ * @see MetalToolBarUI#createRolloverListener()
+ */
+ protected class MetalRolloverListener
+ extends BasicToolBarUI.PropertyListener
+ {
+ /**
+ * Creates a new instance.
+ */
+ protected MetalRolloverListener()
+ {
+ // Nothing to do here.
+ }
+ }
+
+ /**
+ * The container listener (an implementation specific field, according to the
+ * spec, and not used in GNU Classpath).
+ */
+ protected ContainerListener contListener;
+
+ /**
+ * The rollover listener (an implementation specific field, according to the
+ * spec, and not used in GNU Classpath).
+ */
+ protected PropertyChangeListener rolloverListener;
/**
- * Constructs a new instance of MetalToolBarUI.
+ * Creates a new instance of this UI delegate.
*/
public MetalToolBarUI()
{
@@ -59,16 +112,51 @@ public class MetalToolBarUI
}
/**
- * Returns an instance of MetalToolBarUI.
+ * Returns a new instance of <code>MetalToolBarUI</code>.
*
- * @param component the component for which we return an UI instance
+ * @param component the component for which we return an UI instance
*
- * @return an instance of MetalToolBarUI
+ * @return A new instance of <code>MetalToolBarUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
- if (instance == null)
- instance = new MetalToolBarUI();
- return instance;
+ return new MetalToolBarUI();
+ }
+
+ /**
+ * Returns <code>null</code> as permitted by recent versions of the API
+ * specification. Originally it seems this method returned a new instance of
+ * {@link MetalRolloverListener}, but this is now redundant.
+ *
+ * @return <code>null</code>.
+ */
+ protected PropertyChangeListener createRolloverListener()
+ {
+ return null;
+ }
+
+ /**
+ * Returns <code>null</code> as permitted by recent versions of the API
+ * specification. Originally it seems this method returned a new instance of
+ * {@link MetalContainerListener}, but this is now redundant.
+ *
+ * @return <code>null</code>.
+ */
+ protected ContainerListener createContainerListener()
+ {
+ return null;
+ }
+
+ /**
+ * Returns a border with no rollover effect for buttons in the tool bar.
+ *
+ * @return A border.
+ *
+ * @see MetalBorders#getToolbarButtonBorder()
+ */
+ protected Border createNonRolloverBorder()
+ {
+ return MetalBorders.getToolbarButtonBorder();
}
+
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java
index c88b6534ab7..5085d170ac2 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java
@@ -38,32 +38,92 @@ exception statement from your version. */
package javax.swing.plaf.metal;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+import javax.swing.AbstractButton;
import javax.swing.JComponent;
+import javax.swing.JMenuItem;
+import javax.swing.JToolTip;
+import javax.swing.KeyStroke;
+import javax.swing.SwingConstants;
+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.UIResource;
import javax.swing.plaf.basic.BasicToolTipUI;
+/**
+ * A UI delegate for the {@link JToolTip} component.
+ */
public class MetalToolTipUI
extends BasicToolTipUI
{
+ /**
+ * The amount of space between the tool tip text and the accelerator
+ * description (if visible).
+ */
+ public static final int padSpaceBetweenStrings = 12;
- // FIXME: maybe replace by a Map of instances when this becomes stateful
- /** The shared UI instance for MetalToolTipUIs */
+ /** The shared UI instance. */
private static MetalToolTipUI instance = null;
-
+
+ /** A flag controlling the visibility of the accelerator (if there is one). */
+ private boolean isAcceleratorHidden;
+
+ /** A string representing the accelerator key for the component. */
+ private String acceleratorString;
+
+ /**
+ * The delimiter for the accelerator string.
+ */
+ private String acceleratorDelimiter;
+
+ /** The font for the accelerator string. */
+ private Font acceleratorFont;
+
+ /** The color for the accelerator string. */
+ private Color acceleratorForeground;
+
+ /** The active border. */
+ private Border activeBorder;
+
+ /** The inactive border. */
+ private Border inactiveBorder;
+
/**
- * Constructs a new instance of MetalToolTipUI.
+ * Constructs a new instance of <code>MetalToolTipUI</code>.
*/
public MetalToolTipUI()
{
super();
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ activeBorder = defaults.getBorder("ToolTip.border");
+ inactiveBorder = defaults.getBorder("ToolTip.borderInactive");
+ isAcceleratorHidden = defaults.getBoolean("ToolTip.hideAccelerator");
+ acceleratorFont = defaults.getFont("MenuItem.acceleratorFont");
+ acceleratorForeground = defaults.getColor("MenuItem.acceleratorForeground");
+ acceleratorDelimiter = defaults.getString("MenuItem.acceleratorDelimiter");
}
/**
- * Returns an instance of MetalToolTipUI.
+ * Returns a shared instance of the <code>MetalToolTipUI</code> class.
+ * Although this UI delegate does maintain state information, there is never
+ * more than one tool tip visible, so it is OK to use a shared instance.
*
- * @param component the component for which we return an UI instance
+ * @param component the component (a {@link JToolTip}).
*
- * @return an instance of MetalToolTipUI
+ * @return A shared instance of the <code>MetalToolTipUI</code> class.
*/
public static ComponentUI createUI(JComponent component)
{
@@ -71,4 +131,202 @@ public class MetalToolTipUI
instance = new MetalToolTipUI();
return instance;
}
+
+ /**
+ * Returns a string representing the accelerator key (if there is one) for
+ * the component that the tool tip belongs to.
+ *
+ * @return A string representing the accelerator key.
+ */
+ public String getAcceleratorString()
+ {
+ return acceleratorString;
+ }
+
+ /**
+ * Installs the UI for the specified component (a {@link JToolTip}).
+ *
+ * @param c the {@link JToolTip} component.
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ Border existingBorder = c.getBorder();
+ if (existingBorder == null || existingBorder instanceof UIResource)
+ {
+ if (c.isEnabled())
+ c.setBorder(activeBorder);
+ else
+ c.setBorder(inactiveBorder);
+ }
+ }
+
+ /**
+ * Clears the defaults set in {@link #installUI(JComponent)}.
+ *
+ * @param c the component.
+ */
+ public void uninstallUI(JComponent c)
+ {
+ super.uninstallUI(c);
+ if (c.getBorder() instanceof UIResource)
+ c.setBorder(null);
+ }
+
+ /**
+ * Returns <code>true</code> if the accelerator string is hidden, and
+ * <code>false</code> otherwise. This setting is controlled by the
+ * <code>ToolTip.hideAccelerator</code> entry in the UI defaults table.
+ *
+ * @return A boolean.
+ */
+ protected boolean isAcceleratorHidden()
+ {
+ return isAcceleratorHidden;
+ }
+
+ /**
+ * Returns the preferred size for the {@link JToolTip} component.
+ *
+ * @param c the component (a {@link JToolTip}).
+ *
+ * @return The preferred size.
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ if (isAcceleratorHidden())
+ return super.getPreferredSize(c);
+ else
+ {
+ Insets insets = c.getInsets();
+ JToolTip tt = (JToolTip) c;
+ String tipText = tt.getTipText();
+ if (tipText != null)
+ {
+ FontMetrics fm = c.getFontMetrics(c.getFont());
+ int prefH = fm.getHeight() + insets.top + insets.bottom;
+ int prefW = fm.stringWidth(tipText) + insets.left + insets.right;
+
+ // this seems to be the first opportunity we have to get the
+ // accelerator string from the component (if it has one)
+ acceleratorString = fetchAcceleratorString(c);
+ if (acceleratorString != null)
+ {
+ prefW += padSpaceBetweenStrings;
+ fm = c.getFontMetrics(acceleratorFont);
+ prefW += fm.stringWidth(acceleratorString);
+ }
+ return new Dimension(prefW, prefH);
+ }
+ else return new Dimension(0, 0);
+ }
+ }
+
+ /**
+ * Paints the tool tip.
+ *
+ * @param g the graphics context.
+ * @param c the {@link JToolTip} component.
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ JToolTip tip = (JToolTip) c;
+
+ String text = tip.getTipText();
+ Toolkit t = tip.getToolkit();
+ if (text == null)
+ return;
+
+ Rectangle vr = new Rectangle();
+ vr = SwingUtilities.calculateInnerArea(tip, vr);
+ Rectangle ir = new Rectangle();
+ Rectangle tr = new Rectangle();
+ FontMetrics fm = t.getFontMetrics(tip.getFont());
+ int ascent = fm.getAscent();
+ SwingUtilities.layoutCompoundLabel(tip, fm, text, null,
+ SwingConstants.CENTER, SwingConstants.LEFT,
+ SwingConstants.CENTER, SwingConstants.CENTER, vr, ir, tr, 0);
+ Color saved = g.getColor();
+ g.setColor(Color.BLACK);
+
+ g.drawString(text, vr.x, vr.y + ascent);
+
+ // paint accelerator
+ if (acceleratorString != null)
+ {
+ g.setFont(acceleratorFont);
+ g.setColor(acceleratorForeground);
+ fm = t.getFontMetrics(acceleratorFont);
+ int width = fm.stringWidth(acceleratorString);
+ g.drawString(acceleratorString, vr.x + vr.width - width - padSpaceBetweenStrings/2,
+ vr.y + vr.height - fm.getDescent());
+ }
+
+ g.setColor(saved);
+ }
+
+ /**
+ * Returns a string representing the accelerator for the component, or
+ * <code>null</code> if the component has no accelerator.
+ *
+ * @param c the component.
+ *
+ * @return A string representing the accelerator (possibly
+ * <code>null</code>).
+ */
+ private String fetchAcceleratorString(JComponent c)
+ {
+ String result = null;
+ if (c instanceof JToolTip)
+ {
+ JToolTip toolTip = (JToolTip) c;
+ JComponent component = toolTip.getComponent();
+ KeyStroke ks = null;
+ int mne = 0;
+ if (component instanceof JMenuItem)
+ {
+ JMenuItem item = (JMenuItem) component;
+ ks = item.getAccelerator();
+ if (ks == null)
+ mne = item.getMnemonic();
+ }
+ else if (component instanceof AbstractButton)
+ {
+ AbstractButton button = (AbstractButton) component;
+ mne = button.getMnemonic();
+ }
+ if (mne > 0)
+ ks = KeyStroke.getKeyStroke(Character.toUpperCase((char) mne),
+ InputEvent.ALT_MASK, false);
+ if (ks != null)
+ result = acceleratorToString(ks);
+ }
+ return result;
+ }
+
+ /**
+ * Returns a string representing an accelerator.
+ *
+ * @param accelerator the accelerator (<code>null</code> not permitted).
+ *
+ * @return A string representing an accelerator.
+ */
+ private String acceleratorToString(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;
+
+ if (keyCode == KeyEvent.VK_UNDEFINED)
+ return modifiersText + keyChar;
+ else
+ return modifiersText + KeyEvent.getKeyText(keyCode);
+ }
+
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java
index 8d16f7463fe..0ffa0d17470 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java
@@ -38,21 +38,50 @@ exception statement from your version. */
package javax.swing.plaf.metal;
-import java.util.HashMap;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.event.ComponentListener;
+import java.awt.event.FocusListener;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseListener;
+import java.beans.PropertyChangeListener;
+import java.util.Hashtable;
import javax.swing.JComponent;
+import javax.swing.JTree;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
+import javax.swing.tree.TreeCellEditor;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+import javax.swing.event.CellEditorListener;
+import javax.swing.event.TreeExpansionListener;
+import javax.swing.event.TreeModelListener;
+import javax.swing.event.TreeSelectionListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTreeUI;
-public class MetalTreeUI
- extends BasicTreeUI
+/**
+ * A UI delegate for the {@link JTree} component.
+ */
+public class MetalTreeUI extends BasicTreeUI
{
- /** The UI instances for MetalTreeUIs */
- private static HashMap instances = null;
-
+ /** Listeners */
+ private PropertyChangeListener propertyChangeListener;
+ private FocusListener focusListener;
+ private TreeSelectionListener treeSelectionListener;
+ private MouseListener mouseListener;
+ private KeyListener keyListener;
+ private PropertyChangeListener selectionModelPropertyChangeListener;
+ private ComponentListener componentListener;
+ private CellEditorListener cellEditorListener;
+ private TreeExpansionListener treeExpansionListener;
+ private TreeModelListener treeModelListener;
+
/**
- * Constructs a new instance of MetalTreeUI.
+ * Constructs a new instance of <code>MetalTreeUI</code>.
*/
public MetalTreeUI()
{
@@ -60,27 +89,238 @@ public class MetalTreeUI
}
/**
- * Returns an instance of MetalTreeUI.
+ * Returns a new instance of <code>MetalTreeUI</code>.
*
* @param component the component for which we return an UI instance
*
- * @return an instance of MetalTreeUI
+ * @return A new instance of <code>MetalTreeUI</code>.
*/
public static ComponentUI createUI(JComponent component)
{
- if (instances == null)
- instances = new HashMap();
+ return new MetalTreeUI();
+ }
+
+ /**
+ * The horizontal element of legs between nodes starts at the right of the
+ * left-hand side of the child node by default. This method makes the
+ * leg end before that.
+ */
+ protected int getHorizontalLegBuffer()
+ {
+ return super.getHorizontalLegBuffer();
+ }
+
+ /**
+ * Configures the specified component appropriate for the look and feel.
+ * This method is invoked when the ComponentUI instance is being installed
+ * as the UI delegate on the specified component. This method should completely
+ * configure the component for the look and feel, including the following:
+ * 1. Install any default property values for color, fonts, borders, icons,
+ * opacity, etc. on the component. Whenever possible, property values
+ * initialized by the client program should not be overridden.
+ * 2. Install a LayoutManager on the component if necessary.
+ * 3. Create/add any required sub-components to the component.
+ * 4. Create/install event listeners on the component.
+ * 5. Create/install a PropertyChangeListener on the component in order
+ * to detect and respond to component property changes appropriately.
+ * 6. Install keyboard UI (mnemonics, traversal, etc.) on the component.
+ * 7. Initialize any appropriate instance data.
+ */
+ public void installUI(JComponent c)
+ {
+ tree = (JTree) c;
+ configureLayoutCache();
+
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ tree.setFont(defaults.getFont("Tree.font"));
+ tree.setForeground(defaults.getColor("Tree.foreground"));
+ tree.setBackground(defaults.getColor("Tree.background"));
+ tree.setOpaque(true);
+ tree.setScrollsOnExpand(defaults.getBoolean("Tree.scrollsOnExpand"));
+ rightChildIndent = defaults.getInt("Tree.rightChildIndent");
+ leftChildIndent = defaults.getInt("Tree.leftChildIndent");
+ setRowHeight(defaults.getInt("Tree.rowHeight"));
+ tree.setRowHeight(defaults.getInt("Tree.rowHeight"));
+ tree.requestFocusInWindow(false);
+
+ setExpandedIcon(defaults.getIcon("Tree.expandedIcon"));
+ setCollapsedIcon(defaults.getIcon("Tree.collapsedIcon"));
+
+ currentCellRenderer = createDefaultCellRenderer();
+ rendererPane = createCellRendererPane();
+ createdRenderer = true;
+ setCellEditor(createDefaultCellEditor());
+ createdCellEditor = true;
+ TreeModel mod = tree.getModel();
+ setModel(mod);
+
+ treeSelectionModel = tree.getSelectionModel();
+ drawingCache = new Hashtable();
+ nodeDimensions = createNodeDimensions();
+
+ propertyChangeListener = createPropertyChangeListener();
+ focusListener = createFocusListener();
+ treeSelectionListener = createTreeSelectionListener();
+ mouseListener = createMouseListener();
+ keyListener = createKeyListener();
+ selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener();
+ componentListener = createComponentListener();
+ cellEditorListener = createCellEditorListener();
+ treeExpansionListener = createTreeExpansionListener();
+ treeModelListener = createTreeModelListener();
- Object o = instances.get(component);
- MetalTreeUI instance;
- if (o == null)
+ editingRow = -1;
+ lastSelectedRow = -1;
+
+ installKeyboardActions();
+
+ tree.addPropertyChangeListener(propertyChangeListener);
+ tree.addFocusListener(focusListener);
+ tree.addTreeSelectionListener(treeSelectionListener);
+ tree.addMouseListener(mouseListener);
+ tree.addKeyListener(keyListener);
+ tree.addPropertyChangeListener(selectionModelPropertyChangeListener);
+ tree.addComponentListener(componentListener);
+ tree.addTreeExpansionListener(treeExpansionListener);
+ if (treeModel != null)
+ treeModel.addTreeModelListener(treeModelListener);
+
+ if (mod != null)
{
- instance = new MetalTreeUI();
- instances.put(component, instance);
+ TreePath path = new TreePath(mod.getRoot());
+ if (!tree.isExpanded(path))
+ toggleExpandState(path);
}
- else
- instance = (MetalTreeUI) o;
+
+ completeUIInstall();
+ }
+
+ /**
+ * Reverses configuration which was done on the specified component during
+ * installUI. This method is invoked when this UIComponent instance is being
+ * removed as the UI delegate for the specified component. This method should
+ * undo the configuration performed in installUI, being careful to leave the
+ * JComponent instance in a clean state (no extraneous listeners,
+ * look-and-feel-specific property objects, etc.). This should include
+ * the following:
+ * 1. Remove any UI-set borders from the component.
+ * 2. Remove any UI-set layout managers on the component.
+ * 3. Remove any UI-added sub-components from the component.
+ * 4. Remove any UI-added event/property listeners from the component.
+ * 5. Remove any UI-installed keyboard UI from the component.
+ * 6. Nullify any allocated instance data objects to allow for GC.
+ */
+ public void uninstallUI(JComponent c)
+ {
+ tree.setFont(null);
+ tree.setForeground(null);
+ tree.setBackground(null);
+
+ uninstallKeyboardActions();
+
+ tree.removePropertyChangeListener(propertyChangeListener);
+ tree.removeFocusListener(focusListener);
+ tree.removeTreeSelectionListener(treeSelectionListener);
+ tree.removeMouseListener(mouseListener);
+ tree.removeKeyListener(keyListener);
+ tree.removePropertyChangeListener(selectionModelPropertyChangeListener);
+ tree.removeComponentListener(componentListener);
+ tree.removeTreeExpansionListener(treeExpansionListener);
+
+ TreeCellEditor tce = tree.getCellEditor();
+ if (tce != null)
+ tce.removeCellEditorListener(cellEditorListener);
+ TreeModel tm = tree.getModel();
+ if (tm != null)
+ tm.removeTreeModelListener(treeModelListener);
+
+ tree = null;
+ uninstallComponents();
+ completeUIUninstall();
+ }
+
+ /**
+ * This function converts between the string passed into the client
+ * property and the internal representation (currently an int).
+ *
+ * @param lineStyleFlag - String representation
+ */
+ protected void decodeLineStyle(Object lineStyleFlag)
+ {
+ // FIXME: not implemented
+ }
- return instance;
+ /**
+ * Checks if the location is in expand control.
+ *
+ * @param row - current row
+ * @param rowLevel - current level
+ * @param mouseX - current x location of the mouse click
+ * @param mouseY - current y location of the mouse click
+ */
+ protected boolean isLocationInExpandControl(int row, int rowLevel,
+ int mouseX, int mouseY)
+ {
+ return super.isLocationInExpandControl(tree.getPathForRow(row),
+ mouseX, mouseY);
+ }
+
+ /**
+ * Paints the specified component appropriate for the look and feel.
+ * This method is invoked from the ComponentUI.update method when the
+ * specified component is being painted. Subclasses should override this
+ * method and use the specified Graphics object to render the content of
+ * the component.
+ *
+ * @param g - the current graphics configuration.
+ * @param c - the current component to draw
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ // Calls BasicTreeUI's paint since it takes care of painting all
+ // types of icons.
+ super.paint(g, c);
+ }
+
+ /**
+ * Paints the horizontal separators.
+ *
+ * @param g - the current graphics configuration.
+ * @param c - the current component to draw
+ */
+ protected void paintHorizontalSeparators(Graphics g, JComponent c)
+ {
+ // FIXME: not implemented
+ }
+
+
+ /**
+ * Paints the vertical part of the leg. The receiver should NOT modify
+ * clipBounds, insets.
+ *
+ * @param g - the current graphics configuration.
+ * @param clipBounds -
+ * @param insets -
+ * @param path - the current path
+ */
+ protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds,
+ Insets insets, TreePath path)
+ {
+ super.paintVerticalPartOfLeg(g, clipBounds, insets, path);
+ }
+
+ /**
+ * Paints the horizontal part of the leg. The receiver should NOT \
+ * modify clipBounds, or insets.
+ * NOTE: parentRow can be -1 if the root is not visible.
+ */
+ protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
+ Insets insets, Rectangle bounds,
+ TreePath path, int row,
+ boolean isExpanded, boolean hasBeenExpanded,
+ boolean isLeaf)
+ {
+ super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds, path, row,
+ isExpanded, hasBeenExpanded, isLeaf);
}
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java
index a342ee02bd3..c0b4e657676 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java
@@ -1,4 +1,4 @@
-/* Metaltils.java
+/* MetalUtils.java
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,7 +38,12 @@ exception statement from your version. */
package javax.swing.plaf.metal;
import java.awt.Color;
+import java.awt.Component;
import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.TexturePaint;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
/**
* Some utility and helper methods for the Metal Look &amp; Feel.
@@ -49,6 +54,21 @@ class MetalUtils
{
/**
+ * The typical metal pattern for use with Graphics2D.
+ */
+ static BufferedImage pattern2D;
+
+ /**
+ * The light color to draw the pattern.
+ */
+ static Color lightColor;
+
+ /**
+ * The dark color to draw to draw the pattern.
+ */
+ static Color darkColor;
+
+ /**
* Fills a rectangle with the typical Metal pattern.
*
* @param g the <code>Graphics</code> context to use
@@ -57,31 +77,78 @@ class MetalUtils
* @param y the Y coordinate of the upper left corner of the rectangle to
* fill
* @param w the width of the rectangle to fill
- * @param w the height of the rectangle to fill
+ * @param h the height of the rectangle to fill
* @param light the light color to use
* @param dark the dark color to use
*/
- static void fillMetalPattern(Graphics g, int x, int y, int w, int h,
+ static void fillMetalPattern(Component c, Graphics g, int x, int y, int w, int h,
Color light, Color dark)
{
- int xOff = 0;
- for (int mY = y; mY < (y + h); mY++)
+ if (g instanceof Graphics2D)
+ fillMetalPattern2D((Graphics2D) g, x, y, w, h, light, dark);
+ else
{
- // set color alternating with every line
- if ((mY % 2) == 0)
- g.setColor(light);
- else
- g.setColor(dark);
-
- for (int mX = x + (xOff); mX < (x + w); mX += 4)
+ int xOff = 0;
+ for (int mY = y; mY < (y + h); mY++)
{
- g.drawLine(mX, mY, mX, mY);
+ // set color alternating with every line
+ if (((mY - y) % 2) == 0)
+ g.setColor(light);
+ else
+ g.setColor(dark);
+
+ for (int mX = x + (xOff); mX < (x + w); mX += 4)
+ {
+ g.drawLine(mX, mY, mX, mY);
+ }
+
+ // increase x offset
+ xOff++;
+ if (xOff > 3)
+ xOff = 0;
}
+ }
+ }
+
+ /**
+ * Fills a rectangle with the typical Metal pattern using Java2D.
+ *
+ * @param g2d the <code>Graphics2D</code> context to use
+ * @param x the X coordinate of the upper left corner of the rectangle to
+ * fill
+ * @param y the Y coordinate of the upper left corner of the rectangle to
+ * fill
+ * @param w the width of the rectangle to fill
+ * @param h the height of the rectangle to fill
+ */
+ static void fillMetalPattern2D(Graphics2D g2d, int x, int y, int w, int h,
+ Color light, Color dark)
+ {
+ if (pattern2D == null || !darkColor.equals(dark) || !lightColor.equals(light))
+ initializePattern(light, dark);
+
+ // Prepare the texture.
+ TexturePaint texture =
+ new TexturePaint(pattern2D, new Rectangle2D.Double(0., 0., 4., 4.));
+ g2d.setPaint(texture);
+ g2d.fillRect(x, y, w, h);
+ }
- // increase x offset
- xOff++;
- if (xOff > 3)
- xOff = 0;
- }
+ /**
+ * Initializes the pattern image.
+ */
+ static void initializePattern(Color light, Color dark)
+ {
+ pattern2D = new BufferedImage(4, 4, BufferedImage.TYPE_INT_ARGB);
+ lightColor = light;
+ darkColor = dark;
+ Graphics g = pattern2D.getGraphics();
+ g.setColor(light);
+ g.fillRect(0, 0, 1, 1);
+ g.fillRect(2, 2, 1, 1);
+ g.setColor(dark);
+ g.fillRect(1, 1, 1, 1);
+ g.fillRect(3, 3, 1, 1);
+ g.dispose();
}
}
diff --git a/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java b/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java
new file mode 100644
index 00000000000..85a8cb1ff86
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java
@@ -0,0 +1,209 @@
+/* DefaultMetalTheme.java -- A modern theme for the Metal L&F
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.plaf.metal;
+
+import javax.swing.UIDefaults;
+import javax.swing.plaf.ColorUIResource;
+
+/**
+ * A modern theme for the Metal Look &amp; Feel.
+ * @since 1.5
+ *
+ * @author Roman Kennke (roman@kennke.org)
+ */
+public class OceanTheme extends DefaultMetalTheme
+{
+ /**
+ * The OceanTheme value for black.
+ */
+ static final ColorUIResource BLACK = new ColorUIResource(51, 51, 51);
+
+ /**
+ * The OceanTheme value for primary1.
+ */
+ static final ColorUIResource PRIMARY1 = new ColorUIResource(99, 130, 191);
+
+ /**
+ * The OceanTheme value for primary1.
+ */
+ static final ColorUIResource PRIMARY2 = new ColorUIResource(163, 184, 204);
+
+ /**
+ * The OceanTheme value for primary1.
+ */
+ static final ColorUIResource PRIMARY3 = new ColorUIResource(184, 207, 229);
+
+ /**
+ * The OceanTheme value for secondary1.
+ */
+ static final ColorUIResource SECONDARY1 = new ColorUIResource(122, 138, 153);
+
+ /**
+ * The OceanTheme value for secondary2.
+ */
+ static final ColorUIResource SECONDARY2 = new ColorUIResource(184, 207, 229);
+
+ /**
+ * The OceanTheme value for secondary3.
+ */
+ static final ColorUIResource SECONDARY3 = new ColorUIResource(238, 238, 238);
+
+ /**
+ * The OceanTheme value for inactive control text.
+ */
+ static final ColorUIResource INACTIVE_CONTROL_TEXT =
+ new ColorUIResource(153, 153, 153);
+
+ /**
+ * Returns the name of this theme, &quot;Ocean&quot;
+ */
+ public String getName()
+ {
+ return "Ocean";
+ }
+
+ /**
+ * Returns the color for control text, which is the
+ * value of the theme's black value.
+ */
+ public ColorUIResource getControlTextColor()
+ {
+ return getBlack();
+ }
+
+ /**
+ * Returns the desktop color, which is the theme's white color.
+ */
+ public ColorUIResource getDesktopColor()
+ {
+ return getWhite();
+ }
+
+ /**
+ * Returns the color for inactive control text, which is the
+ * RGB value (153, 153, 153).
+ */
+ public ColorUIResource getInactiveControlTextColor()
+ {
+ return INACTIVE_CONTROL_TEXT;
+ }
+
+ /**
+ * Returns the OceanTheme's color for disabled menu foreground,
+ *
+ */
+ public ColorUIResource getMenuDisabledForeground()
+ {
+ return INACTIVE_CONTROL_TEXT;
+ }
+
+
+ /**
+ * Returns the OceanTheme's color for black, the RGB value
+ * (51, 51, 51).
+ *
+ * @return Returns the OceanTheme's value for black
+ */
+ protected ColorUIResource getBlack()
+ {
+ return BLACK;
+ }
+
+ /**
+ * Return the OceanTheme's value for primary 1, the RGB value
+ * (99, 130, 191).
+ */
+ protected ColorUIResource getPrimary1()
+ {
+ return PRIMARY1;
+ }
+
+ /**
+ * Return the OceanTheme's value for primary 2, the RGB value
+ * (163, 184, 204).
+ */
+ protected ColorUIResource getPrimary2()
+ {
+ return PRIMARY2;
+ }
+
+ /**
+ * Return the OceanTheme's value for primary 1, the RGB value
+ * (184, 207, 229).
+ */
+ protected ColorUIResource getPrimary3()
+ {
+ return PRIMARY3;
+ }
+
+ /**
+ * Return the OceanTheme's value for secondary 1, the RGB value
+ * (122, 138, 153).
+ */
+ protected ColorUIResource getSecondary1()
+ {
+ return SECONDARY1;
+ }
+
+ /**
+ * Return the OceanTheme's value for secondary 2, the RGB value
+ * (184, 207, 229).
+ */
+ protected ColorUIResource getSecondary2()
+ {
+ return SECONDARY2;
+ }
+ /**
+ * Return the OceanTheme's value for secondary 3, the RGB value
+ * (238, 238, 238).
+ */
+ protected ColorUIResource getSecondary3()
+ {
+ return SECONDARY3;
+ }
+
+ /**
+ * Adds customized entries to the UIDefaults table.
+ *
+ * @param defaults the UI defaults table
+ */
+ public void addCustomEntriesToTable(UIDefaults defaults)
+ {
+ defaults.put("Button.rollover", Boolean.TRUE);
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/package.html b/libjava/classpath/javax/swing/plaf/metal/package.html
index 2ea787bb5e2..8675493b68c 100644
--- a/libjava/classpath/javax/swing/plaf/metal/package.html
+++ b/libjava/classpath/javax/swing/plaf/metal/package.html
@@ -40,7 +40,16 @@ exception statement from your version. -->
<head><title>GNU Classpath - javax.swing.plaf.metal</title></head>
<body>
-<p>Provides a cross-platform look and feel known as "Metal".</p>
-
+<p>Provides a cross-platform look and feel known as "Metal". To install this
+look and feel, add the following code (or something similar)
+near the start of your application:</p>
+<pre>try
+ {
+&nbsp;&nbsp;UIManager.setLookAndFeel(new MetalLookAndFeel());
+ }
+catch (UnsupportedLookAndFeelException e)
+ {
+&nbsp;&nbsp;e.printStackTrace();
+ }</pre>
</body>
</html>
diff --git a/libjava/classpath/javax/swing/plaf/multi/MultiLookAndFeel.java b/libjava/classpath/javax/swing/plaf/multi/MultiLookAndFeel.java
index a70a8ff690e..2bd358dd01e 100644
--- a/libjava/classpath/javax/swing/plaf/multi/MultiLookAndFeel.java
+++ b/libjava/classpath/javax/swing/plaf/multi/MultiLookAndFeel.java
@@ -56,6 +56,7 @@ public class MultiLookAndFeel extends LookAndFeel {
*/
public MultiLookAndFeel()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java b/libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java
index 349f4baad12..a187d74a686 100644
--- a/libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java
+++ b/libjava/classpath/javax/swing/table/DefaultTableCellRenderer.java
@@ -43,8 +43,10 @@ import java.awt.Component;
import java.awt.Rectangle;
import java.io.Serializable;
+import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JTable;
+import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextField;
@@ -64,10 +66,21 @@ public class DefaultTableCellRenderer extends JLabel
{
public UIResource()
{
+ super();
}
}
/**
+ * Stores the color set by setForeground().
+ */
+ Color foreground;
+
+ /**
+ * Stores the color set by setBackground().
+ */
+ Color background;
+
+ /**
* Creates a default table cell renderer with an empty border.
*/
public DefaultTableCellRenderer()
@@ -83,6 +96,7 @@ public class DefaultTableCellRenderer extends JLabel
public void setForeground(Color c)
{
super.setForeground(c);
+ foreground = c;
}
/**
@@ -93,6 +107,7 @@ public class DefaultTableCellRenderer extends JLabel
public void setBackground(Color c)
{
super.setBackground(c);
+ background = c;
}
/**
@@ -104,6 +119,8 @@ public class DefaultTableCellRenderer extends JLabel
public void updateUI()
{
super.updateUI();
+ background = null;
+ foreground = null;
}
/**
@@ -137,17 +154,41 @@ public class DefaultTableCellRenderer extends JLabel
if (isSelected)
{
- setBackground(table.getSelectionBackground());
- setForeground(table.getSelectionForeground());
+ super.setBackground(table.getSelectionBackground());
+ super.setForeground(table.getSelectionForeground());
}
else
{
- setBackground(table.getBackground());
- setForeground(table.getForeground());
+ if (background != null)
+ super.setBackground(background);
+ else
+ super.setBackground(table.getBackground());
+ if (foreground != null)
+ super.setForeground(foreground);
+ else
+ super.setForeground(table.getForeground());
}
+ if (hasFocus)
+ {
+ setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
+ if (table.isCellEditable(row, column))
+ {
+ super.setBackground(UIManager.getColor("Table.focusCellBackground"));
+ super.setForeground(UIManager.getColor("Table.focusCellForeground"));
+ }
+ }
+ else
+ setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
+
setEnabled(table.isEnabled());
setFont(table.getFont());
+
+ // If the current background is equal to the table's background, then we
+ // can avoid filling the background by setting the renderer opaque.
+ Color back = getBackground();
+ setOpaque(back != null && back.equals(table.getBackground()));
+
return this;
}
diff --git a/libjava/classpath/javax/swing/table/JTableHeader.java b/libjava/classpath/javax/swing/table/JTableHeader.java
index 45586da2009..163509a45c2 100644
--- a/libjava/classpath/javax/swing/table/JTableHeader.java
+++ b/libjava/classpath/javax/swing/table/JTableHeader.java
@@ -61,9 +61,14 @@ import javax.accessibility.AccessibleValue;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.UIManager;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.TableColumnModelEvent;
+import javax.swing.event.TableColumnModelListener;
import javax.swing.plaf.TableHeaderUI;
public class JTableHeader extends JComponent
+ implements TableColumnModelListener, Accessible
{
protected class AccessibleJTableHeader extends AccessibleJComponent
{
@@ -305,11 +310,6 @@ public class JTableHeader extends JComponent
private static final long serialVersionUID = 5144633983372967710L;
/**
- * The accessibleContext property.
- */
- AccessibleContext accessibleContext;
-
- /**
* The columnModel property.
*/
protected TableColumnModel columnModel;
@@ -373,17 +373,8 @@ public class JTableHeader extends JComponent
*/
public JTableHeader(TableColumnModel cm)
{
- accessibleContext = new AccessibleJTableHeader();
columnModel = cm == null ? createDefaultColumnModel() : cm;
- draggedColumn = null;
- draggedDistance = 0;
- opaque = true;
- reorderingAllowed = true;
- resizingAllowed = true;
- resizingColumn = null;
- table = null;
- updateTableInRealTime = true;
- cellRenderer = createDefaultRenderer();
+ initializeLocalVars();
updateUI();
}
@@ -504,7 +495,9 @@ public class JTableHeader extends JComponent
*/
public void setColumnModel(TableColumnModel c)
{
+ columnModel.removeColumnModelListener(this);
columnModel = c;
+ columnModel.addColumnModelListener(this);
}
/**
@@ -619,7 +612,7 @@ public class JTableHeader extends JComponent
public Rectangle getHeaderRect(int column)
{
- Rectangle r = getTable().getCellRect(-1, column, true);
+ Rectangle r = getTable().getCellRect(-1, column, false);
r.height = getHeight();
return r;
}
@@ -665,4 +658,88 @@ public class JTableHeader extends JComponent
return -1;
}
+
+ /**
+ * Receives notification when a column is added to the column model.
+ *
+ * @param event the table column model event
+ */
+ public void columnAdded(TableColumnModelEvent event)
+ {
+ // TODO: What else to do here (if anything)?
+ resizeAndRepaint();
+ }
+
+ /**
+ * Receives notification when a column margin changes in the column model.
+ *
+ * @param event the table column model event
+ */
+ public void columnMarginChanged(ChangeEvent event)
+ {
+ // TODO: What else to do here (if anything)?
+ resizeAndRepaint();
+ }
+
+ /**
+ * Receives notification when a column is moved within the column model.
+ *
+ * @param event the table column model event
+ */
+ public void columnMoved(TableColumnModelEvent event)
+ {
+ // TODO: What else to do here (if anything)?
+ resizeAndRepaint();
+ }
+
+ /**
+ * Receives notification when a column is removed from the column model.
+ *
+ * @param event the table column model event
+ */
+ public void columnRemoved(TableColumnModelEvent event)
+ {
+ // TODO: What else to do here (if anything)?
+ resizeAndRepaint();
+ }
+
+ /**
+ * Receives notification when the column selection has changed.
+ *
+ * @param event the table column model event
+ */
+ public void columnSelectionChanged(ListSelectionEvent event)
+ {
+ // TODO: What else to do here (if anything)?
+ resizeAndRepaint();
+ }
+
+ /**
+ * Validates the layout of this table header and repaints it. This is
+ * equivalent to <code>revalidate()</code> followed by
+ * <code>repaint()</code>.
+ */
+ public void resizeAndRepaint()
+ {
+ revalidate();
+ repaint();
+ }
+
+ /**
+ * Initializes the fields and properties of this class with default values.
+ * This is called by the constructors.
+ */
+ protected void initializeLocalVars()
+ {
+ accessibleContext = new AccessibleJTableHeader();
+ draggedColumn = null;
+ draggedDistance = 0;
+ opaque = true;
+ reorderingAllowed = true;
+ resizingAllowed = true;
+ resizingColumn = null;
+ table = null;
+ updateTableInRealTime = true;
+ cellRenderer = createDefaultRenderer();
+ }
}
diff --git a/libjava/classpath/javax/swing/table/TableColumn.java b/libjava/classpath/javax/swing/table/TableColumn.java
index 9c36bb05ab0..9f06c5b7fcc 100644
--- a/libjava/classpath/javax/swing/table/TableColumn.java
+++ b/libjava/classpath/javax/swing/table/TableColumn.java
@@ -402,7 +402,11 @@ public class TableColumn
if (width == oldWidth)
return;
- firePropertyChange(COLUMN_WIDTH_PROPERTY, oldWidth, width);
+ // We do have a constant field COLUMN_WIDTH_PROPERTY,
+ // however, tests show that the actual fired property name is 'width'
+ // and even Sun's API docs say that this constant field is obsolete and
+ // not used.
+ firePropertyChange("width", oldWidth, width);
}
/**
@@ -422,12 +426,16 @@ public class TableColumn
*/
public void setPreferredWidth(int preferredWidth)
{
+ int oldPrefWidth = this.preferredWidth;
+
if (preferredWidth < minWidth)
this.preferredWidth = minWidth;
else if (preferredWidth > maxWidth)
this.preferredWidth = maxWidth;
else
this.preferredWidth = preferredWidth;
+
+ firePropertyChange("preferredWidth", oldPrefWidth, this.preferredWidth);
}
/**
diff --git a/libjava/classpath/javax/swing/table/TableColumnModel.java b/libjava/classpath/javax/swing/table/TableColumnModel.java
index 76a145604db..b006f9ad4bb 100644
--- a/libjava/classpath/javax/swing/table/TableColumnModel.java
+++ b/libjava/classpath/javax/swing/table/TableColumnModel.java
@@ -50,6 +50,7 @@ import javax.swing.event.TableColumnModelListener;
*
* @author Andrew Selkirk
*/
+// FIXME: The API documentation in this class is incomplete.
public interface TableColumnModel
{
/**
@@ -107,7 +108,7 @@ public interface TableColumnModel
* @throws IllegalArgumentException if <code>identifier</code> is
* <code>null</code> or there is no column with that identifier.
*/
- int getColumnIndex(Object columnIdentifier);
+ int getColumnIndex(Object identifier);
/**
* Returns the <code>TableColumn</code> at the specified index.
@@ -169,7 +170,6 @@ public interface TableColumnModel
/**
* getSelectionModel
- * @param column TableColumn
*/
ListSelectionModel getSelectionModel();
diff --git a/libjava/classpath/javax/swing/text/AbstractDocument.java b/libjava/classpath/javax/swing/text/AbstractDocument.java
index 3c9a4d497a5..baf8608b888 100644
--- a/libjava/classpath/javax/swing/text/AbstractDocument.java
+++ b/libjava/classpath/javax/swing/text/AbstractDocument.java
@@ -65,11 +65,10 @@ import javax.swing.undo.UndoableEdit;
* @author original author unknown
* @author Roman Kennke (roman@kennke.org)
*/
-public abstract class AbstractDocument
- implements Document, Serializable
+public abstract class AbstractDocument implements Document, Serializable
{
- /** The serial version UID for this class as of JDK1.4. */
- private static final long serialVersionUID = -116069779446114664L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 6842927725919637215L;
/**
* Standard error message to indicate a bad location.
@@ -128,7 +127,28 @@ public abstract class AbstractDocument
* Manages event listeners for this <code>Document</code>.
*/
protected EventListenerList listenerList = new EventListenerList();
+
+ /**
+ * Stores the current writer thread. Used for locking.
+ */
+ private Thread currentWriter = null;
+
+ /**
+ * The number of readers. Used for locking.
+ */
+ private int numReaders = 0;
+
+ /**
+ * Tells if there are one or more writers waiting.
+ */
+ private int numWritersWaiting = 0;
+
+ /**
+ * A condition variable that readers and writers wait on.
+ */
+ Object documentCV = new Object();
+
/**
* Creates a new <code>AbstractDocument</code> with the specified
* {@link Content} model.
@@ -332,7 +352,7 @@ public abstract class AbstractDocument
* @see GapContent
* @see StringContent
*/
- protected Content getContent()
+ protected final Content getContent()
{
return content;
}
@@ -348,8 +368,7 @@ public abstract class AbstractDocument
*/
protected Thread getCurrentWriter()
{
- // FIXME: Implement locking!
- return null;
+ return currentWriter;
}
/**
@@ -516,13 +535,18 @@ public abstract class AbstractDocument
// Just return when no text to insert was given.
if (text == null || text.length() == 0)
return;
-
DefaultDocumentEvent event =
new DefaultDocumentEvent(offset, text.length(),
DocumentEvent.EventType.INSERT);
- content.insertString(offset, text);
+
+ writeLock();
+ UndoableEdit undo = content.insertString(offset, text);
insertUpdate(event, attributes);
+ writeUnlock();
+
fireInsertUpdate(event);
+ if (undo != null)
+ fireUndoableEditUpdate(new UndoableEditEvent(this, undo));
}
/**
@@ -566,10 +590,28 @@ public abstract class AbstractDocument
}
/**
- * Blocks until a read lock can be obtained.
+ * Blocks until a read lock can be obtained. Must block if there is
+ * currently a writer modifying the <code>Document</code>.
*/
public void readLock()
{
+ if (currentWriter != null && currentWriter.equals(Thread.currentThread()))
+ return;
+ synchronized (documentCV)
+ {
+ while (currentWriter != null || numWritersWaiting > 0)
+ {
+ try
+ {
+ documentCV.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ throw new Error("interrupted trying to get a readLock");
+ }
+ }
+ numReaders++;
+ }
}
/**
@@ -578,6 +620,40 @@ public abstract class AbstractDocument
*/
public void readUnlock()
{
+ // Note we could have a problem here if readUnlock was called without a
+ // prior call to readLock but the specs simply warn users to ensure that
+ // balance by using a finally block:
+ // readLock()
+ // try
+ // {
+ // doSomethingHere
+ // }
+ // finally
+ // {
+ // readUnlock();
+ // }
+
+ // All that the JDK seems to check for is that you don't call unlock
+ // more times than you've previously called lock, but it doesn't make
+ // sure that the threads calling unlock were the same ones that called lock
+
+ // FIXME: the reference implementation throws a
+ // javax.swing.text.StateInvariantError here
+ if (numReaders == 0)
+ throw new IllegalStateException("document lock failure");
+
+ synchronized (documentCV)
+ {
+ // If currentWriter is not null, the application code probably had a
+ // writeLock and then tried to obtain a readLock, in which case
+ // numReaders wasn't incremented
+ if (currentWriter == null)
+ {
+ numReaders --;
+ if (numReaders == 0 && numWritersWaiting != 0)
+ documentCV.notify();
+ }
+ }
}
/**
@@ -595,10 +671,42 @@ public abstract class AbstractDocument
DefaultDocumentEvent event =
new DefaultDocumentEvent(offset, length,
DocumentEvent.EventType.REMOVE);
+
+ // Here we set up the parameters for an ElementChange, if one
+ // needs to be added to the DocumentEvent later
+ Element root = getDefaultRootElement();
+ int start = root.getElementIndex(offset);
+ int end = root.getElementIndex(offset + length);
+
+ Element[] removed = new Element[end - start + 1];
+ for (int i = start; i <= end; i++)
+ removed[i - start] = root.getElement(i);
+
removeUpdate(event);
- content.remove(offset, length);
+
+ Element[] added = new Element[1];
+ added[0] = root.getElement(start);
+ boolean shouldFire = content.getString(offset, length).length() != 0;
+
+ writeLock();
+ UndoableEdit temp = content.remove(offset, length);
+ writeUnlock();
+
postRemoveUpdate(event);
- fireRemoveUpdate(event);
+
+ GapContent.UndoRemove changes = null;
+ if (content instanceof GapContent)
+ changes = (GapContent.UndoRemove) temp;
+
+ if (changes != null && !(start == end))
+ {
+ // We need to add an ElementChange to our DocumentEvent
+ ElementEdit edit = new ElementEdit (root, start, removed, added);
+ event.addEdit(edit);
+ }
+
+ if (shouldFire)
+ fireRemoveUpdate(event);
}
/**
@@ -713,7 +821,15 @@ public abstract class AbstractDocument
*/
public void render(Runnable runnable)
{
- // FIXME: Implement me!
+ readLock();
+ try
+ {
+ runnable.run();
+ }
+ finally
+ {
+ readUnlock();
+ }
}
/**
@@ -725,6 +841,7 @@ public abstract class AbstractDocument
*/
public void setAsynchronousLoadPriority(int p)
{
+ // TODO: Implement this properly.
}
/**
@@ -739,11 +856,30 @@ public abstract class AbstractDocument
}
/**
- * Blocks until a write lock can be obtained.
+ * Blocks until a write lock can be obtained. Must wait if there are
+ * readers currently reading or another thread is currently writing.
*/
protected void writeLock()
{
- // FIXME: Implement me.
+ if (currentWriter!= null && currentWriter.equals(Thread.currentThread()))
+ return;
+ synchronized (documentCV)
+ {
+ numWritersWaiting++;
+ while (numReaders > 0)
+ {
+ try
+ {
+ documentCV.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ throw new Error("interruped while trying to obtain write lock");
+ }
+ }
+ numWritersWaiting --;
+ currentWriter = Thread.currentThread();
+ }
}
/**
@@ -752,7 +888,14 @@ public abstract class AbstractDocument
*/
protected void writeUnlock()
{
- // FIXME: Implement me.
+ synchronized (documentCV)
+ {
+ if (Thread.currentThread().equals(currentWriter))
+ {
+ currentWriter = null;
+ documentCV.notifyAll();
+ }
+ }
}
/**
@@ -970,8 +1113,8 @@ public abstract class AbstractDocument
public abstract class AbstractElement
implements Element, MutableAttributeSet, TreeNode, Serializable
{
- /** The serial version UID for AbstractElement. */
- private static final long serialVersionUID = 1265312733007397733L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 1712240033321461704L;
/** The number of characters that this Element spans. */
int count;
@@ -1231,6 +1374,9 @@ public abstract class AbstractDocument
/**
* Returns the resolve parent of this element.
+ * This is taken from the AttributeSet, but if this is null,
+ * this method instead returns the Element's parent's
+ * AttributeSet
*
* @return the resolve parent of this element
*
@@ -1238,7 +1384,9 @@ public abstract class AbstractDocument
*/
public AttributeSet getResolveParent()
{
- return attributes.getResolveParent();
+ if (attributes.getResolveParent() != null)
+ return attributes.getResolveParent();
+ return element_parent.getAttributes();
}
/**
@@ -1355,49 +1503,6 @@ public abstract class AbstractDocument
public abstract int getStartOffset();
/**
- * Prints diagnostic information to the specified stream.
- *
- * @param stream the stream to dump to
- * @param indent the indentation level
- * @param element the element to be dumped
- */
- private void dumpElement(PrintStream stream, String indent,
- Element element)
- {
- // FIXME: Should the method be removed?
- System.out.println(indent + "<" + element.getName() +">");
-
- if (element.isLeaf())
- {
- int start = element.getStartOffset();
- int end = element.getEndOffset();
- String text = "";
- try
- {
- text = getContent().getString(start, end - start);
- }
- catch (BadLocationException e)
- {
- AssertionError error =
- new AssertionError("BadLocationException should not be "
- + "thrown here. start = " + start
- + ", end = " + end);
- error.initCause(e);
- throw error;
- }
- System.out.println(indent + " ["
- + start + ","
- + end + "]["
- + text + "]");
- }
- else
- {
- for (int i = 0; i < element.getElementCount(); ++i)
- dumpElement(stream, indent + " ", element.getElement(i));
- }
- }
-
- /**
* Prints diagnostic output to the specified stream.
*
* @param stream the stream to write to
@@ -1405,10 +1510,66 @@ public abstract class AbstractDocument
*/
public void dump(PrintStream stream, int indent)
{
- String indentStr = "";
+ StringBuffer b = new StringBuffer();
for (int i = 0; i < indent; ++i)
- indentStr += " ";
- dumpElement(stream, indentStr, this);
+ b.append(' ');
+ b.append('<');
+ b.append(getName());
+ // Dump attributes if there are any.
+ if (getAttributeCount() > 0)
+ {
+ b.append('\n');
+ Enumeration attNames = getAttributeNames();
+ while (attNames.hasMoreElements())
+ {
+ for (int i = 0; i < indent + 2; ++i)
+ b.append(' ');
+ Object attName = attNames.nextElement();
+ b.append(attName);
+ b.append('=');
+ Object attribute = getAttribute(attName);
+ b.append(attribute);
+ b.append('\n');
+ }
+ }
+ b.append(">\n");
+
+ // Dump element content for leaf elements.
+ if (isLeaf())
+ {
+ for (int i = 0; i < indent + 2; ++i)
+ b.append(' ');
+ int start = getStartOffset();
+ int end = getEndOffset();
+ b.append('[');
+ b.append(start);
+ b.append(',');
+ b.append(end);
+ b.append("][");
+ try
+ {
+ b.append(getDocument().getText(start, end - start));
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError("BadLocationException "
+ + "must not be thrown "
+ + "here.");
+ err.initCause(ex);
+ throw err;
+ }
+ b.append("]\n");
+ }
+ stream.print(b.toString());
+
+ // Dump child elements if any.
+ int count = getElementCount();
+ for (int i = 0; i < count; ++i)
+ {
+ Element el = getElement(i);
+ if (el instanceof AbstractElement)
+ ((AbstractElement) el).dump(stream, indent + 2);
+ }
}
}
@@ -1418,8 +1579,8 @@ public abstract class AbstractDocument
*/
public class BranchElement extends AbstractElement
{
- /** The serial version UID for BranchElement. */
- private static final long serialVersionUID = -8595176318868717313L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -6037216547466333183L;
/** The child elements of this BranchElement. */
private Element[] children = new Element[0];
@@ -1503,19 +1664,30 @@ public abstract class AbstractDocument
*/
public int getElementIndex(int offset)
{
- // If we have no children, return -1.
- if (getElementCount() == 0)
- return - 1;
-
+ // If offset is less than the start offset of our first child,
+ // return 0
+ if (offset < getStartOffset())
+ return 0;
+
// XXX: There is surely a better algorithm
// as beginning from first element each time.
- for (int index = 0; index < children.length; ++index)
+ for (int index = 0; index < children.length - 1; ++index)
{
Element elem = children[index];
if ((elem.getStartOffset() <= offset)
&& (offset < elem.getEndOffset()))
return index;
+ // If the next element's start offset is greater than offset
+ // then we have to return the closest Element, since no Elements
+ // will contain the offset
+ if (children[index + 1].getStartOffset() > offset)
+ {
+ if ((offset - elem.getEndOffset()) > (children[index + 1].getStartOffset() - offset))
+ return index + 1;
+ else
+ return index;
+ }
}
// If offset is greater than the index of the last element, return
@@ -1642,8 +1814,8 @@ public abstract class AbstractDocument
public class DefaultDocumentEvent extends CompoundEdit
implements DocumentEvent
{
- /** The serial version UID of DefaultDocumentEvent. */
- private static final long serialVersionUID = -7406103236022413522L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 5230037221564563284L;
/** The starting offset of the change. */
private int offset;
@@ -1748,7 +1920,7 @@ public abstract class AbstractDocument
return (DocumentEvent.ElementChange) changes.get(elem);
}
}
-
+
/**
* An implementation of {@link DocumentEvent.ElementChange} to be added
* to {@link DefaultDocumentEvent}s.
@@ -1843,8 +2015,8 @@ public abstract class AbstractDocument
*/
public class LeafElement extends AbstractElement
{
- /** The serial version UID of LeafElement. */
- private static final long serialVersionUID = 5115368706941283802L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -8906306331347768017L;
/** Manages the start offset of this element. */
Position startPos;
diff --git a/libjava/classpath/javax/swing/text/AttributeSet.java b/libjava/classpath/javax/swing/text/AttributeSet.java
index 2f1f1890bae..01d148c067b 100644
--- a/libjava/classpath/javax/swing/text/AttributeSet.java
+++ b/libjava/classpath/javax/swing/text/AttributeSet.java
@@ -58,6 +58,7 @@ public interface AttributeSet
*/
static interface CharacterAttribute
{
+ // This interface is a marker interface and has no methods.
}
/**
@@ -65,6 +66,7 @@ public interface AttributeSet
*/
static interface ColorAttribute
{
+ // This interface is a marker interface and has no methods.
}
/**
@@ -72,6 +74,7 @@ public interface AttributeSet
*/
static interface FontAttribute
{
+ // This interface is a marker interface and has no methods.
}
/**
@@ -79,6 +82,7 @@ public interface AttributeSet
*/
static interface ParagraphAttribute
{
+ // This interface is a marker interface and has no methods.
}
/**
@@ -99,7 +103,7 @@ public interface AttributeSet
* <code>false</code> otherwise.
*
* @param name the name of the requested attribute
- * @param the value of the requested attribute
+ * @param value the value of the requested attribute
*
* @return <code>true</code> if this <code>AttributeSet</code> contains
* an attribute with the specified <code>name</code> and
diff --git a/libjava/classpath/javax/swing/text/BoxView.java b/libjava/classpath/javax/swing/text/BoxView.java
index 0f8ba1ce15e..f201045dbdb 100644
--- a/libjava/classpath/javax/swing/text/BoxView.java
+++ b/libjava/classpath/javax/swing/text/BoxView.java
@@ -155,8 +155,9 @@ public class BoxView
* automatically when any of the child view changes its preferences
* via {@link #preferenceChanged(View, boolean, boolean)}.
*
- * The layout will be updated the next time when {@link #setSize()} is
- * called, typically from within the {@link #paint()} method.
+ * The layout will be updated the next time when
+ * {@link #setSize(float, float)} is called, typically from within the
+ * {@link #paint(Graphics, Shape)} method.
*
* Valid values for the axis are {@link View#X_AXIS} and
* {@link View#Y_AXIS}.
@@ -216,12 +217,11 @@ public class BoxView
* @param alloc the allocated region for the child to paint into
* @param index the index of the child to be painted
*
- * @see {@link #childAllocation}
+ * @see #childAllocation(int, Rectangle)
*/
protected void paintChild(Graphics g, Rectangle alloc, int index)
{
View child = getView(index);
- childAllocation(index, alloc);
child.paint(g, alloc);
}
@@ -301,18 +301,15 @@ public class BoxView
setSize(bounds.width, bounds.height);
Rectangle inside = getInsideAllocation(a);
-
Rectangle copy = new Rectangle(inside);
int count = getViewCount();
for (int i = 0; i < count; ++i)
{
- // TODO: Figure out if the parameter to paintChild is meant to
- // be the child allocation or the allocation of this BoxView.
- // I assume the second option here.
- // We pass this method a copy of the inside rectangle here because
- // it modifies the actual values.
copy.setBounds(inside);
- paintChild(g, copy, i);
+ childAllocation(i, copy);
+ if (!copy.isEmpty()
+ && g.hitClip(copy.x, copy.y, copy.width, copy.height))
+ paintChild(g, copy, i);
}
}
@@ -362,6 +359,24 @@ public class BoxView
}
/**
+ * Calculates the layout of the children of this <code>BoxView</code> along
+ * the specified axis.
+ *
+ * @param span the target span
+ * @param axis the axis that is examined
+ * @param offsets an empty array, filled with the offsets of the children
+ * @param spans an empty array, filled with the spans of the children
+ */
+ protected void baselineLayout(int span, int axis, int[] offsets,
+ int[] spans)
+ {
+ if (axis == myAxis)
+ layoutMajorAxis(span, axis, offsets, spans);
+ else
+ layoutMinorAxis(span, axis, offsets, spans);
+ }
+
+ /**
* Calculates the size requirements of this <code>BoxView</code> along
* its major axis, that is the axis specified in the constructor.
*
@@ -375,27 +390,8 @@ public class BoxView
protected SizeRequirements calculateMajorAxisRequirements(int axis,
SizeRequirements sr)
{
- if (sr == null)
- sr = new SizeRequirements();
- else
- {
- sr.maximum = 0;
- sr.minimum = 0;
- sr.preferred = 0;
- sr.alignment = 0.5F;
- }
-
- int count = getViewCount();
-
- // Sum up the sizes of the children along the specified axis.
- for (int i = 0; i < count; ++i)
- {
- View child = getView(i);
- sr.minimum += child.getMinimumSpan(axis);
- sr.preferred += child.getPreferredSpan(axis);
- sr.maximum += child.getMaximumSpan(axis);
- }
- return sr;
+ SizeRequirements[] childReqs = getChildRequirements(axis);
+ return SizeRequirements.getTiledSizeRequirements(childReqs);
}
/**
@@ -413,48 +409,8 @@ public class BoxView
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements sr)
{
- if (sr == null)
- sr = new SizeRequirements();
- else
- {
- sr.maximum = 0;
- sr.minimum = 0;
- sr.preferred = 0;
- sr.alignment = 0.5F;
- }
-
- int count = getViewCount();
-
- int aboveBaseline = 0;
- int belowBaseline = 0;
- int aboveBaselineMin = 0;
- int belowBaselineMin = 0;
- int aboveBaselineMax = 0;
- int belowBaselineMax = 0;
-
- for (int i = 0; i < count; ++i)
- {
- View child = getView(i);
- float align = child.getAlignment(axis);
- int pref = (int) child.getPreferredSpan(axis);
- int min = (int) child.getMinimumSpan(axis);
- int max = (int) child.getMaximumSpan(axis);
- aboveBaseline += (int) (align * pref);
- belowBaseline += (int) ((1.F - align) * pref);
- aboveBaselineMin += (int) (align * min);
- belowBaselineMin += (int) ((1.F - align) * min);
- aboveBaselineMax += (int) (align * max);
- belowBaselineMax += (int) ((1.F - align) * max);
- }
- sr.minimum = aboveBaselineMin + belowBaselineMin;
- sr.maximum = aboveBaselineMax + belowBaselineMax;
- sr.preferred = aboveBaseline + belowBaseline;
- if (aboveBaseline == 0)
- sr.alignment = 1.0F;
- else
- sr.alignment = (float) (sr.preferred / aboveBaseline);
-
- return sr;
+ SizeRequirements[] childReqs = getChildRequirements(axis);
+ return SizeRequirements.getAlignedSizeRequirements(childReqs);
}
/**
@@ -569,19 +525,8 @@ public class BoxView
*/
protected void layout(int width, int height)
{
- this.width = width;
- this.height = height;
-
- if (myAxis == X_AXIS)
- {
- layoutMajorAxis(width, X_AXIS, offsetsX, spansX);
- layoutMinorAxis(height, Y_AXIS, offsetsY, spansY);
- }
- else
- {
- layoutMajorAxis(height, Y_AXIS, offsetsY, spansY);
- layoutMinorAxis(width, X_AXIS, offsetsX, spansX);
- }
+ baselineLayout(width, X_AXIS, offsetsX, spansX);
+ baselineLayout(height, Y_AXIS, offsetsY, spansY);
}
/**
@@ -591,28 +536,16 @@ public class BoxView
* to layout the children
* @param axis the axis along which the layout is performed
* @param offsets the array that holds the offsets of the children on exit
- * @param offsets the array that holds the spans of the children on exit
+ * @param spans the array that holds the spans of the children on exit
*/
protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
int[] spans)
{
- // Allocate SizeRequirements for each child view.
- int count = getViewCount();
- SizeRequirements[] childReqs = new SizeRequirements[count];
- for (int i = 0; i < count; ++i)
- {
- View view = getView(i);
- childReqs[i] = new SizeRequirements((int) view.getMinimumSpan(axis),
- (int) view.getPreferredSpan(axis),
- (int) view.getMaximumSpan(axis),
- view.getAlignment(axis));
- }
-
+ SizeRequirements[] childReqs = getChildRequirements(axis);
// Calculate the spans and offsets using the SizeRequirements uility
// methods.
SizeRequirements.calculateTiledPositions(targetSpan, null, childReqs,
offsets, spans);
-
validateLayout(axis);
}
@@ -623,26 +556,21 @@ public class BoxView
* to layout the children
* @param axis the axis along which the layout is performed
* @param offsets the array that holds the offsets of the children on exit
- * @param offsets the array that holds the spans of the children on exit
+ * @param spans the array that holds the spans of the children on exit
*/
protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets,
int[] spans)
{
- // Allocate SizeRequirements for each child view.
- int count = getViewCount();
- SizeRequirements[] childReqs = new SizeRequirements[count];
- for (int i = 0; i < count; ++i)
- {
- View view = getView(i);
- childReqs[i] = new SizeRequirements((int) view.getMinimumSpan(axis),
- (int) view.getPreferredSpan(axis),
- (int) view.getMaximumSpan(axis),
- view.getAlignment(axis));
- }
-
+ SizeRequirements[] childReqs = getChildRequirements(axis);
// Calculate the spans and offsets using the SizeRequirements uility
// methods.
- SizeRequirements.calculateAlignedPositions(targetSpan, null, childReqs,
+ // TODO: This might be an opportunity for performance optimization. Here
+ // we could use a cached instance of SizeRequirements instead of passing
+ // null to baselineRequirements. However, this would involve rewriting
+ // the baselineRequirements() method to not use the SizeRequirements
+ // utility method, since they cannot reuse a cached instance.
+ SizeRequirements total = baselineRequirements(axis, null);
+ SizeRequirements.calculateAlignedPositions(targetSpan, total, childReqs,
offsets, spans);
validateLayout(axis);
}
@@ -692,6 +620,9 @@ public class BoxView
layoutChanged(X_AXIS);
if (this.height != (int) height)
layoutChanged(Y_AXIS);
+
+ this.width = (int) width;
+ this.height = (int) height;
Rectangle outside = new Rectangle(0, 0, this.width, this.height);
Rectangle inside = getInsideAllocation(outside);
@@ -711,4 +642,99 @@ public class BoxView
if (axis == Y_AXIS)
yLayoutValid = true;
}
+
+ /**
+ * Returns the size requirements of this view's children for the major
+ * axis.
+ *
+ * @return the size requirements of this view's children for the major
+ * axis
+ */
+ SizeRequirements[] getChildRequirements(int axis)
+ {
+ // Allocate SizeRequirements for each child view.
+ int count = getViewCount();
+ SizeRequirements[] childReqs = new SizeRequirements[count];
+ for (int i = 0; i < count; ++i)
+ {
+ View view = getView(i);
+ childReqs[i] = new SizeRequirements((int) view.getMinimumSpan(axis),
+ (int) view.getPreferredSpan(axis),
+ (int) view.getMaximumSpan(axis),
+ view.getAlignment(axis));
+ }
+ return childReqs;
+ }
+
+ /**
+ * Returns the span for the child view with the given index for the specified
+ * axis.
+ *
+ * @param axis the axis to examine, either <code>X_AXIS</code> or
+ * <code>Y_AXIS</code>
+ * @param childIndex the index of the child for for which to return the span
+ *
+ * @return the span for the child view with the given index for the specified
+ * axis
+ */
+ protected int getSpan(int axis, int childIndex)
+ {
+ if (axis == X_AXIS)
+ return spansX[childIndex];
+ else
+ return spansY[childIndex];
+ }
+
+ /**
+ * Returns the offset for the child view with the given index for the
+ * specified axis.
+ *
+ * @param axis the axis to examine, either <code>X_AXIS</code> or
+ * <code>Y_AXIS</code>
+ * @param childIndex the index of the child for for which to return the span
+ *
+ * @return the offset for the child view with the given index for the
+ * specified axis
+ */
+ protected int getOffset(int axis, int childIndex)
+ {
+ if (axis == X_AXIS)
+ return offsetsX[childIndex];
+ else
+ return offsetsY[childIndex];
+ }
+
+ /**
+ * Returns the alignment for this box view for the specified axis. The
+ * axis that is tiled (the major axis) will be requested to be aligned
+ * centered (0.5F). The minor axis alignment depends on the child view's
+ * total alignment.
+ *
+ * @param axis the axis which is examined
+ *
+ * @return the alignment for this box view for the specified axis
+ */
+ public float getAlignment(int axis)
+ {
+ if (axis == myAxis)
+ return 0.5F;
+ else
+ return baselineRequirements(axis, null).alignment;
+ }
+
+ /**
+ * Called by a child View when its preferred span has changed.
+ *
+ * @param width indicates that the preferred width of the child changed.
+ * @param height indicates that the preferred height of the child changed.
+ * @param child the child View.
+ */
+ public void preferenceChanged (View child, boolean width, boolean height)
+ {
+ if (width)
+ xLayoutValid = false;
+ if (height)
+ yLayoutValid = false;
+ super.preferenceChanged(child, width, height);
+ }
}
diff --git a/libjava/classpath/javax/swing/text/ComponentView.java b/libjava/classpath/javax/swing/text/ComponentView.java
index f6feda21513..16112c8f4de 100644
--- a/libjava/classpath/javax/swing/text/ComponentView.java
+++ b/libjava/classpath/javax/swing/text/ComponentView.java
@@ -1,5 +1,5 @@
/* ComponentView.java --
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,65 +41,125 @@ import java.awt.Component;
import java.awt.Graphics;
import java.awt.Shape;
+import javax.swing.SwingConstants;
+
+/**
+ * A {@link View} implementation that is able to render arbitrary
+ * {@link Component}s. This uses the attribute
+ * {@link StyleConstants#ComponentAttribute} to determine the
+ * <code>Component</code> that should be rendered. This <code>Component</code>
+ * becomes a direct child of the <code>JTextComponent</code> that contains
+ * this <code>ComponentView</code>, so this view must not be shared between
+ * multiple <code>JTextComponent</code>s.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman@kennke.org)
+ */
+// FIXME: This class is a complete stub and needs to be implemented properly.
public class ComponentView extends View
{
- public ComponentView(Element elem)
- {
- super(elem);
- }
-
- protected Component createComponent()
- {
- return null;
- }
-
- public float getAlignment(int axis)
- {
- return 0;
- }
-
- public final Component getComponent()
- {
- return null;
- }
-
- public float getMaximumSpan(int axis)
- {
- return 0;
- }
-
- public float getMinimumSpan(int axis)
- {
- return 0;
- }
-
- public float getPreferredSpan(int axis)
- {
- return 0;
- }
-
- public Shape modelToView(int pos, Shape a, Position.Bias b)
- throws BadLocationException
- {
- return null;
- }
-
- public void paint(Graphics g, Shape a)
- {
- }
+ /**
+ * Creates a new instance of <code>ComponentView</code> for the specified
+ * <code>Element</code>.
+ *
+ * @param elem the element that this <code>View</code> is rendering
+ */
+ public ComponentView(Element elem)
+ {
+ super(elem);
+ }
+
+ /**
+ * Creates the <code>Component</code> that this <code>View</code> is
+ * rendering. The <code>Component</code> is determined using
+ * the {@link StyleConstants#ComponentAttribute} of the associated
+ * <code>Element</code>.
+ *
+ * @return the component that is rendered
+ */
+ protected Component createComponent()
+ {
+ return StyleConstants.getComponent(getElement().getAttributes());
+ }
+
+ /**
+ * Returns the alignment of this <code>View</code> along the specified axis.
+ *
+ * @param axis either {@link View#X_AXIS} or {@link View#Y_AXIS}
+ *
+ * @return the alignment of this <code>View</code> along the specified axis
+ */
+ public float getAlignment(int axis)
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the <code>Component</code> that is rendered by this
+ * <code>ComponentView</code>.
+ *
+ * @return the <code>Component</code> that is rendered by this
+ * <code>ComponentView</code>
+ */
+ public final Component getComponent()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the maximum span of this <code>View</code> along the specified
+ * axis.
+ *
+ * This will return {@link Component#getMaximumSize()} for the specified
+ * axis.
+ *
+ * @return the maximum span of this <code>View</code> along the specified
+ * axis
+ */
+ public float getMaximumSpan(int axis)
+ {
+ return 0;
+ }
+
+ public float getMinimumSpan(int axis)
+ {
+ // TODO: Implement this properly.
+ return 0;
+ }
+
+ public float getPreferredSpan(int axis)
+ {
+ // TODO: Implement this properly.
+ return 0;
+ }
+
+ public Shape modelToView(int pos, Shape a, Position.Bias b)
+ throws BadLocationException
+ {
+ // TODO: Implement this properly.
+ return null;
+ }
- public void setParent(View p)
- {
- }
+ public void paint(Graphics g, Shape a)
+ {
+ // TODO: Implement this properly.
+ }
+
+ public void setParent(View p)
+ {
+ // TODO: Implement this properly.
+ }
- public void setSize(float width, float height)
- {
- }
+ public void setSize(float width, float height)
+ {
+ // TODO: Implement this properly.
+ }
- public int viewToModel(float x, float y, Shape a, Position.Bias[] bias)
- {
- return 0;
- }
+ public int viewToModel(float x, float y, Shape a, Position.Bias[] bias)
+ {
+ // TODO: Implement this properly.
+ return 0;
+ }
/**
* Maps coordinates from the <code>View</code>'s space into a position
@@ -118,4 +178,34 @@ public class ComponentView extends View
// FIXME: Implement this properly.
return 0;
}
+
+ /**
+ * Returns the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction <code>d</code>.
+ *
+ * @param c the text component
+ * @param pos the document position
+ * @param b the bias for <code>pos</code>
+ * @param d the direction, must be either {@link SwingConstants#NORTH},
+ * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
+ * {@link SwingConstants#EAST}
+ * @param biasRet an array of {@link Position.Bias} that can hold at least
+ * one element, which is filled with the bias of the return position
+ * on method exit
+ *
+ * @return the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction
+ * <code>d</code>
+ *
+ * @throws BadLocationException if <code>pos</code> is not a valid offset in
+ * the document model
+ */
+ public int getNextVisualPositionFrom(JTextComponent c, int pos,
+ Position.Bias b, int d,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ // TODO: Implement this properly.
+ throw new AssertionError("Not implemented yet.");
+ }
}
diff --git a/libjava/classpath/javax/swing/text/CompositeView.java b/libjava/classpath/javax/swing/text/CompositeView.java
index 6776c95727a..bc626a40696 100644
--- a/libjava/classpath/javax/swing/text/CompositeView.java
+++ b/libjava/classpath/javax/swing/text/CompositeView.java
@@ -62,7 +62,7 @@ public abstract class CompositeView
/**
* The allocation of this <code>View</code> minus its insets. This is
* initialized in {@link #getInsideAllocation} and reused and modified in
- * {@link childAllocation}.
+ * {@link #childAllocation(int, Rectangle)}.
*/
Rectangle insideAllocation;
@@ -221,20 +221,17 @@ public abstract class CompositeView
if (childIndex != -1)
{
View child = getView(childIndex);
- Shape result = child.modelToView(pos, a, bias);
+ Rectangle r = a.getBounds();
+ childAllocation(childIndex, r);
+ Shape result = child.modelToView(pos, r, bias);
if (result == null)
throw new AssertionError("" + child.getClass().getName()
+ ".modelToView() must not return null");
return result;
}
else
- {
- // FIXME: Handle the case when we have no child view for the given
- // position.
- throw new AssertionError("No child views found where child views are "
- + "expected. pos = " + pos + ", bias = "
- + bias);
- }
+ throw new BadLocationException("No child view for the specified location",
+ pos);
}
/**
@@ -314,6 +311,7 @@ public abstract class CompositeView
*/
public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a,
int direction, Position.Bias[] biasRet)
+ throws BadLocationException
{
int retVal = -1;
switch (direction)
@@ -433,10 +431,16 @@ public abstract class CompositeView
*/
protected int getViewIndexAtPosition(int pos)
{
- // We have one child view allocated for each child element in
- // loadChildren(), so this should work.
- Element el = getElement();
- int index = el.getElementIndex(pos);
+ int index = -1;
+ for (int i = 0; i < children.length; i++)
+ {
+ if (children[i].getStartOffset() <= pos
+ && children[i].getEndOffset() > pos)
+ {
+ index = i;
+ break;
+ }
+ }
return index;
}
@@ -473,8 +477,8 @@ public abstract class CompositeView
insideAllocation = inside;
}
}
- inside.x = alloc.x - insets.left;
- inside.y = alloc.y - insets.top;
+ inside.x = alloc.x + insets.left;
+ inside.y = alloc.y + insets.top;
inside.width = alloc.width - insets.left - insets.right;
inside.height = alloc.height - insets.top - insets.bottom;
return inside;
@@ -594,6 +598,7 @@ public abstract class CompositeView
protected int getNextNorthSouthVisualPositionFrom(int pos, Position.Bias b,
Shape a, int direction,
Position.Bias[] biasRet)
+ throws BadLocationException
{
// FIXME: Implement this correctly.
return pos;
@@ -627,6 +632,7 @@ public abstract class CompositeView
protected int getNextEastWestVisualPositionFrom(int pos, Position.Bias b,
Shape a, int direction,
Position.Bias[] biasRet)
+ throws BadLocationException
{
// FIXME: Implement this correctly.
return pos;
@@ -649,4 +655,34 @@ public abstract class CompositeView
{
return false;
}
+
+ /**
+ * Returns the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction <code>d</code>.
+ *
+ * @param c the text component
+ * @param pos the document position
+ * @param b the bias for <code>pos</code>
+ * @param d the direction, must be either {@link SwingConstants#NORTH},
+ * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
+ * {@link SwingConstants#EAST}
+ * @param biasRet an array of {@link Position.Bias} that can hold at least
+ * one element, which is filled with the bias of the return position
+ * on method exit
+ *
+ * @return the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction
+ * <code>d</code>
+ *
+ * @throws BadLocationException if <code>pos</code> is not a valid offset in
+ * the document model
+ */
+ public int getNextVisualPositionFrom(JTextComponent c, int pos,
+ Position.Bias b, int d,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ // TODO: Implement this properly.
+ throw new AssertionError("Not implemented yet.");
+ }
}
diff --git a/libjava/classpath/javax/swing/text/DefaultCaret.java b/libjava/classpath/javax/swing/text/DefaultCaret.java
index 33c3ae3bf28..66e2f4723cf 100644
--- a/libjava/classpath/javax/swing/text/DefaultCaret.java
+++ b/libjava/classpath/javax/swing/text/DefaultCaret.java
@@ -40,15 +40,24 @@ package javax.swing.text;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.util.EventListener;
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
import javax.swing.event.EventListenerList;
/**
@@ -60,12 +69,164 @@ import javax.swing.event.EventListenerList;
public class DefaultCaret extends Rectangle
implements Caret, FocusListener, MouseListener, MouseMotionListener
{
+
+ /**
+ * Controls the blinking of the caret.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
+ */
+ private class BlinkTimerListener implements ActionListener
+ {
+ /**
+ * Forces the next event to be ignored. The next event should be ignored
+ * if we force the caret to appear. We do not know how long will it take
+ * to fire the comming event; this may be near immediately. Better to leave
+ * the caret visible one iteration longer.
+ */
+ boolean ignoreNextEvent;
+
+ /**
+ * Receives notification when the blink timer fires and updates the visible
+ * state of the caret.
+ *
+ * @param event the action event
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ if (ignoreNextEvent)
+ ignoreNextEvent = false;
+ else
+ {
+ visible = !visible;
+ repaint();
+ }
+ }
+ }
+
+ /**
+ * Listens for changes in the text component's document and updates the
+ * caret accordingly.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class DocumentHandler implements DocumentListener
+ {
+ /**
+ * Receives notification that some text attributes have changed. No action
+ * is taken here.
+ *
+ * @param event the document event
+ */
+ public void changedUpdate(DocumentEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Receives notification that some text has been inserted from the text
+ * component. The caret is moved forward accordingly.
+ *
+ * @param event the document event
+ */
+ public void insertUpdate(DocumentEvent event)
+ {
+ if (policy == ALWAYS_UPDATE ||
+ (SwingUtilities.isEventDispatchThread() &&
+ policy == UPDATE_WHEN_ON_EDT))
+ {
+ int dot = getDot();
+ setDot(dot + event.getLength());
+ }
+ }
+
+ /**
+ * Receives notification that some text has been removed into the text
+ * component. The caret is moved backwards accordingly.
+ *
+ * @param event the document event
+ */
+ public void removeUpdate(DocumentEvent event)
+ {
+ if (policy == ALWAYS_UPDATE ||
+ (SwingUtilities.isEventDispatchThread() &&
+ policy == UPDATE_WHEN_ON_EDT))
+ {
+ int dot = getDot();
+ setDot(dot - event.getLength());
+ }
+ else if (policy == NEVER_UPDATE)
+ {
+ int docLength = event.getDocument().getLength();
+ if (getDot() > docLength)
+ setDot(docLength);
+ }
+ }
+ }
+
+ /**
+ * Listens for property changes on the text document. This is used to add and
+ * remove our document listener, if the document of the text component has
+ * changed.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class PropertyChangeHandler implements PropertyChangeListener
+ {
+
+ /**
+ * Receives notification when a property has changed on the text component.
+ * This adds/removes our document listener from the text component's
+ * document when the document changes.
+ *
+ * @param e the property change event
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals("document"))
+ {
+ Document oldDoc = (Document) e.getOldValue();
+ oldDoc.removeDocumentListener(documentListener);
+ Document newDoc = (Document) e.getNewValue();
+ newDoc.addDocumentListener(documentListener);
+ }
+ }
+
+ }
+
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 4325555698756477346L;
+
/**
- * The serial version UID for DefaultCaret.
+ * Indicates the Caret position should always be updated after Document
+ * changes even if the updates are not performed on the Event Dispatching
+ * thread.
+ *
+ * @since 1.5
*/
- private static final long serialVersionUID = 228155774675466193L;
+ public static final int ALWAYS_UPDATE = 2;
/**
+ * Indicates the Caret position should not be changed unless the Document
+ * length becomes less than the Caret position, in which case the Caret
+ * is moved to the end of the Document.
+ *
+ * @since 1.5
+ */
+ public static final int NEVER_UPDATE = 1;
+
+ /**
+ * Indicates the Caret position should be updated only if Document changes
+ * are made on the Event Dispatcher thread.
+ *
+ * @since 1.5
+ */
+ public static final int UPDATE_WHEN_ON_EDT = 0;
+
+ /** Keeps track of the current update policy **/
+ int policy = UPDATE_WHEN_ON_EDT;
+
+ /**
* The <code>ChangeEvent</code> that is fired by {@link #fireStateChanged()}.
*/
protected ChangeEvent changeEvent = new ChangeEvent(this);
@@ -76,6 +237,16 @@ public class DefaultCaret extends Rectangle
protected EventListenerList listenerList = new EventListenerList();
/**
+ * Our document listener.
+ */
+ DocumentListener documentListener;
+
+ /**
+ * Our property listener.
+ */
+ PropertyChangeListener propertyChangeListener;
+
+ /**
* The text component in which this caret is installed.
*/
private JTextComponent textComponent;
@@ -106,15 +277,65 @@ public class DefaultCaret extends Rectangle
private Point magicCaretPosition = null;
/**
- * Indicates if this <code>Caret</code> is currently visible or not.
+ * Indicates if this <code>Caret</code> is currently visible or not. This is
+ * package private to avoid an accessor method.
*/
- private boolean visible = true;
+ boolean visible = false;
/**
* The current highlight entry.
*/
private Object highlightEntry;
+ private Timer blinkTimer;
+
+ private BlinkTimerListener blinkListener;
+
+ /**
+ * Creates a new <code>DefaultCaret</code> instance.
+ */
+ public DefaultCaret()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Sets the Caret update policy.
+ *
+ * @param policy the new policy. Valid values are:
+ * ALWAYS_UPDATE: always update the Caret position, even when Document
+ * updates don't occur on the Event Dispatcher thread.
+ * NEVER_UPDATE: don't update the Caret position unless the Document
+ * length becomes less than the Caret position (then update the
+ * Caret to the end of the Document).
+ * UPDATE_WHEN_ON_EDT: update the Caret position when the
+ * Document updates occur on the Event Dispatcher thread. This is the
+ * default.
+ *
+ * @since 1.5
+ * @throws IllegalArgumentException if policy is not one of the above.
+ */
+ public void setUpdatePolicy (int policy)
+ {
+ if (policy != ALWAYS_UPDATE && policy != NEVER_UPDATE
+ && policy != UPDATE_WHEN_ON_EDT)
+ throw new
+ IllegalArgumentException
+ ("policy must be ALWAYS_UPDATE, NEVER__UPDATE, or UPDATE_WHEN_ON_EDT");
+ this.policy = policy;
+ }
+
+ /**
+ * Gets the caret update policy.
+ *
+ * @return the caret update policy.
+ * @since 1.5
+ */
+ public int getUpdatePolicy ()
+ {
+ return policy;
+ }
+
/**
* Moves the caret position when the mouse is dragged over the text
* component, modifying the selection accordingly.
@@ -123,7 +344,7 @@ public class DefaultCaret extends Rectangle
*/
public void mouseDragged(MouseEvent event)
{
- // FIXME: Implement this properly.
+ moveCaret(event);
}
/**
@@ -153,7 +374,7 @@ public class DefaultCaret extends Rectangle
*/
public void mouseClicked(MouseEvent event)
{
- // FIXME: Implement this properly.
+ // TODO: Implement double- and triple-click behaviour here.
}
/**
@@ -175,6 +396,7 @@ public class DefaultCaret extends Rectangle
*/
public void mouseExited(MouseEvent event)
{
+ // Nothing to do here.
}
/**
@@ -187,7 +409,7 @@ public class DefaultCaret extends Rectangle
*/
public void mousePressed(MouseEvent event)
{
- // FIXME: Implement this properly.
+ positionCaret(event);
}
/**
@@ -208,6 +430,7 @@ public class DefaultCaret extends Rectangle
*/
public void focusGained(FocusEvent event)
{
+ setVisible(true);
}
/**
@@ -217,6 +440,8 @@ public class DefaultCaret extends Rectangle
*/
public void focusLost(FocusEvent event)
{
+ if (event.isTemporary() == false)
+ setVisible(false);
}
/**
@@ -227,7 +452,8 @@ public class DefaultCaret extends Rectangle
*/
protected void moveCaret(MouseEvent event)
{
- // FIXME: Implement this properly.
+ int newDot = getComponent().viewToModel(event.getPoint());
+ moveDot(newDot);
}
/**
@@ -238,7 +464,8 @@ public class DefaultCaret extends Rectangle
*/
protected void positionCaret(MouseEvent event)
{
- // FIXME: Implement this properly.
+ int newDot = getComponent().viewToModel(event.getPoint());
+ setDot(newDot);
}
/**
@@ -253,7 +480,16 @@ public class DefaultCaret extends Rectangle
textComponent.removeFocusListener(this);
textComponent.removeMouseListener(this);
textComponent.removeMouseMotionListener(this);
+ textComponent.getDocument().removeDocumentListener(documentListener);
+ documentListener = null;
+ textComponent.removePropertyChangeListener(propertyChangeListener);
+ propertyChangeListener = null;
textComponent = null;
+
+ // Deinstall blink timer if present.
+ if (blinkTimer != null)
+ blinkTimer.stop();
+ blinkTimer = null;
}
/**
@@ -269,6 +505,11 @@ public class DefaultCaret extends Rectangle
textComponent.addFocusListener(this);
textComponent.addMouseListener(this);
textComponent.addMouseMotionListener(this);
+ propertyChangeListener = new PropertyChangeHandler();
+ textComponent.addPropertyChangeListener(propertyChangeListener);
+ documentListener = new DocumentHandler();
+ textComponent.getDocument().addDocumentListener(documentListener);
+
repaint();
}
@@ -376,10 +617,7 @@ public class DefaultCaret extends Rectangle
*/
protected final void repaint()
{
- // FIXME: Is this good? This possibly causes alot of the component
- // hierarchy to be repainted on every caret blink.
- if (textComponent != null)
- textComponent.repaint();
+ getComponent().repaint(x, y, width, height);
}
/**
@@ -390,7 +628,8 @@ public class DefaultCaret extends Rectangle
*/
public void paint(Graphics g)
{
- if (textComponent == null)
+ JTextComponent comp = getComponent();
+ if (comp == null)
return;
int dot = getDot();
@@ -398,25 +637,33 @@ public class DefaultCaret extends Rectangle
try
{
- rect = textComponent.modelToView(dot);
+ rect = textComponent.modelToView(dot);
}
catch (BadLocationException e)
{
- // This should never happen as dot should be always valid.
- return;
+ assert false : "Unexpected bad caret location: " + dot;
+ return;
}
if (rect == null)
return;
-
- // First we need to delete the old caret.
- // FIXME: Implement deleting of old caret.
-
+
+ // Check if paint has possibly been called directly, without a previous
+ // call to damage(). In this case we need to do some cleanup first.
+ if ((x != rect.x) || (y != rect.y))
+ {
+ repaint(); // Erase previous location of caret.
+ x = rect.x;
+ y = rect.y;
+ width = 1;
+ height = rect.height;
+ }
+
// Now draw the caret on the new position if visible.
if (visible)
{
- g.setColor(textComponent.getCaretColor());
- g.drawLine(rect.x, rect.y, rect.x, rect.y + rect.height);
+ g.setColor(textComponent.getCaretColor());
+ g.drawLine(rect.x, rect.y, rect.x, rect.y + rect.height);
}
}
@@ -507,6 +754,8 @@ public class DefaultCaret extends Rectangle
*/
public void setBlinkRate(int rate)
{
+ if (blinkTimer != null)
+ blinkTimer.setDelay(rate);
blinkRate = rate;
}
@@ -534,7 +783,8 @@ public class DefaultCaret extends Rectangle
{
this.dot = dot;
handleHighlight();
- repaint();
+ adjustVisibility(this);
+ appear();
}
/**
@@ -551,8 +801,45 @@ public class DefaultCaret extends Rectangle
this.dot = dot;
this.mark = dot;
handleHighlight();
- repaint();
+ adjustVisibility(this);
+ appear();
}
+
+ /**
+ * Show the caret (may be hidden due blinking) and adjust the timer not to
+ * hide it (possibly immediately).
+ *
+ * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
+ */
+ void appear()
+ {
+ // All machinery is only required if the carret is blinking.
+ if (blinkListener != null)
+ {
+ blinkListener.ignoreNextEvent = true;
+
+ // If the caret is visible, erase the current position by repainting
+ // over.
+ if (visible)
+ repaint();
+
+ // Draw the caret in the new position.
+ visible = true;
+
+ Rectangle area = null;
+ try
+ {
+ area = getComponent().modelToView(getDot());
+ }
+ catch (BadLocationException ex)
+ {
+ assert false : "Unexpected bad caret location: " + getDot();
+ }
+ if (area != null)
+ damage(area);
+ }
+ repaint();
+ }
/**
* Returns <code>true</code> if this <code>Caret</code> is currently visible,
@@ -574,8 +861,33 @@ public class DefaultCaret extends Rectangle
*/
public void setVisible(boolean v)
{
- visible = v;
- repaint();
+ if (v != visible)
+ {
+ visible = v;
+ if (visible)
+ if (textComponent.isEnabled() && textComponent.isEditable())
+ {
+ if (blinkTimer == null)
+ initBlinkTimer();
+ blinkTimer.start();
+ }
+ else
+ {
+ if (blinkTimer != null)
+ blinkTimer.stop();
+ }
+ Rectangle area = null;
+ try
+ {
+ area = getComponent().modelToView(getDot());
+ }
+ catch (BadLocationException ex)
+ {
+ assert false: "Unexpected bad caret location: " + getDot();
+ }
+ if (area != null)
+ damage(area);
+ }
}
/**
@@ -589,4 +901,47 @@ public class DefaultCaret extends Rectangle
{
return DefaultHighlighter.DefaultPainter;
}
+
+ /**
+ * Updates the carets rectangle properties to the specified rectangle and
+ * repaints the caret.
+ *
+ * @param r the rectangle to set as the caret rectangle
+ */
+ protected void damage(Rectangle r)
+ {
+ if (r == null)
+ return;
+ x = r.x;
+ y = r.y;
+ width = 1;
+ // height is normally set in paint and we leave it untouched. However, we
+ // must set a valid value here, since otherwise the painting mechanism
+ // sets a zero clip and never calls paint.
+ if (height <= 0)
+ height = getComponent().getHeight();
+ repaint();
+ }
+
+ /**
+ * Adjusts the text component so that the caret is visible. This default
+ * implementation simply calls
+ * {@link JComponent#scrollRectToVisible(Rectangle)} on the text component.
+ * Subclasses may wish to change this.
+ */
+ protected void adjustVisibility(Rectangle rect)
+ {
+ getComponent().scrollRectToVisible(rect);
+ }
+
+ /**
+ * Initializes the blink timer.
+ */
+ private void initBlinkTimer()
+ {
+ // Setup the blink timer.
+ blinkListener = new BlinkTimerListener();
+ blinkTimer = new Timer(getBlinkRate(), blinkListener);
+ blinkTimer.setRepeats(true);
+ }
}
diff --git a/libjava/classpath/javax/swing/text/DefaultEditorKit.java b/libjava/classpath/javax/swing/text/DefaultEditorKit.java
index a14f3ff4fe0..3b3fc1f7238 100644
--- a/libjava/classpath/javax/swing/text/DefaultEditorKit.java
+++ b/libjava/classpath/javax/swing/text/DefaultEditorKit.java
@@ -66,8 +66,7 @@ public class DefaultEditorKit extends EditorKit
*
* @see Toolkit#beep()
*/
- public static class BeepAction
- extends TextAction
+ public static class BeepAction extends TextAction
{
/**
* Creates a new <code>BeepAction</code>.
@@ -95,8 +94,7 @@ public class DefaultEditorKit extends EditorKit
* @see CutAction
* @see PasteAction
*/
- public static class CopyAction
- extends TextAction
+ public static class CopyAction extends TextAction
{
/**
@@ -128,8 +126,7 @@ public class DefaultEditorKit extends EditorKit
* @see CopyAction
* @see PasteAction
*/
- public static class CutAction
- extends TextAction
+ public static class CutAction extends TextAction
{
/**
@@ -159,8 +156,7 @@ public class DefaultEditorKit extends EditorKit
* @see CopyAction
* @see CutAction
*/
- public static class PasteAction
- extends TextAction
+ public static class PasteAction extends TextAction
{
/**
@@ -226,9 +222,6 @@ public class DefaultEditorKit extends EditorKit
{
t.getDocument().insertString(t.getCaret().getDot(),
event.getActionCommand(), null);
- t.getCaret().setDot(Math.min(t.getCaret().getDot() + 1,
- t.getDocument().getEndPosition()
- .getOffset()));
}
catch (BadLocationException be)
{
@@ -243,8 +236,7 @@ public class DefaultEditorKit extends EditorKit
* of the text component. This is typically triggered by hitting
* ENTER on the keyboard.
*/
- public static class InsertBreakAction
- extends TextAction
+ public static class InsertBreakAction extends TextAction
{
/**
@@ -273,8 +265,7 @@ public class DefaultEditorKit extends EditorKit
*/
// FIXME: Figure out what this Action is supposed to do. Obviously text
// that is entered by the user is inserted through DefaultKeyTypedAction.
- public static class InsertContentAction
- extends TextAction
+ public static class InsertContentAction extends TextAction
{
/**
@@ -292,14 +283,15 @@ public class DefaultEditorKit extends EditorKit
*/
public void actionPerformed(ActionEvent event)
{
+ // FIXME: Figure out what this Action is supposed to do. Obviously text
+ // that is entered by the user is inserted through DefaultKeyTypedAction.
}
}
/**
* Inserts a TAB character into the text editor.
*/
- public static class InsertTabAction
- extends TextAction
+ public static class InsertTabAction extends TextAction
{
/**
@@ -699,6 +691,7 @@ public class DefaultEditorKit extends EditorKit
*/
public DefaultEditorKit()
{
+ // Nothing to do here.
}
/**
@@ -954,15 +947,23 @@ public class DefaultEditorKit extends EditorKit
* @param offset the beginning offset from where to write
* @param len the length of the fragment to write
*
- * @throws BadLocationException if <code>offset</code> or
- * <code>offset + len</code>is an invalid location inside
- * <code>document</code>
+ * @throws BadLocationException if <code>offset</code> is an
+ * invalid location inside <code>document</code>.
* @throws IOException if something goes wrong while writing to
* <code>out</code>
*/
public void write(Writer out, Document document, int offset, int len)
- throws BadLocationException, IOException
+ throws BadLocationException, IOException
{
- // TODO: Implement this properly.
+ // Throw a BLE if offset is invalid
+ if (offset < 0 || offset > document.getLength())
+ throw new BadLocationException("Tried to write to invalid location",
+ offset);
+
+ // If they gave an overly large len, just adjust it
+ if (offset + len > document.getLength())
+ len = document.getLength() - offset;
+
+ out.write(document.getText(offset, len));
}
}
diff --git a/libjava/classpath/javax/swing/text/DefaultFormatter.java b/libjava/classpath/javax/swing/text/DefaultFormatter.java
index c97d90703c7..f9e0f10e654 100644
--- a/libjava/classpath/javax/swing/text/DefaultFormatter.java
+++ b/libjava/classpath/javax/swing/text/DefaultFormatter.java
@@ -57,8 +57,7 @@ import javax.swing.JFormattedTextField;
*
* @author Roman Kennke (roman@kennke.org)
*/
-public class DefaultFormatter
- extends JFormattedTextField.AbstractFormatter
+public class DefaultFormatter extends JFormattedTextField.AbstractFormatter
implements Cloneable, Serializable
{
@@ -156,9 +155,6 @@ public class DefaultFormatter
* Checks if the value in the input field is valid. If the
* property allowsInvalid is set to <code>false</code>, then
* the string in the input field is not allowed to be entered.
- *
- * @param doc the document of the input field
- * @param value the current (old) value of the input field
*/
private void checkValidInput()
{
@@ -179,15 +175,18 @@ public class DefaultFormatter
catch (ParseException pe)
{
// if that happens, something serious must be wrong
- throw new AssertionError("values must be parseable");
+ AssertionError ae;
+ ae = new AssertionError("values must be parseable");
+ ae.initCause(pe);
+ throw ae;
}
}
}
}
}
- /** The serialVersoinUID. */
- private static final long serialVersionUID = -7369196326612908900L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -355018354457785329L;
/**
* Indicates if the value should be committed after every
diff --git a/libjava/classpath/javax/swing/text/DefaultHighlighter.java b/libjava/classpath/javax/swing/text/DefaultHighlighter.java
index c8d874caa51..40ea4f80aab 100644
--- a/libjava/classpath/javax/swing/text/DefaultHighlighter.java
+++ b/libjava/classpath/javax/swing/text/DefaultHighlighter.java
@@ -168,6 +168,7 @@ public class DefaultHighlighter extends LayeredHighlighter
public DefaultHighlighter()
{
+ // Nothing to do here.
}
public boolean getDrawsLayeredHighlights()
@@ -238,6 +239,7 @@ public class DefaultHighlighter extends LayeredHighlighter
Shape viewBounds, JTextComponent editor,
View view)
{
+ // TODO: Implement this properly.
}
public void paint(Graphics g)
diff --git a/libjava/classpath/javax/swing/text/DefaultStyledDocument.java b/libjava/classpath/javax/swing/text/DefaultStyledDocument.java
index 3545e52c453..eb56bb0f8e5 100644
--- a/libjava/classpath/javax/swing/text/DefaultStyledDocument.java
+++ b/libjava/classpath/javax/swing/text/DefaultStyledDocument.java
@@ -1,5 +1,5 @@
/* DefaultStyledDocument.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,8 +41,14 @@ package javax.swing.text;
import java.awt.Color;
import java.awt.Font;
import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Vector;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.UndoableEdit;
/**
* The default implementation of {@link StyledDocument}.
@@ -60,12 +66,359 @@ public class DefaultStyledDocument extends AbstractDocument
implements StyledDocument
{
/**
+ * An {@link UndoableEdit} that can undo attribute changes to an element.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ public static class AttributeUndoableEdit
+ extends AbstractUndoableEdit
+ {
+ /**
+ * A copy of the old attributes.
+ */
+ protected AttributeSet copy;
+
+ /**
+ * The new attributes.
+ */
+ protected AttributeSet newAttributes;
+
+ /**
+ * If the new attributes replaced the old attributes or if they only were
+ * added to them.
+ */
+ protected boolean isReplacing;
+
+ /**
+ * The element that has changed.
+ */
+ protected Element element;
+
+ /**
+ * Creates a new <code>AttributeUndoableEdit</code>.
+ *
+ * @param el the element that changes attributes
+ * @param newAtts the new attributes
+ * @param replacing if the new attributes replace the old or only append to
+ * them
+ */
+ public AttributeUndoableEdit(Element el, AttributeSet newAtts,
+ boolean replacing)
+ {
+ element = el;
+ newAttributes = newAtts;
+ isReplacing = replacing;
+ copy = el.getAttributes().copyAttributes();
+ }
+
+ /**
+ * Undos the attribute change. The <code>copy</code> field is set as
+ * attributes on <code>element</code>.
+ */
+ public void undo()
+ {
+ super.undo();
+ AttributeSet atts = element.getAttributes();
+ if (atts instanceof MutableAttributeSet)
+ {
+ MutableAttributeSet mutable = (MutableAttributeSet) atts;
+ mutable.removeAttributes(atts);
+ mutable.addAttributes(copy);
+ }
+ }
+
+ /**
+ * Redos an attribute change. This adds <code>newAttributes</code> to the
+ * <code>element</code>'s attribute set, possibly clearing all attributes
+ * if <code>isReplacing</code> is true.
+ */
+ public void redo()
+ {
+ super.undo();
+ AttributeSet atts = element.getAttributes();
+ if (atts instanceof MutableAttributeSet)
+ {
+ MutableAttributeSet mutable = (MutableAttributeSet) atts;
+ if (isReplacing)
+ mutable.removeAttributes(atts);
+ mutable.addAttributes(newAttributes);
+ }
+ }
+ }
+
+ /**
+ * Carries specification information for new {@link Element}s that should
+ * be created in {@link ElementBuffer}. This allows the parsing process
+ * to be decoupled from the <code>Element</code> creation process.
+ */
+ public static class ElementSpec
+ {
+ /**
+ * This indicates a start tag. This is a possible value for
+ * {@link #getType}.
+ */
+ public static final short StartTagType = 1;
+
+ /**
+ * This indicates an end tag. This is a possible value for
+ * {@link #getType}.
+ */
+ public static final short EndTagType = 2;
+
+ /**
+ * This indicates a content element. This is a possible value for
+ * {@link #getType}.
+ */
+ public static final short ContentType = 3;
+
+ /**
+ * This indicates that the data associated with this spec should be joined
+ * with what precedes it. This is a possible value for
+ * {@link #getDirection}.
+ */
+ public static final short JoinPreviousDirection = 4;
+
+ /**
+ * This indicates that the data associated with this spec should be joined
+ * with what follows it. This is a possible value for
+ * {@link #getDirection}.
+ */
+ public static final short JoinNextDirection = 5;
+
+ /**
+ * This indicates that the data associated with this spec should be used
+ * to create a new element. This is a possible value for
+ * {@link #getDirection}.
+ */
+ public static final short OriginateDirection = 6;
+
+ /**
+ * This indicates that the data associated with this spec should be joined
+ * to the fractured element. This is a possible value for
+ * {@link #getDirection}.
+ */
+ public static final short JoinFractureDirection = 7;
+
+ /**
+ * The type of the tag.
+ */
+ short type;
+
+ /**
+ * The direction of the tag.
+ */
+ short direction;
+
+ /**
+ * The offset of the content.
+ */
+ int offset;
+
+ /**
+ * The length of the content.
+ */
+ int length;
+
+ /**
+ * The actual content.
+ */
+ char[] content;
+
+ /**
+ * The attributes for the tag.
+ */
+ AttributeSet attributes;
+
+ /**
+ * Creates a new <code>ElementSpec</code> with no content, length or
+ * offset. This is most useful for start and end tags.
+ *
+ * @param a the attributes for the element to be created
+ * @param type the type of the tag
+ */
+ public ElementSpec(AttributeSet a, short type)
+ {
+ this(a, type, 0);
+ }
+
+ /**
+ * Creates a new <code>ElementSpec</code> that specifies the length but
+ * not the offset of an element. Such <code>ElementSpec</code>s are
+ * processed sequentially from a known starting point.
+ *
+ * @param a the attributes for the element to be created
+ * @param type the type of the tag
+ * @param len the length of the element
+ */
+ public ElementSpec(AttributeSet a, short type, int len)
+ {
+ this(a, type, null, 0, len);
+ }
+
+ /**
+ * Creates a new <code>ElementSpec</code> with document content.
+ *
+ * @param a the attributes for the element to be created
+ * @param type the type of the tag
+ * @param txt the actual content
+ * @param offs the offset into the <code>txt</code> array
+ * @param len the length of the element
+ */
+ public ElementSpec(AttributeSet a, short type, char[] txt, int offs,
+ int len)
+ {
+ attributes = a;
+ this.type = type;
+ offset = offs;
+ length = len;
+ content = txt;
+ direction = OriginateDirection;
+ }
+
+ /**
+ * Sets the type of the element.
+ *
+ * @param type the type of the element to be set
+ */
+ public void setType(short type)
+ {
+ this.type = type;
+ }
+
+ /**
+ * Returns the type of the element.
+ *
+ * @return the type of the element
+ */
+ public short getType()
+ {
+ return type;
+ }
+
+ /**
+ * Sets the direction of the element.
+ *
+ * @param dir the direction of the element to be set
+ */
+ public void setDirection(short dir)
+ {
+ direction = dir;
+ }
+
+ /**
+ * Returns the direction of the element.
+ *
+ * @return the direction of the element
+ */
+ public short getDirection()
+ {
+ return direction;
+ }
+
+ /**
+ * Returns the attributes of the element.
+ *
+ * @return the attributes of the element
+ */
+ public AttributeSet getAttributes()
+ {
+ return attributes;
+ }
+
+ /**
+ * Returns the actual content of the element.
+ *
+ * @return the actual content of the element
+ */
+ public char[] getArray()
+ {
+ return content;
+ }
+
+ /**
+ * Returns the offset of the content.
+ *
+ * @return the offset of the content
+ */
+ public int getOffset()
+ {
+ return offset;
+ }
+
+ /**
+ * Returns the length of the content.
+ *
+ * @return the length of the content
+ */
+ public int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * Returns a String representation of this <code>ElementSpec</code>
+ * describing the type, direction and length of this
+ * <code>ElementSpec</code>.
+ *
+ * @return a String representation of this <code>ElementSpec</code>
+ */
+ public String toString()
+ {
+ StringBuilder b = new StringBuilder();
+ b.append('<');
+ switch (type)
+ {
+ case StartTagType:
+ b.append("StartTag");
+ break;
+ case EndTagType:
+ b.append("EndTag");
+ break;
+ case ContentType:
+ b.append("Content");
+ break;
+ default:
+ b.append("??");
+ break;
+ }
+
+ b.append(':');
+
+ switch (direction)
+ {
+ case JoinPreviousDirection:
+ b.append("JoinPrevious");
+ break;
+ case JoinNextDirection:
+ b.append("JoinNext");
+ break;
+ case OriginateDirection:
+ b.append("Originate");
+ break;
+ case JoinFractureDirection:
+ b.append("Fracture");
+ break;
+ default:
+ b.append("??");
+ break;
+ }
+
+ b.append(':');
+ b.append(length);
+
+ return b.toString();
+ }
+ }
+
+ /**
* Performs all <em>structural</code> changes to the <code>Element</code>
* hierarchy.
*/
- public class ElementBuffer
- implements Serializable
+ public class ElementBuffer implements Serializable
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 1688745877691146623L;
+
/** The root element of the hierarchy. */
private Element root;
@@ -76,6 +429,19 @@ public class DefaultStyledDocument extends AbstractDocument
private int length;
/**
+ * Holds fractured elements during insertion of end and start tags.
+ * Inserting an end tag may lead to fracturing of the current paragraph
+ * element. The elements that have been cut off may be added to the
+ * next paragraph that is created in the next start tag.
+ */
+ Element[] fracture;
+
+ /**
+ * The ElementChange that describes the latest changes.
+ */
+ DefaultDocumentEvent documentEvent;
+
+ /**
* Creates a new <code>ElementBuffer</code> for the specified
* <code>root</code> element.
*
@@ -114,6 +480,7 @@ public class DefaultStyledDocument extends AbstractDocument
{
this.offset = offset;
this.length = length;
+ documentEvent = ev;
changeUpdate();
}
@@ -142,38 +509,352 @@ public class DefaultStyledDocument extends AbstractDocument
void split(Element el, int offset)
{
if (el instanceof AbstractElement)
- {
- AbstractElement ael = (AbstractElement) el;
- int startOffset = ael.getStartOffset();
- int endOffset = ael.getEndOffset();
- int len = endOffset - startOffset;
- if (startOffset != offset && endOffset != offset)
- {
- Element paragraph = ael.getParentElement();
- if (paragraph instanceof BranchElement)
- {
- BranchElement par = (BranchElement) paragraph;
- Element child1 = createLeafElement(par, ael, startOffset,
- offset);
- Element child2 = createLeafElement(par, ael, offset,
- endOffset);
- int index = par.getElementIndex(startOffset);
- par.replace(index, 1, new Element[]{ child1, child2 });
- }
+ {
+ AbstractElement ael = (AbstractElement) el;
+ int startOffset = ael.getStartOffset();
+ int endOffset = ael.getEndOffset();
+ int len = endOffset - startOffset;
+ if (startOffset != offset && endOffset != offset)
+ {
+ Element paragraph = ael.getParentElement();
+ if (paragraph instanceof BranchElement)
+ {
+ BranchElement par = (BranchElement) paragraph;
+ Element child1 = createLeafElement(par, ael, startOffset,
+ offset);
+ Element child2 = createLeafElement(par, ael, offset,
+ endOffset);
+ int index = par.getElementIndex(startOffset);
+ Element[] add = new Element[]{ child1, child2 };
+ par.replace(index, 1, add);
+ documentEvent.addEdit(new ElementEdit(par, index,
+ new Element[]{ el },
+ add));
+ }
else
throw new AssertionError("paragraph elements are expected to "
+ "be instances of "
+ "javax.swing.text.AbstractDocument.BranchElement");
- }
- }
+ }
+ }
else
- throw new AssertionError("content elements are expected to be "
- + "instances of "
+ throw new AssertionError("content elements are expected to be "
+ + "instances of "
+ "javax.swing.text.AbstractDocument.AbstractElement");
}
+
+ /**
+ * Inserts new <code>Element</code> in the document at the specified
+ * position.
+ *
+ * Most of the work is done by {@link #insertUpdate}, after some fields
+ * have been prepared for it.
+ *
+ * @param offset the location in the document at which the content is
+ * inserted
+ * @param length the length of the inserted content
+ * @param data the element specifications for the content to be inserted
+ * @param ev the document event that is updated to reflect the structural
+ * changes
+ */
+ public void insert(int offset, int length, ElementSpec[] data,
+ DefaultDocumentEvent ev)
+ {
+ this.offset = offset;
+ this.length = length;
+ documentEvent = ev;
+ insertUpdate(data);
+ }
+
+ /**
+ * Performs the actual structural change for {@link #insert}. This
+ * creates a bunch of {@link Element}s as specified by <code>data</code>
+ * and inserts it into the document as specified in the arguments to
+ * {@link #insert}.
+ *
+ * @param data the element specifications for the elements to be inserte
+ */
+ protected void insertUpdate(ElementSpec[] data)
+ {
+ for (int i = 0; i < data.length; i++)
+ {
+ switch (data[i].getType())
+ {
+ case ElementSpec.StartTagType:
+ insertStartTag(data[i]);
+ break;
+ case ElementSpec.EndTagType:
+ insertEndTag(data[i]);
+ break;
+ default:
+ insertContentTag(data[i]);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Insert a new paragraph after the paragraph at the current position.
+ *
+ * @param tag the element spec that describes the element to be inserted
+ */
+ void insertStartTag(ElementSpec tag)
+ {
+ BranchElement root = (BranchElement) getDefaultRootElement();
+ int index = root.getElementIndex(offset);
+ if (index == -1)
+ index = 0;
+
+ BranchElement newParagraph =
+ (BranchElement) createBranchElement(root, tag.getAttributes());
+ newParagraph.setResolveParent(getStyle(StyleContext.DEFAULT_STYLE));
+
+ // Add new paragraph into document structure.
+ Element[] added = new Element[]{newParagraph};
+ root.replace(index + 1, 0, added);
+ ElementEdit edit = new ElementEdit(root, index + 1, new Element[0],
+ added);
+ documentEvent.addEdit(edit);
+
+ // Maybe add fractured elements.
+ if (tag.getDirection() == ElementSpec.JoinFractureDirection)
+ {
+ Element[] newFracture = new Element[fracture.length];
+ for (int i = 0; i < fracture.length; i++)
+ {
+ Element oldLeaf = fracture[i];
+ Element newLeaf = createLeafElement(newParagraph,
+ oldLeaf.getAttributes(),
+ oldLeaf.getStartOffset(),
+ oldLeaf.getEndOffset());
+ newFracture[i] = newLeaf;
+ }
+ newParagraph.replace(0, 0, newFracture);
+ edit = new ElementEdit(newParagraph, 0, new Element[0],
+ fracture);
+ documentEvent.addEdit(edit);
+ fracture = new Element[0];
+ }
+ }
+
+ /**
+ * Inserts an end tag into the document structure. This cuts of the
+ * current paragraph element, possibly fracturing it's child elements.
+ * The fractured elements are saved so that they can be joined later
+ * with a new paragraph element.
+ */
+ void insertEndTag(ElementSpec tag)
+ {
+ BranchElement root = (BranchElement) getDefaultRootElement();
+ int parIndex = root.getElementIndex(offset);
+ BranchElement paragraph = (BranchElement) root.getElement(parIndex);
+
+ int index = paragraph.getElementIndex(offset);
+ LeafElement content = (LeafElement) paragraph.getElement(index);
+ // We might have to split the element at offset.
+ split(content, offset);
+ index = paragraph.getElementIndex(offset);
+
+ int count = paragraph.getElementCount();
+ // Store fractured elements.
+ fracture = new Element[count - index];
+ for (int i = index; i < count; ++i)
+ fracture[i - index] = paragraph.getElement(i);
+
+ // Delete fractured elements.
+ paragraph.replace(index, count - index, new Element[0]);
+
+ // Add this action to the document event.
+ ElementEdit edit = new ElementEdit(paragraph, index, fracture,
+ new Element[0]);
+ documentEvent.addEdit(edit);
+ }
+
+ /**
+ * Inserts a content element into the document structure.
+ *
+ * @param tag the element spec
+ */
+ void insertContentTag(ElementSpec tag)
+ {
+ int len = tag.getLength();
+ int dir = tag.getDirection();
+ if (dir == ElementSpec.JoinPreviousDirection)
+ {
+ Element prev = getCharacterElement(offset);
+ BranchElement prevParent = (BranchElement) prev.getParentElement();
+ Element join = createLeafElement(prevParent, tag.getAttributes(),
+ prev.getStartOffset(),
+ Math.max(prev.getEndOffset(),
+ offset + len));
+ int ind = prevParent.getElementIndex(offset);
+ if (ind == -1)
+ ind = 0;
+ Element[] add = new Element[]{join};
+ prevParent.replace(ind, 1, add);
+
+ // Add this action to the document event.
+ ElementEdit edit = new ElementEdit(prevParent, ind,
+ new Element[]{prev}, add);
+ documentEvent.addEdit(edit);
+ }
+ else if (dir == ElementSpec.JoinNextDirection)
+ {
+ Element next = getCharacterElement(offset + len);
+ BranchElement nextParent = (BranchElement) next.getParentElement();
+ Element join = createLeafElement(nextParent, tag.getAttributes(),
+ offset,
+ next.getEndOffset());
+ int ind = nextParent.getElementIndex(offset + len);
+ if (ind == -1)
+ ind = 0;
+ Element[] add = new Element[]{join};
+ nextParent.replace(ind, 1, add);
+
+ // Add this action to the document event.
+ ElementEdit edit = new ElementEdit(nextParent, ind,
+ new Element[]{next}, add);
+ documentEvent.addEdit(edit);
+ }
+ else
+ {
+ BranchElement par = (BranchElement) getParagraphElement(offset);
+
+ int ind = par.getElementIndex(offset);
+
+ // Make room for the element.
+ // Cut previous element.
+ Element prev = par.getElement(ind);
+ if (prev != null && prev.getStartOffset() < offset)
+ {
+ Element cutPrev = createLeafElement(par, prev.getAttributes(),
+ prev.getStartOffset(),
+ offset);
+ Element[] remove = new Element[]{prev};
+ Element[] add = new Element[]{cutPrev};
+ if (prev.getEndOffset() > offset + len)
+ {
+ Element rem = createLeafElement(par, prev.getAttributes(),
+ offset + len,
+ prev.getEndOffset());
+ add = new Element[]{cutPrev, rem};
+ }
+
+ par.replace(ind, 1, add);
+ documentEvent.addEdit(new ElementEdit(par, ind, remove, add));
+ ind++;
+ }
+ // ind now points to the next element.
+
+ // Cut next element if necessary.
+ Element next = par.getElement(ind);
+ if (next != null && next.getStartOffset() < offset + len)
+ {
+ Element cutNext = createLeafElement(par, next.getAttributes(),
+ offset + len,
+ next.getEndOffset());
+ Element[] remove = new Element[]{next};
+ Element[] add = new Element[]{cutNext};
+ par.replace(ind, 1, add);
+ documentEvent.addEdit(new ElementEdit(par, ind, remove,
+ add));
+ }
+
+ // Insert new element.
+ Element newEl = createLeafElement(par, tag.getAttributes(),
+ offset, offset + len);
+ Element[] added = new Element[]{newEl};
+ par.replace(ind, 0, added);
+ // Add this action to the document event.
+ ElementEdit edit = new ElementEdit(par, ind, new Element[0],
+ added);
+ documentEvent.addEdit(edit);
+ }
+ offset += len;
+ }
+
+ /**
+ * Creates a copy of the element <code>clonee</code> that has the parent
+ * <code>parent</code>.
+ * @param parent the parent of the newly created Element
+ * @param clonee the Element to clone
+ * @return the cloned Element
+ */
+ public Element clone (Element parent, Element clonee)
+ {
+ // If the Element we want to clone is a leaf, then simply copy it
+ if (clonee.isLeaf())
+ return createLeafElement(parent, clonee.getAttributes(),
+ clonee.getStartOffset(), clonee.getEndOffset());
+
+ // Otherwise create a new BranchElement with the desired parent and
+ // the clonee's attributes
+ BranchElement result = (BranchElement) createBranchElement(parent, clonee.getAttributes());
+
+ // And clone all the of clonee's children
+ Element[] children = new Element[clonee.getElementCount()];
+ for (int i = 0; i < children.length; i++)
+ children[i] = clone(result, clonee.getElement(i));
+
+ // Make the cloned children the children of the BranchElement
+ result.replace(0, 0, children);
+ return result;
+ }
}
/**
+ * An element type for sections. This is a simple BranchElement with
+ * a unique name.
+ */
+ protected class SectionElement extends BranchElement
+ {
+ /**
+ * Creates a new SectionElement.
+ */
+ public SectionElement()
+ {
+ super(null, null);
+ }
+
+ /**
+ * Returns the name of the element. This method always returns
+ * &quot;section&quot;.
+ *
+ * @return the name of the element
+ */
+ public String getName()
+ {
+ return "section";
+ }
+ }
+
+ /**
+ * Receives notification when any of the document's style changes and calls
+ * {@link DefaultStyledDocument#styleChanged(Style)}.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class StyleChangeListener
+ implements ChangeListener
+ {
+
+ /**
+ * Receives notification when any of the document's style changes and calls
+ * {@link DefaultStyledDocument#styleChanged(Style)}.
+ *
+ * @param event the change event
+ */
+ public void stateChanged(ChangeEvent event)
+ {
+ Style style = (Style) event.getSource();
+ styleChanged(style);
+ }
+ }
+
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 940485415728614849L;
+
+ /**
* The default size to use for new content buffers.
*/
public static final int BUFFER_SIZE_DEFAULT = 4096;
@@ -185,6 +866,11 @@ public class DefaultStyledDocument extends AbstractDocument
protected DefaultStyledDocument.ElementBuffer buffer;
/**
+ * Listens for changes on this document's styles and notifies styleChanged().
+ */
+ private StyleChangeListener styleChangeListener;
+
+ /**
* Creates a new <code>DefaultStyledDocument</code>.
*/
public DefaultStyledDocument()
@@ -237,7 +923,14 @@ public class DefaultStyledDocument extends AbstractDocument
public Style addStyle(String nm, Style parent)
{
StyleContext context = (StyleContext) getAttributeContext();
- return context.addStyle(nm, parent);
+ Style newStyle = context.addStyle(nm, parent);
+
+ // Register change listener.
+ if (styleChangeListener == null)
+ styleChangeListener = new StyleChangeListener();
+ newStyle.addChangeListener(styleChangeListener);
+
+ return newStyle;
}
/**
@@ -250,9 +943,11 @@ public class DefaultStyledDocument extends AbstractDocument
Element[] tmp;
// FIXME: Create a SecionElement here instead of a BranchElement.
// Use createBranchElement() and createLeafElement instead.
- BranchElement section = new BranchElement(null, null);
-
- BranchElement paragraph = new BranchElement(section, null);
+ SectionElement section = new SectionElement();
+
+ BranchElement paragraph =
+ (BranchElement) createBranchElement(section, null);
+ paragraph.setResolveParent(getStyle(StyleContext.DEFAULT_STYLE));
tmp = new Element[1];
tmp[0] = paragraph;
section.replace(0, 0, tmp);
@@ -261,7 +956,7 @@ public class DefaultStyledDocument extends AbstractDocument
tmp = new Element[1];
tmp[0] = leaf;
paragraph.replace(0, 0, tmp);
-
+
return section;
}
@@ -279,10 +974,10 @@ public class DefaultStyledDocument extends AbstractDocument
{
Element element = getDefaultRootElement();
- while (! element.isLeaf())
+ while (!element.isLeaf())
{
- int index = element.getElementIndex(position);
- element = element.getElement(index);
+ int index = element.getElementIndex(position);
+ element = element.getElement(index);
}
return element;
@@ -353,6 +1048,10 @@ public class DefaultStyledDocument extends AbstractDocument
/**
* Returns the paragraph element for the specified position.
+ * If the position is outside the bounds of the document's root element,
+ * then the closest element is returned. That is the last paragraph if
+ * <code>position >= endIndex</code> or the first paragraph if
+ * <code>position < startIndex</code>.
*
* @param position the position for which to query the paragraph element
*
@@ -360,8 +1059,18 @@ public class DefaultStyledDocument extends AbstractDocument
*/
public Element getParagraphElement(int position)
{
- Element element = getCharacterElement(position);
- return element.getParentElement();
+ BranchElement root = (BranchElement) getDefaultRootElement();
+ int start = root.getStartOffset();
+ int end = root.getEndOffset();
+ if (position >= end)
+ position = end - 1;
+ else if (position < start)
+ position = start;
+
+ Element par = root.positionToElement(position);
+
+ assert par != null : "The paragraph element must not be null";
+ return par;
}
/**
@@ -416,35 +1125,37 @@ public class DefaultStyledDocument extends AbstractDocument
int paragraphCount = root.getElementCount();
for (int pindex = 0; pindex < paragraphCount; pindex++)
{
- Element paragraph = root.getElement(pindex);
- // Skip paragraphs that lie outside the interval.
- if ((paragraph.getStartOffset() > offset + length)
- || (paragraph.getEndOffset() < offset))
- continue;
-
- // Visit content elements within this paragraph
- int contentCount = paragraph.getElementCount();
- for (int cindex = 0; cindex < contentCount; cindex++)
- {
- Element content = paragraph.getElement(cindex);
- // Skip content that lies outside the interval.
- if ((content.getStartOffset() > offset + length)
- || (content.getEndOffset() < offset))
- continue;
-
- if (content instanceof AbstractElement)
- {
- AbstractElement el = (AbstractElement) content;
- if (replace)
- el.removeAttributes(el);
- el.addAttributes(attributes);
- }
- else
- throw new AssertionError("content elements are expected to be"
- + "instances of "
+ Element paragraph = root.getElement(pindex);
+ // Skip paragraphs that lie outside the interval.
+ if ((paragraph.getStartOffset() > offset + length)
+ || (paragraph.getEndOffset() < offset))
+ continue;
+
+ // Visit content elements within this paragraph
+ int contentCount = paragraph.getElementCount();
+ for (int cindex = 0; cindex < contentCount; cindex++)
+ {
+ Element content = paragraph.getElement(cindex);
+ // Skip content that lies outside the interval.
+ if ((content.getStartOffset() > offset + length)
+ || (content.getEndOffset() < offset))
+ continue;
+
+ if (content instanceof AbstractElement)
+ {
+ AbstractElement el = (AbstractElement) content;
+ if (replace)
+ el.removeAttributes(el);
+ el.addAttributes(attributes);
+ }
+ else
+ throw new AssertionError("content elements are expected to be"
+ + "instances of "
+ "javax.swing.text.AbstractDocument.AbstractElement");
- }
+ }
}
+
+ fireChangedUpdate(ev);
}
/**
@@ -476,10 +1187,199 @@ public class DefaultStyledDocument extends AbstractDocument
* selection are overridden, otherwise they are merged
*/
public void setParagraphAttributes(int offset, int length,
- AttributeSet attributes,
- boolean replace)
+ AttributeSet attributes,
+ boolean replace)
+ {
+ int index = offset;
+ while (index < offset + length)
+ {
+ AbstractElement par = (AbstractElement) getParagraphElement(index);
+ AttributeContext ctx = getAttributeContext();
+ if (replace)
+ par.removeAttributes(par);
+ par.addAttributes(attributes);
+ index = par.getElementCount();
+ }
+ }
+
+ /**
+ * Called in response to content insert actions. This is used to
+ * update the element structure.
+ *
+ * @param ev the <code>DocumentEvent</code> describing the change
+ * @param attr the attributes for the change
+ */
+ protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr)
+ {
+ super.insertUpdate(ev, attr);
+ int offset = ev.getOffset();
+ int length = ev.getLength();
+ int endOffset = offset + length;
+ Segment txt = new Segment();
+ try
+ {
+ getText(offset, length, txt);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError ae = new AssertionError("Unexpected bad location");
+ ae.initCause(ex);
+ throw ae;
+ }
+
+ int len = 0;
+ Vector specs = new Vector();
+
+ Element prev = getCharacterElement(offset);
+ Element next = getCharacterElement(endOffset);
+
+ for (int i = offset; i < endOffset; ++i)
+ {
+ len++;
+ if (txt.array[i] == '\n')
+ {
+ ElementSpec spec = new ElementSpec(attr, ElementSpec.ContentType,
+ len);
+
+ // If we are at the last index, then check if we could probably be
+ // joined with the next element.
+ if (i == endOffset - 1)
+ {
+ if (next.getAttributes().isEqual(attr))
+ spec.setDirection(ElementSpec.JoinNextDirection);
+ }
+ // If we are at the first new element, then check if it could be
+ // joined with the previous element.
+ else if (specs.size() == 0)
+ {
+ if (prev.getAttributes().isEqual(attr))
+ spec.setDirection(ElementSpec.JoinPreviousDirection);
+ }
+
+ specs.add(spec);
+
+ // Add ElementSpecs for the newline.
+ ElementSpec endTag = new ElementSpec(null, ElementSpec.EndTagType);
+ specs.add(endTag);
+ ElementSpec startTag = new ElementSpec(null,
+ ElementSpec.StartTagType);
+ startTag.setDirection(ElementSpec.JoinFractureDirection);
+ specs.add(startTag);
+
+ len = 0;
+ offset += len;
+ }
+ }
+
+ // Create last element if last character hasn't been a newline.
+ if (len > 0)
+ {
+ ElementSpec spec = new ElementSpec(attr, ElementSpec.ContentType, len);
+ // If we are at the first new element, then check if it could be
+ // joined with the previous element.
+ if (specs.size() == 0)
+ {
+ if (prev.getAttributes().isEqual(attr))
+ spec.setDirection(ElementSpec.JoinPreviousDirection);
+ }
+ // Check if we could probably be joined with the next element.
+ else if (next.getAttributes().isEqual(attr))
+ spec.setDirection(ElementSpec.JoinNextDirection);
+
+ specs.add(spec);
+ }
+
+ ElementSpec[] elSpecs =
+ (ElementSpec[]) specs.toArray(new ElementSpec[specs.size()]);
+
+ buffer.insert(offset, length, elSpecs, ev);
+ }
+
+ /**
+ * Returns an enumeration of all style names.
+ *
+ * @return an enumeration of all style names
+ */
+ public Enumeration getStyleNames()
+ {
+ StyleContext context = (StyleContext) getAttributeContext();
+ return context.getStyleNames();
+ }
+
+ /**
+ * Called when any of this document's styles changes.
+ *
+ * @param style the style that changed
+ */
+ protected void styleChanged(Style style)
{
- // FIXME: Implement me.
- throw new Error("not implemented");
+ // Nothing to do here. This is intended to be overridden by subclasses.
+ }
+
+ /**
+ * Inserts a bulk of structured content at once.
+ *
+ * @param offset the offset at which the content should be inserted
+ * @param data the actual content spec to be inserted
+ */
+ protected void insert(int offset, ElementSpec[] data)
+ throws BadLocationException
+ {
+ writeLock();
+ // First we insert the content.
+ int index = offset;
+ for (int i = 0; i < data.length; i++)
+ {
+ ElementSpec spec = data[i];
+ if (spec.getArray() != null && spec.getLength() > 0)
+ {
+ String insertString = new String(spec.getArray(), spec.getOffset(),
+ spec.getLength());
+ content.insertString(index, insertString);
+ }
+ index += spec.getLength();
+ }
+ // Update the view structure.
+ DefaultDocumentEvent ev = new DefaultDocumentEvent(offset, index - offset,
+ DocumentEvent.EventType.INSERT);
+ for (int i = 0; i < data.length; i++)
+ {
+ ElementSpec spec = data[i];
+ AttributeSet atts = spec.getAttributes();
+ if (atts != null)
+ insertUpdate(ev, atts);
+ }
+
+ // Finally we must update the document structure and fire the insert update
+ // event.
+ buffer.insert(offset, index - offset, data, ev);
+ fireInsertUpdate(ev);
+ writeUnlock();
+ }
+
+ /**
+ * Initializes the <code>DefaultStyledDocument</code> with the specified
+ * data.
+ *
+ * @param data the specification of the content with which the document is
+ * initialized
+ */
+ protected void create(ElementSpec[] data)
+ {
+ try
+ {
+ // Clear content.
+ content.remove(0, content.length());
+ // Clear buffer and root element.
+ buffer = new ElementBuffer(createDefaultRoot());
+ // Insert the data.
+ insert(0, data);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError("Unexpected bad location");
+ err.initCause(ex);
+ throw err;
+ }
}
}
diff --git a/libjava/classpath/javax/swing/text/DefaultTextUI.java b/libjava/classpath/javax/swing/text/DefaultTextUI.java
new file mode 100644
index 00000000000..e7ff01845e6
--- /dev/null
+++ b/libjava/classpath/javax/swing/text/DefaultTextUI.java
@@ -0,0 +1,61 @@
+/* DefaultTextUI.java -- Deprecated base UI for text components
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import javax.swing.plaf.basic.BasicTextUI;
+
+/**
+ * This class is deprecated and should not be used anymore. The base UI for
+ * all text components is now {@link BasicTextUI}.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public abstract class DefaultTextUI extends BasicTextUI
+{
+ /**
+ * This class is deprecated and should not be used anymore. The base UI for
+ * all text components is now {@link BasicTextUI}.
+ *
+ * @deprecated use {@link BasicTextUI} instead
+ */
+ public DefaultTextUI()
+ {
+ // Nothing to do here.
+ }
+}
diff --git a/libjava/classpath/javax/swing/text/EditorKit.java b/libjava/classpath/javax/swing/text/EditorKit.java
index bd51a866f68..8719aee595f 100644
--- a/libjava/classpath/javax/swing/text/EditorKit.java
+++ b/libjava/classpath/javax/swing/text/EditorKit.java
@@ -48,24 +48,24 @@ import java.io.Writer;
import javax.swing.Action;
import javax.swing.JEditorPane;
-public abstract class EditorKit
- implements Cloneable, Serializable
+public abstract class EditorKit implements Cloneable, Serializable
{
private static final long serialVersionUID = -5044124649345887822L;
public EditorKit()
{
+ // Nothing to do here.
}
public Object clone()
{
try
{
- return super.clone();
+ return super.clone();
}
catch (CloneNotSupportedException e)
{
- return null;
+ return null;
}
}
@@ -74,10 +74,12 @@ public abstract class EditorKit
*/
public void deinstall(JEditorPane c)
{
+ // This default implementation does nothing.
}
public void install(JEditorPane c)
{
+ // This default implementation does nothing.
}
public abstract Caret createCaret();
diff --git a/libjava/classpath/javax/swing/text/FieldView.java b/libjava/classpath/javax/swing/text/FieldView.java
index e2e04d7c495..2496418444e 100644
--- a/libjava/classpath/javax/swing/text/FieldView.java
+++ b/libjava/classpath/javax/swing/text/FieldView.java
@@ -118,22 +118,24 @@ public class FieldView extends PlainView
FontMetrics fm = getFontMetrics();
if (axis == Y_AXIS)
- return fm.getHeight();
+ return super.getPreferredSpan(axis);
String text;
Element elem = getElement();
try
{
- text = elem.getDocument().getText(elem.getStartOffset(),
- elem.getEndOffset());
+ text = elem.getDocument().getText(elem.getStartOffset(),
+ elem.getEndOffset());
}
catch (BadLocationException e)
{
- // This should never happen.
- text = "";
+ // Should never happen
+ AssertionError ae = new AssertionError();
+ ae.initCause(e);
+ throw ae;
}
-
+
return fm.stringWidth(text);
}
@@ -159,18 +161,21 @@ public class FieldView extends PlainView
{
Shape newAlloc = adjustAllocation(shape);
super.insertUpdate(ev, newAlloc, vf);
+ getContainer().repaint();
}
public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
{
Shape newAlloc = adjustAllocation(shape);
super.removeUpdate(ev, newAlloc, vf);
+ getContainer().repaint();
}
public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
{
Shape newAlloc = adjustAllocation(shape);
super.removeUpdate(ev, newAlloc, vf);
+ getContainer().repaint();
}
public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias)
diff --git a/libjava/classpath/javax/swing/text/FlowView.java b/libjava/classpath/javax/swing/text/FlowView.java
index a6ef89efb78..fd6785b6f18 100644
--- a/libjava/classpath/javax/swing/text/FlowView.java
+++ b/libjava/classpath/javax/swing/text/FlowView.java
@@ -42,8 +42,10 @@ import java.awt.Container;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
+import java.util.Iterator;
import java.util.Vector;
+import javax.swing.SwingConstants;
import javax.swing.event.DocumentEvent;
/**
@@ -71,6 +73,7 @@ public abstract class FlowView extends BoxView
*/
public FlowStrategy()
{
+ // Nothing to do here.
}
/**
@@ -137,7 +140,7 @@ public abstract class FlowView extends BoxView
* Performs the layout for the whole view. By default this rebuilds
* all the physical views from the logical views of the managed FlowView.
*
- * This is called by {@link FlowLayout#layout} to update the layout of
+ * This is called by {@link FlowView#layout} to update the layout of
* the view.
*
* @param fv the flow view for which we perform the layout
@@ -183,11 +186,17 @@ public abstract class FlowView extends BoxView
{
View child = createView(fv, offset, spanLeft, rowIndex);
if (child == null)
- break;
+ {
+ offset = -1;
+ break;
+ }
int span = (int) child.getPreferredSpan(flowAxis);
if (span > spanLeft)
- break;
+ {
+ offset = -1;
+ break;
+ }
row.append(child);
spanLeft -= span;
@@ -204,7 +213,7 @@ public abstract class FlowView extends BoxView
* not fit in the available span and also cannot be broken down).
*
* @param fv the flow view
- * @param startOffset the start offset for the view to be created
+ * @param offset the start offset for the view to be created
* @param spanLeft the available span
* @param rowIndex the index of the row
*
@@ -218,13 +227,15 @@ public abstract class FlowView extends BoxView
View logicalView = getLogicalView(fv);
int viewIndex = logicalView.getViewIndex(offset, Position.Bias.Forward);
+ if (viewIndex == -1)
+ return null;
+
View child = logicalView.getView(viewIndex);
int flowAxis = fv.getFlowAxis();
int span = (int) child.getPreferredSpan(flowAxis);
if (span <= spanLeft)
return child;
-
else if (child.getBreakWeight(flowAxis, offset, spanLeft)
> BadBreakWeight)
// FIXME: What to do with the pos parameter here?
@@ -326,7 +337,19 @@ public abstract class FlowView extends BoxView
*/
public int getViewIndex(int pos, Position.Bias b)
{
- return getElement().getElementIndex(pos);
+ int index = -1;
+ int i = 0;
+ for (Iterator it = children.iterator(); it.hasNext(); i++)
+ {
+ View child = (View) it.next();
+ if (child.getStartOffset() >= pos
+ && child.getEndOffset() < pos)
+ {
+ index = i;
+ break;
+ }
+ }
+ return index;
}
/**
@@ -373,6 +396,37 @@ public abstract class FlowView extends BoxView
throw new AssertionError("This method must not be called in "
+ "LogicalView.");
}
+
+ /**
+ * Returns the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction <code>d</code>.
+ *
+ * @param c the text component
+ * @param pos the document position
+ * @param b the bias for <code>pos</code>
+ * @param d the direction, must be either {@link SwingConstants#NORTH},
+ * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
+ * {@link SwingConstants#EAST}
+ * @param biasRet an array of {@link Position.Bias} that can hold at least
+ * one element, which is filled with the bias of the return position
+ * on method exit
+ *
+ * @return the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction
+ * <code>d</code>
+ *
+ * @throws BadLocationException if <code>pos</code> is not a valid offset in
+ * the document model
+ */
+ public int getNextVisualPositionFrom(JTextComponent c, int pos,
+ Position.Bias b, int d,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ assert false : "getNextVisualPositionFrom() must not be called in "
+ + "LogicalView";
+ return 0;
+ }
}
/**
@@ -478,7 +532,7 @@ public abstract class FlowView extends BoxView
* The real children are created at layout time and each represent one
* row.
*
- * This method is called by {@link #setParent} in order to initialize
+ * This method is called by {@link View#setParent} in order to initialize
* the view.
*
* @param vf the view factory to use for creating the child views
@@ -502,7 +556,7 @@ public abstract class FlowView extends BoxView
/**
* Performs the layout of this view. If the span along the flow axis changed,
- * this first calls {@link FlowStrategy.layout} in order to rebuild the
+ * this first calls {@link FlowStrategy#layout} in order to rebuild the
* rows of this view. Then the superclass's behaviour is called to arrange
* the rows within the box.
*
diff --git a/libjava/classpath/javax/swing/text/GapContent.java b/libjava/classpath/javax/swing/text/GapContent.java
index 1dd46c4b0f4..4c65de0f5f4 100644
--- a/libjava/classpath/javax/swing/text/GapContent.java
+++ b/libjava/classpath/javax/swing/text/GapContent.java
@@ -39,10 +39,15 @@ exception statement from your version. */
package javax.swing.text;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.Collections;
-import java.util.LinkedList;
+import java.util.Iterator;
import java.util.ListIterator;
+import java.util.Vector;
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoableEdit;
/**
@@ -59,7 +64,6 @@ import javax.swing.undo.UndoableEdit;
public class GapContent
implements AbstractDocument.Content, Serializable
{
-
/**
* A {@link Position} implementation for <code>GapContent</code>.
*/
@@ -114,6 +118,11 @@ public class GapContent
*/
public int getOffset()
{
+ // Check precondition.
+ assert mark <= gapStart || mark >= gapEnd : "mark: " + mark
+ + ", gapStart: " + gapStart
+ + ", gapEnd: " + gapEnd;
+
if (mark <= gapStart)
return mark;
else
@@ -121,13 +130,91 @@ public class GapContent
}
}
- private static final long serialVersionUID = 8374645204155842629L;
+ class UndoInsertString extends AbstractUndoableEdit
+ {
+ public int where, length;
+ String text;
+ public UndoInsertString(int start, int len)
+ {
+ where = start;
+ length = len;
+ }
+
+ public void undo () throws CannotUndoException
+ {
+ super.undo();
+ try
+ {
+ text = getString(where, length);
+ remove(where, length);
+ }
+ catch (BadLocationException ble)
+ {
+ throw new CannotUndoException();
+ }
+ }
+
+ public void redo () throws CannotUndoException
+ {
+ super.redo();
+ try
+ {
+ insertString(where, text);
+ }
+ catch (BadLocationException ble)
+ {
+ throw new CannotRedoException();
+ }
+ }
+
+ }
+
+ class UndoRemove extends AbstractUndoableEdit
+ {
+ public int where;
+ String text;
+ public UndoRemove(int start, String removedText)
+ {
+ where = start;
+ text = removedText;
+ }
+
+ public void undo () throws CannotUndoException
+ {
+ super.undo();
+ try
+ {
+ insertString(where, text);
+ }
+ catch (BadLocationException ble)
+ {
+ throw new CannotUndoException();
+ }
+ }
+
+ public void redo () throws CannotUndoException
+ {
+ super.redo();
+ try
+ {
+ remove(where, text.length());
+ }
+ catch (BadLocationException ble)
+ {
+ throw new CannotRedoException();
+ }
+ }
+
+ }
+
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -6226052713477823730L;
/**
* This is the default buffer size and the amount of bytes that a buffer is
* extended if it is full.
*/
- static final int DEFAULT_BUFSIZE = 64;
+ static final int DEFAULT_BUFSIZE = 10;
/**
* The text buffer.
@@ -148,7 +235,7 @@ public class GapContent
* The positions generated by this GapContent. They are kept in an ordered
* fashion, so they can be looked up easily.
*/
- LinkedList positions;
+ ArrayList positions;
/**
* Creates a new GapContent object.
@@ -166,10 +253,10 @@ public class GapContent
public GapContent(int size)
{
buffer = (char[]) allocateArray(size);
- gapStart = 0;
- gapEnd = size - 1;
- buffer[size - 1] = '\n';
- positions = new LinkedList();
+ gapStart = 1;
+ gapEnd = size;
+ buffer[0] = '\n';
+ positions = new ArrayList();
}
/**
@@ -211,8 +298,7 @@ public class GapContent
* @param where the position where the string is inserted
* @param str the string that is to be inserted
*
- * @return an UndoableEdit object (currently not supported, so
- * <code>null</code> is returned)
+ * @return an UndoableEdit object
*
* @throws BadLocationException if <code>where</code> is not a valid
* location in the buffer
@@ -228,9 +314,9 @@ public class GapContent
throw new BadLocationException("the where argument cannot be greater"
+ " than the content length", where);
- replace(where, 0, str.toCharArray(), str.length());
+ replace(where, 0, str.toCharArray(), strLen);
- return null;
+ return new UndoInsertString(where, strLen);
}
/**
@@ -239,8 +325,7 @@ public class GapContent
* @param where the position where the content is to be removed
* @param nitems number of characters to be removed
*
- * @return an UndoableEdit object (currently not supported, so
- * <code>null</code> is returned)
+ * @return an UndoableEdit object
*
* @throws BadLocationException if <code>where</code> is not a valid
* location in the buffer
@@ -257,9 +342,10 @@ public class GapContent
throw new BadLocationException("where + nitems cannot be greater"
+ " than the content length", where + nitems);
+ String removedText = getString(where, nitems);
replace(where, nitems, null, 0);
- return null;
+ return new UndoRemove(where, removedText);
}
/**
@@ -372,7 +458,6 @@ public class GapContent
if (index < 0)
index = -(index + 1);
positions.add(index, pos);
-
return pos;
}
@@ -386,7 +471,14 @@ public class GapContent
*/
protected void shiftEnd(int newSize)
{
- int delta = (gapEnd - gapStart) - newSize;
+ assert newSize > (gapEnd - gapStart) : "The new gap size must be greater "
+ + "than the old gap size";
+
+ int delta = newSize - gapEnd + gapStart;
+ // Update the marks after the gapEnd.
+ adjustPositionsInRange(gapEnd, buffer.length - gapEnd, delta);
+
+ // Copy the data around.
char[] newBuf = (char[]) allocateArray(length() + newSize);
System.arraycopy(buffer, 0, newBuf, 0, gapStart);
System.arraycopy(buffer, gapEnd, newBuf, gapStart + newSize, buffer.length
@@ -394,18 +486,6 @@ public class GapContent
gapEnd = gapStart + newSize;
buffer = newBuf;
- // Update the marks after the gapEnd.
- int index = Collections.binarySearch(positions, new GapContentPosition(
- gapEnd));
- if (index < 0)
- {
- index = -(index + 1);
- }
- for (ListIterator i = positions.listIterator(index); i.hasNext();)
- {
- GapContentPosition p = (GapContentPosition) i.next();
- p.mark += delta;
- }
}
/**
@@ -415,32 +495,15 @@ public class GapContent
*/
protected void shiftGap(int newGapStart)
{
- int newGapEnd = newGapStart + (gapEnd - gapStart);
-
- // Update the positions between newGapEnd and (old) gapEnd. The marks
- // must be shifted by (gapEnd - newGapEnd).
- int index1 = Collections.binarySearch(positions,
- new GapContentPosition(gapEnd));
- int index2 = Collections.binarySearch(positions,
- new GapContentPosition(newGapEnd));
- if (index1 > 0 && index2 > 0)
- {
- int i1 = Math.min(index1, index2);
- int i2 = Math.max(index1, index2);
- for (ListIterator i = positions.listIterator(i1); i.hasNext();)
- {
- if (i.nextIndex() > i2)
- break;
-
- GapContentPosition p = (GapContentPosition) i.next();
- p.mark += gapEnd - newGapEnd;
- }
- }
-
if (newGapStart == gapStart)
return;
- else if (newGapStart < gapStart)
+
+ int newGapEnd = newGapStart + gapEnd - gapStart;
+ if (newGapStart < gapStart)
{
+ // Update the positions between newGapStart and (old) gapStart. The marks
+ // must be shifted by (gapEnd - gapStart).
+ adjustPositionsInRange(newGapStart, gapStart - newGapStart, gapEnd - gapStart);
System.arraycopy(buffer, newGapStart, buffer, newGapEnd, gapStart
- newGapStart);
gapStart = newGapStart;
@@ -448,11 +511,54 @@ public class GapContent
}
else
{
+ // Update the positions between newGapEnd and (old) gapEnd. The marks
+ // must be shifted by (gapEnd - gapStart).
+ adjustPositionsInRange(gapEnd, newGapEnd - gapEnd, -(gapEnd - gapStart));
System.arraycopy(buffer, gapEnd, buffer, gapStart, newGapStart
- gapStart);
gapStart = newGapStart;
gapEnd = newGapEnd;
}
+ if (gapStart == 0)
+ resetMarksAtZero();
+ }
+
+ /**
+ * Shifts the gap start downwards. This does not affect the content of the
+ * buffer. This only updates the gap start and all the marks that are between
+ * the old gap start and the new gap start. They all are squeezed to the start
+ * of the gap, because their location has been removed.
+ *
+ * @param newGapStart the new gap start
+ */
+ protected void shiftGapStartDown(int newGapStart)
+ {
+ if (newGapStart == gapStart)
+ return;
+
+ assert newGapStart < gapStart : "The new gap start must be less than the "
+ + "old gap start.";
+ setPositionsInRange(newGapStart, gapStart - newGapStart, gapStart);
+ gapStart = newGapStart;
+ }
+
+ /**
+ * Shifts the gap end upwards. This does not affect the content of the
+ * buffer. This only updates the gap end and all the marks that are between
+ * the old gap end and the new end start. They all are squeezed to the end
+ * of the gap, because their location has been removed.
+ *
+ * @param newGapEnd the new gap start
+ */
+ protected void shiftGapEndUp(int newGapEnd)
+ {
+ if (newGapEnd == gapEnd)
+ return;
+
+ assert newGapEnd > gapEnd : "The new gap end must be greater than the "
+ + "old gap end.";
+ setPositionsInRange(gapEnd, newGapEnd - gapEnd, newGapEnd + 1);
+ gapEnd = newGapEnd;
}
/**
@@ -476,13 +582,15 @@ public class GapContent
protected void replace(int position, int rmSize, Object addItems,
int addSize)
{
+ if (gapStart != position)
+ shiftGap(position);
// Remove content
- shiftGap(position);
- gapEnd += rmSize;
+ if (rmSize > 0)
+ shiftGapEndUp(gapEnd + rmSize);
// If gap is too small, enlarge the gap.
- if ((gapEnd - gapStart) < addSize)
- shiftEnd(addSize);
+ if ((gapEnd - gapStart) <= addSize)
+ shiftEnd((addSize - gapEnd + gapStart + 1) * 2 + gapEnd + DEFAULT_BUFSIZE);
// Add new items to the buffer.
if (addItems != null)
@@ -491,4 +599,164 @@ public class GapContent
gapStart += addSize;
}
}
+
+ /**
+ * Returns the start index of the gap within the buffer array.
+ *
+ * @return the start index of the gap within the buffer array
+ */
+ protected final int getGapStart()
+ {
+ return gapStart;
+ }
+
+ /**
+ * Returns the end index of the gap within the buffer array.
+ *
+ * @return the end index of the gap within the buffer array
+ */
+ protected final int getGapEnd()
+ {
+ return gapEnd;
+ }
+
+ /**
+ * Returns all <code>Position</code>s that are in the range specified by
+ * <code>offset</code> and </code>length</code> within the buffer array.
+ *
+ * @param v the vector to use; if <code>null</code>, a new Vector is allocated
+ * @param offset the start offset of the range to search
+ * @param length the length of the range to search
+ *
+ * @return the positions within the specified range
+ */
+ protected Vector getPositionsInRange(Vector v, int offset, int length)
+ {
+ Vector res = v;
+ if (res == null)
+ res = new Vector();
+ else
+ res.clear();
+
+ int endOffset = offset + length;
+
+ int index1 = Collections.binarySearch(positions,
+ new GapContentPosition(offset));
+ if (index1 < 0)
+ index1 = -(index1 + 1);
+ for (ListIterator i = positions.listIterator(index1); i.hasNext();)
+ {
+ GapContentPosition p = (GapContentPosition) i.next();
+ if (p.mark > endOffset)
+ break;
+ if (p.mark >= offset && p.mark <= endOffset)
+ res.add(p);
+ }
+ return res;
+ }
+
+ /**
+ * Sets the mark of all <code>Position</code>s that are in the range
+ * specified by <code>offset</code> and </code>length</code> within
+ * the buffer array to <code>value</code>
+ *
+ * @param offset the start offset of the range to search
+ * @param length the length of the range to search
+ * @param value the new value for each mark
+ */
+ void setPositionsInRange(int offset, int length, int value)
+ {
+ int endOffset = offset + length;
+
+ int index1 = Collections.binarySearch(positions,
+ new GapContentPosition(offset));
+ if (index1 < 0)
+ index1 = -(index1 + 1);
+ for (ListIterator i = positions.listIterator(index1); i.hasNext();)
+ {
+ GapContentPosition p = (GapContentPosition) i.next();
+ if (p.mark > endOffset)
+ break;
+
+ if (p.mark >= offset && p.mark <= endOffset)
+ p.mark = value;
+ }
+ }
+
+ /**
+ * Adjusts the mark of all <code>Position</code>s that are in the range
+ * specified by <code>offset</code> and </code>length</code> within
+ * the buffer array by <code>increment</code>
+ *
+ * @param offset the start offset of the range to search
+ * @param length the length of the range to search
+ * @param incr the increment
+ */
+ void adjustPositionsInRange(int offset, int length, int incr)
+ {
+ int endOffset = offset + length;
+
+ int index1 = Collections.binarySearch(positions,
+ new GapContentPosition(offset));
+ if (index1 < 0)
+ index1 = -(index1 + 1);
+ for (ListIterator i = positions.listIterator(index1); i.hasNext();)
+ {
+ GapContentPosition p = (GapContentPosition) i.next();
+ if (p.mark > endOffset)
+ break;
+
+ if (p.mark >= offset && p.mark <= endOffset)
+ p.mark += incr;
+ }
+ }
+
+ /**
+ * Resets all <code>Position</code> that have an offset of <code>0</code>,
+ * to also have an array index of <code>0</code>. This might be necessary
+ * after a call to <code>shiftGap(0)</code>, since then the marks at offset
+ * <code>0</code> get shifted to <code>gapEnd</code>.
+ */
+ protected void resetMarksAtZero()
+ {
+ if (gapStart != 0)
+ return;
+
+ setPositionsInRange(gapEnd, 0, 0);
+ }
+
+ /**
+ * Outputs debugging info to System.err. It prints out the buffer array,
+ * the gapStart is marked by a &lt; sign, the gapEnd is marked by a &gt;
+ * sign and each position is marked by a # sign.
+ */
+ private void dump()
+ {
+ System.err.println("GapContent debug information");
+ System.err.println("buffer length: " + buffer.length);
+ System.err.println("gap start: " + gapStart);
+ System.err.println("gap end: " + gapEnd);
+ for (int i = 0; i < buffer.length; i++)
+ {
+ if (i == gapStart)
+ System.err.print('<');
+ if (i == gapEnd)
+ System.err.print('>');
+
+ if (!Character.isISOControl(buffer[i]))
+ System.err.print(buffer[i]);
+ else
+ System.err.print('.');
+ }
+ System.err.println();
+ }
+
+ private void dumpPositions()
+ {
+ for (Iterator i = positions.iterator(); i.hasNext();)
+ {
+ GapContentPosition pos = (GapContentPosition) i.next();
+ System.err.println("position at: " + pos.mark);
+ }
+ }
}
diff --git a/libjava/classpath/javax/swing/text/GlyphView.java b/libjava/classpath/javax/swing/text/GlyphView.java
index f9e60972d84..eb1fadd4f2d 100644
--- a/libjava/classpath/javax/swing/text/GlyphView.java
+++ b/libjava/classpath/javax/swing/text/GlyphView.java
@@ -44,6 +44,12 @@ import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
+import java.awt.Toolkit;
+import java.text.BreakIterator;
+
+import javax.swing.SwingConstants;
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.Position.Bias;
/**
* Renders a run of styled text. This {@link View} subclass paints the
@@ -52,9 +58,7 @@ import java.awt.Shape;
*
* @author Roman Kennke (roman@kennke.org)
*/
-public class GlyphView
- extends View
- implements TabableView, Cloneable
+public class GlyphView extends View implements TabableView, Cloneable
{
/**
@@ -68,15 +72,47 @@ public class GlyphView
*/
public GlyphPainter()
{
+ // Nothing to do here.
}
/**
+ * Returns the ascent of the font that is used by this glyph painter.
+ *
+ * @param v the glyph view
+ *
+ * @return the ascent of the font that is used by this glyph painter
+ */
+ public abstract float getAscent(GlyphView v);
+
+ /**
+ * Returns the descent of the font that is used by this glyph painter.
+ *
+ * @param v the glyph view
+ *
+ * @return the descent of the font that is used by this glyph painter
+ */
+ public abstract float getDescent(GlyphView v);
+
+ /**
* Returns the full height of the rendered text.
*
* @return the full height of the rendered text
*/
public abstract float getHeight(GlyphView view);
-
+
+ /**
+ * Determines the model offset, so that the text between <code>p0</code>
+ * and this offset fits within the span starting at <code>x</code> with
+ * the length of <code>len</code>.
+ *
+ * @param v the glyph view
+ * @param p0 the starting offset in the model
+ * @param x the start location in the view
+ * @param len the length of the span in the view
+ */
+ public abstract int getBoundedPosition(GlyphView v, int p0, float x,
+ float len);
+
/**
* Paints the glyphs.
*
@@ -97,8 +133,8 @@ public class GlyphView
* @param view the glyph view
* @param pos the position of the character in the model
* @param a the area that is occupied by the view
- * @param bias either {@link Position.Bias.Forward} or
- * {@link Position.Bias.Backward} depending on the preferred
+ * @param b either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward} depending on the preferred
* direction bias. If <code>null</code> this defaults to
* <code>Position.Bias.Forward</code>
*
@@ -114,6 +150,20 @@ public class GlyphView
throws BadLocationException;
/**
+ * Maps a visual position into a document location.
+ *
+ * @param v the glyph view
+ * @param x the X coordinate of the visual position
+ * @param y the Y coordinate of the visual position
+ * @param a the allocated region
+ * @param biasRet filled with the bias of the model location on method exit
+ *
+ * @return the model location that represents the specified view location
+ */
+ public abstract int viewToModel(GlyphView v, float x, float y, Shape a,
+ Position.Bias[] biasRet);
+
+ /**
* Determine the span of the glyphs from location <code>p0</code> to
* location <code>p1</code>. If <code>te</code> is not <code>null</code>,
* then TABs are expanded using this <code>TabExpander</code>.
@@ -122,7 +172,7 @@ public class GlyphView
*
* @param view the glyph view
* @param p0 the starting location in the document model
- * @param p0 the end location in the document model
+ * @param p1 the end location in the document model
* @param te the tab expander to use
* @param x the location at which the view is located
*
@@ -132,6 +182,69 @@ public class GlyphView
public abstract float getSpan(GlyphView view, int p0, int p1,
TabExpander te, float x);
+
+ /**
+ * Returns the model location that should be used to place a caret when
+ * moving the caret through the document.
+ *
+ * @param v the glyph view
+ * @param pos the current model location
+ * @param b the bias for <code>p</code>
+ * @param a the allocated region for the glyph view
+ * @param direction the direction from the current position; Must be one of
+ * {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
+ * {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
+ * @param biasRet filled with the bias of the resulting location when method
+ * returns
+ *
+ * @return the location within the document that should be used to place the
+ * caret when moving the caret around the document
+ *
+ * @throws BadLocationException if <code>pos</code> is an invalid model
+ * location
+ * @throws IllegalArgumentException if <code>d</code> is invalid
+ */
+ public int getNextVisualPositionFrom(GlyphView v, int pos, Position.Bias b,
+ Shape a, int direction,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+
+ {
+ int result = pos;
+ switch (direction)
+ {
+ case SwingConstants.EAST:
+ result = pos + 1;
+ break;
+ case SwingConstants.WEST:
+ result = pos - 1;
+ break;
+ case SwingConstants.NORTH:
+ case SwingConstants.SOUTH:
+ default:
+ // This should be handled in enclosing view, since the glyph view
+ // does not layout vertically.
+ break;
+ }
+ return result;
+ }
+
+ /**
+ * Returns a painter that can be used to render the specified glyph view.
+ * If this glyph painter is stateful, then it should return a new instance.
+ * However, if this painter is stateless it should return itself. The
+ * default behaviour is to return itself.
+ *
+ * @param v the glyph view for which to create a painter
+ * @param p0 the start offset of the rendered area
+ * @param p1 the end offset of the rendered area
+ *
+ * @return a painter that can be used to render the specified glyph view
+ */
+ public GlyphPainter getPainter(GlyphView v, int p0, int p1)
+ {
+ return this;
+ }
}
/**
@@ -147,7 +260,7 @@ public class GlyphView
public float getHeight(GlyphView view)
{
Font font = view.getFont();
- FontMetrics metrics = view.getContainer().getFontMetrics(font);
+ FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
float height = metrics.getHeight();
return height;
}
@@ -173,11 +286,40 @@ public class GlyphView
if (parent instanceof TabExpander)
tabEx = (TabExpander) parent;
- // FIXME: Set character attributes like font-family, font-size, colors.
- Color foreground = view.getForeground();
- g.setColor(foreground);
- Utilities.drawTabbedText(txt, bounds.x, bounds.y, g, tabEx,
- txt.offset);
+ // Fill the background of the text run.
+ Color background = view.getBackground();
+ g.setColor(background);
+ int width = Utilities.getTabbedTextWidth(txt, g.getFontMetrics(),
+ bounds.x, tabEx, txt.offset);
+ g.fillRect(bounds.x, bounds.y, width, height);
+
+ // Draw the actual text.
+ g.setColor(view.getForeground());
+ g.setFont(view.getFont());
+ if (view.isSuperscript())
+ // TODO: Adjust font for superscripting.
+ Utilities.drawTabbedText(txt, bounds.x, bounds.y - height / 2, g, tabEx,
+ txt.offset);
+ else if (view.isSubscript())
+ // TODO: Adjust font for subscripting.
+ Utilities.drawTabbedText(txt, bounds.x, bounds.y + height / 2, g, tabEx,
+ txt.offset);
+ else
+ Utilities.drawTabbedText(txt, bounds.x, bounds.y, g, tabEx,
+ txt.offset);
+
+ if (view.isStikeThrough())
+ {
+ int strikeHeight = (int) (getAscent(view) / 2);
+ g.drawLine(bounds.x, bounds.y + strikeHeight, bounds.height + width,
+ bounds.y + strikeHeight);
+ }
+ if (view.isUnderline())
+ {
+ int lineHeight = (int) getAscent(view);
+ g.drawLine(bounds.x, bounds.y + lineHeight, bounds.height + width,
+ bounds.y + lineHeight);
+ }
}
/**
@@ -188,8 +330,8 @@ public class GlyphView
* @param view the glyph view
* @param pos the position of the character in the model
* @param a the area that is occupied by the view
- * @param bias either {@link Position.Bias.Forward} or
- * {@link Position.Bias.Backward} depending on the preferred
+ * @param b either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward} depending on the preferred
* direction bias. If <code>null</code> this defaults to
* <code>Position.Bias.Forward</code>
*
@@ -225,7 +367,7 @@ public class GlyphView
*
* @param view the glyph view
* @param p0 the starting location in the document model
- * @param p0 the end location in the document model
+ * @param p1 the end location in the document model
* @param te the tab expander to use
* @param x the location at which the view is located
*
@@ -237,11 +379,90 @@ public class GlyphView
{
Element el = view.getElement();
Font font = view.getFont();
- FontMetrics fm = view.getContainer().getFontMetrics(font);
+ FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
Segment txt = view.getText(p0, p1);
int span = Utilities.getTabbedTextWidth(txt, fm, (int) x, te, p0);
return span;
}
+
+ /**
+ * Returns the ascent of the text run that is rendered by this
+ * <code>GlyphPainter</code>.
+ *
+ * @param v the glyph view
+ *
+ * @return the ascent of the text run that is rendered by this
+ * <code>GlyphPainter</code>
+ *
+ * @see FontMetrics#getAscent()
+ */
+ public float getAscent(GlyphView v)
+ {
+ Font font = v.getFont();
+ FontMetrics fm = v.getContainer().getFontMetrics(font);
+ return fm.getAscent();
+ }
+
+ /**
+ * Returns the descent of the text run that is rendered by this
+ * <code>GlyphPainter</code>.
+ *
+ * @param v the glyph view
+ *
+ * @return the descent of the text run that is rendered by this
+ * <code>GlyphPainter</code>
+ *
+ * @see FontMetrics#getDescent()
+ */
+ public float getDescent(GlyphView v)
+ {
+ Font font = v.getFont();
+ FontMetrics fm = v.getContainer().getFontMetrics(font);
+ return fm.getDescent();
+ }
+
+ /**
+ * Determines the model offset, so that the text between <code>p0</code>
+ * and this offset fits within the span starting at <code>x</code> with
+ * the length of <code>len</code>.
+ *
+ * @param v the glyph view
+ * @param p0 the starting offset in the model
+ * @param x the start location in the view
+ * @param len the length of the span in the view
+ */
+ public int getBoundedPosition(GlyphView v, int p0, float x, float len)
+ {
+ TabExpander te = v.getTabExpander();
+ Segment txt = v.getText(p0, v.getEndOffset());
+ Font font = v.getFont();
+ FontMetrics fm = v.getContainer().getFontMetrics(font);
+ int pos = Utilities.getTabbedTextOffset(txt, fm, (int) x,
+ (int) (x + len), te, p0, false);
+ return pos;
+ }
+
+ /**
+ * Maps a visual position into a document location.
+ *
+ * @param v the glyph view
+ * @param x the X coordinate of the visual position
+ * @param y the Y coordinate of the visual position
+ * @param a the allocated region
+ * @param biasRet filled with the bias of the model location on method exit
+ *
+ * @return the model location that represents the specified view location
+ */
+ public int viewToModel(GlyphView v, float x, float y, Shape a,
+ Bias[] biasRet)
+ {
+ Rectangle b = a.getBounds();
+ assert b.contains(x, y) : "The coordinates are expected to be within the "
+ + "view's bounds: x=" + x + ", y=" + y
+ + "a=" + a;
+ int pos = getBoundedPosition(v, v.getStartOffset(), b.x, x - b.x);
+ return pos;
+ }
}
/**
@@ -250,6 +471,16 @@ public class GlyphView
GlyphPainter glyphPainter;
/**
+ * The start offset within the document for this view.
+ */
+ int startOffset;
+
+ /**
+ * The end offset within the document for this view.
+ */
+ int endOffset;
+
+ /**
* Creates a new <code>GlyphView</code> for the given <code>Element</code>.
*
* @param element the element that is rendered by this GlyphView
@@ -257,6 +488,8 @@ public class GlyphView
public GlyphView(Element element)
{
super(element);
+ startOffset = element.getStartOffset();
+ endOffset = element.getEndOffset();
}
/**
@@ -319,16 +552,21 @@ public class GlyphView
*/
public float getPreferredSpan(int axis)
{
- Element el = getElement();
+ float span = 0;
checkPainter();
GlyphPainter painter = getGlyphPainter();
- TabExpander tabEx = null;
- View parent = getParent();
- if (parent instanceof TabExpander)
- tabEx = (TabExpander) parent;
- // FIXME: Figure out how to determine the x parameter.
- float span = painter.getSpan(this, el.getStartOffset(), el.getEndOffset(),
- tabEx, 0.F);
+ if (axis == X_AXIS)
+ {
+ Element el = getElement();
+ TabExpander tabEx = null;
+ View parent = getParent();
+ if (parent instanceof TabExpander)
+ tabEx = (TabExpander) parent;
+ span = painter.getSpan(this, getStartOffset(), getEndOffset(),
+ tabEx, 0.F);
+ }
+ else
+ span = painter.getHeight(this);
return span;
}
@@ -372,8 +610,9 @@ public class GlyphView
*/
public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
{
- // FIXME: not implemented
- return 0;
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ return painter.viewToModel(this, x, y, a, b);
}
/**
@@ -383,12 +622,11 @@ public class GlyphView
*/
public TabExpander getTabExpander()
{
- // TODO: Figure out if this is correct.
TabExpander te = null;
View parent = getParent();
- if (parent instanceof ParagraphView)
- te = (ParagraphView) parent;
+ if (parent instanceof TabExpander)
+ te = (TabExpander) parent;
return te;
}
@@ -428,23 +666,26 @@ public class GlyphView
}
catch (BadLocationException ex)
{
- throw new AssertionError("BadLocationException must not be thrown "
- + "here");
+ AssertionError ae;
+ ae = new AssertionError("BadLocationException must not be thrown "
+ + "here");
+ ae.initCause(ex);
+ throw ae;
}
FontMetrics fm = null; // Fetch font metrics somewhere.
return Utilities.getTabbedTextWidth(seg, fm, 0, null, p0);
}
/**
- * Returns the starting offset in the document model of the portion
+ * Returns the start offset in the document model of the portion
* of text that this view is responsible for.
*
- * @return the starting offset in the document model of the portion
+ * @return the start offset in the document model of the portion
* of text that this view is responsible for
*/
- public int getBeginIndex()
+ public int getStartOffset()
{
- return getElement().getStartOffset();
+ return startOffset;
}
/**
@@ -454,9 +695,9 @@ public class GlyphView
* @return the end offset in the document model of the portion
* of text that this view is responsible for
*/
- public int getEndIndex()
+ public int getEndOffset()
{
- return getElement().getEndOffset();
+ return endOffset;
}
/**
@@ -476,8 +717,11 @@ public class GlyphView
}
catch (BadLocationException ex)
{
- throw new AssertionError("BadLocationException should not be "
- + "thrown here. p0 = " + p0 + ", p1 = " + p1);
+ AssertionError ae;
+ ae = new AssertionError("BadLocationException should not be "
+ + "thrown here. p0 = " + p0 + ", p1 = " + p1);
+ ae.initCause(ex);
+ throw ae;
}
return txt;
@@ -518,4 +762,332 @@ public class GlyphView
AttributeSet atts = el.getAttributes();
return StyleConstants.getForeground(atts);
}
+
+ /**
+ * Returns the background color which should be used to paint the text.
+ * This is fetched from the associated element's text attributes using
+ * {@link StyleConstants#getBackground}.
+ *
+ * @return the background color which should be used to paint the text
+ */
+ public Color getBackground()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.getBackground(atts);
+ }
+
+ /**
+ * Determines whether the text should be rendered strike-through or not. This
+ * is determined using the method
+ * {@link StyleConstants#isStrikeThrough(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered strike-through or not
+ */
+ public boolean isStikeThrough()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isStrikeThrough(atts);
+ }
+
+ /**
+ * Determines whether the text should be rendered as subscript or not. This
+ * is determined using the method
+ * {@link StyleConstants#isSubscript(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered as subscript or not
+ */
+ public boolean isSubscript()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isSubscript(atts);
+ }
+
+ /**
+ * Determines whether the text should be rendered as superscript or not. This
+ * is determined using the method
+ * {@link StyleConstants#isSuperscript(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered as superscript or not
+ */
+ public boolean isSuperscript()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isSuperscript(atts);
+ }
+
+ /**
+ * Determines whether the text should be rendered as underlined or not. This
+ * is determined using the method
+ * {@link StyleConstants#isUnderline(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered as underlined or not
+ */
+ public boolean isUnderline()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isUnderline(atts);
+ }
+
+ /**
+ * Creates and returns a shallow clone of this GlyphView. This is used by
+ * the {@link #createFragment} and {@link #breakView} methods.
+ *
+ * @return a shallow clone of this GlyphView
+ */
+ protected final Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ AssertionError err = new AssertionError("CloneNotSupportedException "
+ + "must not be thrown here");
+ err.initCause(ex);
+ throw err;
+ }
+ }
+
+ /**
+ * Tries to break the view near the specified view span <code>len</code>.
+ * The glyph view can only be broken in the X direction. For Y direction it
+ * returns itself.
+ *
+ * @param axis the axis for breaking, may be {@link View#X_AXIS} or
+ * {@link View#Y_AXIS}
+ * @param p0 the model location where the fragment should start
+ * @param pos the view position along the axis where the fragment starts
+ * @param len the desired length of the fragment view
+ *
+ * @return the fragment view, or <code>this</code> if breaking was not
+ * possible
+ */
+ public View breakView(int axis, int p0, float pos, float len)
+ {
+ if (axis == Y_AXIS)
+ return this;
+
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ int breakLocation = painter.getBoundedPosition(this, p0, pos, len);
+ // Try to find a suitable line break.
+ BreakIterator lineBreaker = BreakIterator.getLineInstance();
+ Segment txt = new Segment();
+ try
+ {
+ getDocument().getText(getStartOffset(), getEndOffset(), txt);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError("BadLocationException must not "
+ + "be thrown here.");
+ err.initCause(ex);
+ throw err;
+ }
+ lineBreaker.setText(txt);
+ int goodBreakLocation = lineBreaker.previous();
+ if (goodBreakLocation != BreakIterator.DONE)
+ breakLocation = goodBreakLocation;
+
+ View brokenView = createFragment(p0, breakLocation);
+ return brokenView;
+ }
+
+ /**
+ * Determines how well the specified view location is suitable for inserting
+ * a line break. If <code>axis</code> is <code>View.Y_AXIS</code>, then
+ * this method forwards to the superclass, if <code>axis</code> is
+ * <code>View.X_AXIS</code> then this method returns
+ * {@link View#ExcellentBreakWeight} if there is a suitable break location
+ * (usually whitespace) within the specified view span, or
+ * {@link View#GoodBreakWeight} if not.
+ *
+ * @param axis the axis along which the break weight is requested
+ * @param pos the starting view location
+ * @param len the length of the span at which the view should be broken
+ *
+ * @return the break weight
+ */
+ public int getBreakWeight(int axis, float pos, float len)
+ {
+ int weight;
+ if (axis == Y_AXIS)
+ weight = super.getBreakWeight(axis, pos, len);
+ else
+ {
+ // Determine the model locations at pos and pos + len.
+ int spanX = (int) getPreferredSpan(X_AXIS);
+ int spanY = (int) getPreferredSpan(Y_AXIS);
+ Rectangle dummyAlloc = new Rectangle(0, 0, spanX, spanY);
+ Position.Bias[] biasRet = new Position.Bias[1];
+ int offset1 = viewToModel(pos, spanY / 2, dummyAlloc, biasRet);
+ int offset2 = viewToModel(pos, spanY / 2, dummyAlloc, biasRet);
+ Segment txt = getText(offset1, offset2);
+ BreakIterator lineBreaker = BreakIterator.getLineInstance();
+ lineBreaker.setText(txt);
+ int breakLoc = lineBreaker.previous();
+ if (breakLoc == offset1)
+ weight = View.BadBreakWeight;
+ else if(breakLoc == BreakIterator.DONE)
+ weight = View.GoodBreakWeight;
+ else
+ weight = View.ExcellentBreakWeight;
+ }
+ return weight;
+ }
+
+ /**
+ * Receives notification that some text attributes have changed within the
+ * text fragment that this view is responsible for. This calls
+ * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
+ * both width and height.
+ *
+ * @param e the document event describing the change; not used here
+ * @param a the view allocation on screen; not used here
+ * @param vf the view factory; not used here
+ */
+ public void changedUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+ {
+ getParent().preferenceChanged(this, true, true);
+ }
+
+ /**
+ * Receives notification that some text has been inserted within the
+ * text fragment that this view is responsible for. This calls
+ * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
+ * width.
+ *
+ * @param e the document event describing the change; not used here
+ * @param a the view allocation on screen; not used here
+ * @param vf the view factory; not used here
+ */
+ public void insertUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+ {
+ getParent().preferenceChanged(this, true, false);
+ }
+
+ /**
+ * Receives notification that some text has been removed within the
+ * text fragment that this view is responsible for. This calls
+ * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
+ * width.
+ *
+ * @param e the document event describing the change; not used here
+ * @param a the view allocation on screen; not used here
+ * @param vf the view factory; not used here
+ */
+ public void removeUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+ {
+ getParent().preferenceChanged(this, true, false);
+ }
+
+ /**
+ * Creates a fragment view of this view that starts at <code>p0</code> and
+ * ends at <code>p1</code>.
+ *
+ * @param p0 the start location for the fragment view
+ * @param p1 the end location for the fragment view
+ *
+ * @return the fragment view
+ */
+ public View createFragment(int p0, int p1)
+ {
+ GlyphView fragment = (GlyphView) clone();
+ fragment.startOffset = p0;
+ fragment.endOffset = p1;
+ return fragment;
+ }
+
+ /**
+ * Returns the alignment of this view along the specified axis. For the Y
+ * axis this is <code>(height - descent) / height</code> for the used font,
+ * so that it is aligned along the baseline.
+ * For the X axis the superclass is called.
+ */
+ public float getAlignment(int axis)
+ {
+ float align;
+ if (axis == Y_AXIS)
+ {
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ float height = painter.getHeight(this);
+ float descent = painter.getDescent(this);
+ align = (height - descent) / height;
+ }
+ else
+ align = super.getAlignment(axis);
+
+ return align;
+ }
+
+ /**
+ * Returns the model location that should be used to place a caret when
+ * moving the caret through the document.
+ *
+ * @param pos the current model location
+ * @param bias the bias for <code>p</code>
+ * @param a the allocated region for the glyph view
+ * @param direction the direction from the current position; Must be one of
+ * {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
+ * {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
+ * @param biasRet filled with the bias of the resulting location when method
+ * returns
+ *
+ * @return the location within the document that should be used to place the
+ * caret when moving the caret around the document
+ *
+ * @throws BadLocationException if <code>pos</code> is an invalid model
+ * location
+ * @throws IllegalArgumentException if <code>d</code> is invalid
+ */
+ public int getNextVisualPositionFrom(int pos, Position.Bias bias, Shape a,
+ int direction, Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ return painter.getNextVisualPositionFrom(this, pos, bias, a, direction,
+ biasRet);
+ }
+
+ /**
+ * Returns the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction <code>d</code>.
+ *
+ * @param c the text component
+ * @param pos the document position
+ * @param b the bias for <code>pos</code>
+ * @param d the direction, must be either {@link SwingConstants#NORTH},
+ * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
+ * {@link SwingConstants#EAST}
+ * @param biasRet an array of {@link Position.Bias} that can hold at least
+ * one element, which is filled with the bias of the return position
+ * on method exit
+ *
+ * @return the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction
+ * <code>d</code>
+ *
+ * @throws BadLocationException if <code>pos</code> is not a valid offset in
+ * the document model
+ */
+ public int getNextVisualPositionFrom(JTextComponent c, int pos,
+ Position.Bias b, int d,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ // TODO: Implement this properly.
+ throw new AssertionError("Not implemented yet.");
+ }
}
diff --git a/libjava/classpath/javax/swing/text/IconView.java b/libjava/classpath/javax/swing/text/IconView.java
index c7e22b6c3eb..6dd0f7ad34a 100644
--- a/libjava/classpath/javax/swing/text/IconView.java
+++ b/libjava/classpath/javax/swing/text/IconView.java
@@ -41,6 +41,8 @@ package javax.swing.text;
import java.awt.Graphics;
import java.awt.Shape;
+import javax.swing.SwingConstants;
+
// TODO: Implement this class.
public class IconView
extends View
@@ -125,4 +127,34 @@ public class IconView
// FIXME: not implemented
return 0;
}
+
+ /**
+ * Returns the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction <code>d</code>.
+ *
+ * @param c the text component
+ * @param pos the document position
+ * @param b the bias for <code>pos</code>
+ * @param d the direction, must be either {@link SwingConstants#NORTH},
+ * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
+ * {@link SwingConstants#EAST}
+ * @param biasRet an array of {@link Position.Bias} that can hold at least
+ * one element, which is filled with the bias of the return position
+ * on method exit
+ *
+ * @return the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction
+ * <code>d</code>
+ *
+ * @throws BadLocationException if <code>pos</code> is not a valid offset in
+ * the document model
+ */
+ public int getNextVisualPositionFrom(JTextComponent c, int pos,
+ Position.Bias b, int d,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ // TODO: Implement this properly.
+ throw new AssertionError("Not implemented yet.");
+ }
}
diff --git a/libjava/classpath/javax/swing/text/InternationalFormatter.java b/libjava/classpath/javax/swing/text/InternationalFormatter.java
index cedaf59feeb..86300a70d8e 100644
--- a/libjava/classpath/javax/swing/text/InternationalFormatter.java
+++ b/libjava/classpath/javax/swing/text/InternationalFormatter.java
@@ -57,9 +57,8 @@ import javax.swing.JFormattedTextField;
public class InternationalFormatter
extends DefaultFormatter
{
-
- /** The serialVersoinUID. */
- private static final long serialVersionUID = 6941977820906408656L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 2436068675711756856L;
/** The format that handles value to string conversion. */
Format format;
diff --git a/libjava/classpath/javax/swing/text/JTextComponent.java b/libjava/classpath/javax/swing/text/JTextComponent.java
index b3fad79124c..83966bbdf47 100644
--- a/libjava/classpath/javax/swing/text/JTextComponent.java
+++ b/libjava/classpath/javax/swing/text/JTextComponent.java
@@ -50,9 +50,9 @@ import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.awt.event.InputMethodListener;
import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
@@ -72,7 +72,6 @@ import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;
-import javax.swing.Timer;
import javax.swing.TransferHandler;
import javax.swing.UIManager;
import javax.swing.event.CaretEvent;
@@ -89,6 +88,7 @@ public abstract class JTextComponent extends JComponent
/**
* AccessibleJTextComponent
*/
+ // FIXME: This inner class is a complete stub and needs to be implemented.
public class AccessibleJTextComponent extends AccessibleJComponent
implements AccessibleText, CaretListener, DocumentListener
{
@@ -99,6 +99,7 @@ public abstract class JTextComponent extends JComponent
*/
public AccessibleJTextComponent()
{
+ // Nothing to do here.
}
/**
@@ -301,50 +302,6 @@ public abstract class JTextComponent extends JComponent
}
/**
- * The timer that lets the caret blink.
- */
- private class CaretBlinkTimer
- extends Timer
- implements ActionListener
- {
- /**
- * Creates a new CaretBlinkTimer object with a default delay of 1 second.
- */
- public CaretBlinkTimer()
- {
- super(1000, null);
- addActionListener(this);
- }
-
- /**
- * Lets the caret blink.
- */
- public void actionPerformed(ActionEvent ev)
- {
- Caret c = caret;
- if (c != null)
- c.setVisible(!c.isVisible());
- }
-
- /**
- * Updates the blink delay according to the current caret.
- */
- public void update()
- {
- stop();
- Caret c = caret;
- if (c != null)
- {
- setDelay(c.getBlinkRate());
- if (editable)
- start();
- else
- c.setVisible(false);
- }
- }
- }
-
- /**
* According to <a
* href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">this
* report</a>, a pair of private classes wraps a {@link
@@ -604,8 +561,7 @@ public abstract class JTextComponent extends JComponent
}
}
- class DefaultTransferHandler
- extends TransferHandler
+ class DefaultTransferHandler extends TransferHandler
{
public boolean canImport(JComponent component, DataFlavor[] flavors)
{
@@ -631,23 +587,23 @@ public abstract class JTextComponent extends JComponent
int end = textComponent.getSelectionEnd();
if (start == end)
- return;
+ return;
try
- {
- // Copy text to clipboard.
- String data = textComponent.getDocument().getText(start, end);
- StringSelection selection = new StringSelection(data);
- clipboard.setContents(selection, null);
-
- // Delete selected text on cut action.
- if (action == MOVE)
- doc.remove(start, end - start);
- }
+ {
+ // Copy text to clipboard.
+ String data = textComponent.getDocument().getText(start, end);
+ StringSelection selection = new StringSelection(data);
+ clipboard.setContents(selection, null);
+
+ // Delete selected text on cut action.
+ if (action == MOVE)
+ doc.remove(start, end - start);
+ }
catch (BadLocationException e)
- {
- // Ignore this and do nothing.
- }
+ {
+ // Ignore this and do nothing.
+ }
}
public int getSourceActions()
@@ -661,30 +617,30 @@ public abstract class JTextComponent extends JComponent
DataFlavor[] flavors = transferable.getTransferDataFlavors();
if (flavors == null)
- return false;
+ return false;
for (int i = 0; i < flavors.length; ++i)
- if (flavors[i].equals(DataFlavor.stringFlavor))
- flavor = flavors[i];
+ if (flavors[i].equals(DataFlavor.stringFlavor))
+ flavor = flavors[i];
if (flavor == null)
- return false;
+ return false;
try
- {
- JTextComponent textComponent = (JTextComponent) component;
- String data = (String) transferable.getTransferData(flavor);
- textComponent.replaceSelection(data);
- return true;
- }
+ {
+ JTextComponent textComponent = (JTextComponent) component;
+ String data = (String) transferable.getTransferData(flavor);
+ textComponent.replaceSelection(data);
+ return true;
+ }
catch (IOException e)
- {
- // Ignored.
- }
+ {
+ // Ignored.
+ }
catch (UnsupportedFlavorException e)
- {
- // Ignored.
- }
+ {
+ // Ignored.
+ }
return false;
}
@@ -701,8 +657,6 @@ public abstract class JTextComponent extends JComponent
private char focusAccelerator = '\0';
private NavigationFilter navigationFilter;
- private CaretBlinkTimer caretBlinkTimer;
-
/**
* Get a Keymap from the global keymap table, by name.
*
@@ -960,8 +914,6 @@ public abstract class JTextComponent extends JComponent
creatingKeymap = true;
}
- caretBlinkTimer = new CaretBlinkTimer();
-
setFocusable(true);
setEditable(true);
enableEvents(AWTEvent.KEY_EVENT_MASK);
@@ -1021,12 +973,17 @@ public abstract class JTextComponent extends JComponent
{
try
{
- doc.remove(0, doc.getLength());
- doc.insertString(0, text, null);
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).replace(0, doc.getLength(), text, null);
+ else
+ {
+ doc.remove(0, doc.getLength());
+ doc.insertString(0, text, null);
+ }
}
catch (BadLocationException e)
{
- // This can never happen.
+ // This can never happen.
}
}
@@ -1044,12 +1001,12 @@ public abstract class JTextComponent extends JComponent
try
{
- return doc.getText(0, doc.getLength());
+ return doc.getText(0, doc.getLength());
}
catch (BadLocationException e)
{
- // This should never happen.
- return "";
+ // This should never happen.
+ return "";
}
}
@@ -1080,12 +1037,12 @@ public abstract class JTextComponent extends JComponent
{
try
{
- return doc.getText(getSelectionStart(), getSelectionEnd());
+ return doc.getText(getSelectionStart(), getSelectionEnd());
}
catch (BadLocationException e)
{
- // This should never happen.
- return null;
+ // This should never happen.
+ return null;
}
}
@@ -1105,7 +1062,8 @@ public abstract class JTextComponent extends JComponent
*/
protected String paramString()
{
- return "JTextComponent";
+ // TODO: Do something useful here.
+ return super.paramString();
}
/**
@@ -1194,14 +1152,6 @@ public abstract class JTextComponent extends JComponent
if (editable == newValue)
return;
- if (newValue == true)
- caretBlinkTimer.start();
- else
- {
- caretBlinkTimer.stop();
- caret.setVisible(false);
- }
-
boolean oldValue = editable;
editable = newValue;
firePropertyChange("editable", oldValue, newValue);
@@ -1230,8 +1180,6 @@ public abstract class JTextComponent extends JComponent
Caret oldCaret = caret;
caret = newCaret;
- caretBlinkTimer.update();
-
if (caret != null)
caret.install(this);
@@ -1399,7 +1347,7 @@ public abstract class JTextComponent extends JComponent
start = Math.max(start, 0);
start = Math.min(start, length);
- end = Math.max(end, 0);
+ end = Math.max(end, start);
end = Math.min(end, length);
setCaretPosition(start);
@@ -1422,28 +1370,28 @@ public abstract class JTextComponent extends JComponent
// If content is empty delete selection.
if (content == null)
{
- caret.setDot(dot);
- return;
+ caret.setDot(dot);
+ return;
}
try
{
- int start = getSelectionStart();
- int end = getSelectionEnd();
-
- // Remove selected text.
- if (dot != mark)
- doc.remove(start, end - start);
-
- // Insert new text.
- doc.insertString(start, content, null);
-
- // Set dot to new position.
- setCaretPosition(start + content.length());
+ int start = getSelectionStart();
+ int end = getSelectionEnd();
+
+ // Remove selected text.
+ if (dot != mark)
+ doc.remove(start, end - start);
+
+ // Insert new text.
+ doc.insertString(start, content, null);
+
+ // Set dot to new position.
+ setCaretPosition(start + content.length());
}
catch (BadLocationException e)
{
- // This should never happen.
+ // This should never happen.
}
}
@@ -1577,15 +1525,15 @@ public abstract class JTextComponent extends JComponent
// Install default TransferHandler if none set.
if (getTransferHandler() == null)
{
- if (defaultTransferHandler == null)
- defaultTransferHandler = new DefaultTransferHandler();
-
- setTransferHandler(defaultTransferHandler);
+ if (defaultTransferHandler == null)
+ defaultTransferHandler = new DefaultTransferHandler();
+
+ setTransferHandler(defaultTransferHandler);
}
// Perform action.
ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
- action.getValue(Action.NAME).toString());
+ action.getValue(Action.NAME).toString());
action.actionPerformed(event);
}
@@ -1669,5 +1617,20 @@ public abstract class JTextComponent extends JComponent
throws IOException
{
output.write(getText());
- }
+ }
+
+ /**
+ * Returns the tooltip text for this text component for the given mouse
+ * event. This forwards the call to
+ * {@link TextUI#getToolTipText(JTextComponent, Point)}.
+ *
+ * @param ev the mouse event
+ *
+ * @return the tooltip text for this text component for the given mouse
+ * event
+ */
+ public String getToolTipText(MouseEvent ev)
+ {
+ return getUI().getToolTipText(this, ev.getPoint());
+ }
}
diff --git a/libjava/classpath/javax/swing/text/LabelView.java b/libjava/classpath/javax/swing/text/LabelView.java
index a10391613cd..4890735b925 100644
--- a/libjava/classpath/javax/swing/text/LabelView.java
+++ b/libjava/classpath/javax/swing/text/LabelView.java
@@ -38,10 +38,57 @@ exception statement from your version. */
package javax.swing.text;
-// TODO: Implement this class.
-public class LabelView
- extends GlyphView
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Shape;
+
+import javax.swing.event.DocumentEvent;
+
+/**
+ * A {@link GlyphView} that caches the textattributes for most effective
+ * rendering.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class LabelView extends GlyphView
{
+
+ /**
+ * The background color.
+ */
+ Color background;
+
+ /**
+ * The foreground color.
+ */
+ Color foreground;
+
+ /**
+ * The background color.
+ */
+ Font font;
+
+ /**
+ * The strikethrough flag.
+ */
+ boolean strikeThrough;
+
+ /**
+ * The underline flag.
+ */
+ boolean underline;
+
+ /**
+ * The subscript flag.
+ */
+ boolean subscript;
+
+ /**
+ * The superscript flag.
+ */
+ boolean superscript;
+
/**
* Creates a new <code>GlyphView</code> for the given <code>Element</code>.
*
@@ -50,5 +97,194 @@ public class LabelView
public LabelView(Element element)
{
super(element);
+ setPropertiesFromAttributes();
+ }
+
+ /**
+ * Loads the properties of this label view from the element's text
+ * attributes. This method is called from the constructor and the
+ * {@link #changedUpdate} method
+ */
+ protected void setPropertiesFromAttributes()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ background = StyleConstants.getBackground(atts);
+ foreground = StyleConstants.getForeground(atts);
+ strikeThrough = StyleConstants.isStrikeThrough(atts);
+ subscript = StyleConstants.isSubscript(atts);
+ superscript = StyleConstants.isSuperscript(atts);
+ underline = StyleConstants.isUnderline(atts);
+
+ // Determine the font.
+ String family = StyleConstants.getFontFamily(atts);
+ int size = StyleConstants.getFontSize(atts);
+ int style = Font.PLAIN;
+ if (StyleConstants.isBold(atts))
+ style |= Font.BOLD;
+ if (StyleConstants.isItalic(atts))
+ style |= Font.ITALIC;
+ font = new Font(family, style, size);
+ }
+
+ /**
+ * Receives notification when text attributes change in the chunk of
+ * text that this view is responsible for. This simply calls
+ * {@link #setPropertiesFromAttributes()}.
+ *
+ * @param e the document event
+ * @param a the allocation of this view
+ * @param vf the view factory to use for creating new views
+ */
+ public void changedUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+ {
+ setPropertiesFromAttributes();
+ }
+
+ /**
+ * Returns the background color for the glyphs.
+ *
+ * @return the background color for the glyphs
+ */
+ public Color getBackground()
+ {
+ return background;
+ }
+
+ /**
+ * Sets the background color for the glyphs. A value of <code>null</code>
+ * means the background of the parent view should shine through.
+ *
+ * @param bg the background to set or <code>null</code>
+ *
+ * @since 1.5
+ */
+ protected void setBackground(Color bg)
+ {
+ background = bg;
+ }
+
+ /**
+ * Returns the foreground color for the glyphs.
+ *
+ * @return the foreground color for the glyphs
+ */
+ public Color getForeground()
+ {
+ return foreground;
+ }
+
+ /**
+ * Returns the font for the glyphs.
+ *
+ * @return the font for the glyphs
+ */
+ public Font getFont()
+ {
+ return font;
+ }
+
+ /**
+ * Returns the font metrics of the current font.
+ *
+ * @return the font metrics of the current font
+ *
+ * @deprecated this is not used anymore
+ */
+ protected FontMetrics getFontMetrics()
+ {
+ return getContainer().getGraphics().getFontMetrics(font);
+ }
+
+ /**
+ * Returns <code>true</code> if the glyphs are rendered underlined,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the glyphs are rendered underlined,
+ * <code>false</code> otherwise
+ */
+ public boolean isUnderline()
+ {
+ return underline;
+ }
+
+ /**
+ * Sets the underline flag.
+ *
+ * @param flag <code>true</code> if the glyphs are rendered underlined,
+ * <code>false</code> otherwise
+ */
+ protected void setUnderline(boolean flag)
+ {
+ underline = flag;
+ }
+
+ /**
+ * Returns <code>true</code> if the glyphs are rendered as subscript,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the glyphs are rendered as subscript,
+ * <code>false</code> otherwise
+ */
+ public boolean isSubscript()
+ {
+ return subscript;
+ }
+
+ /**
+ * Sets the subscript flag.
+ *
+ * @param flag <code>true</code> if the glyphs are rendered as subscript,
+ * <code>false</code> otherwise
+ */
+ protected void setSubscript(boolean flag)
+ {
+ subscript = flag;
+ }
+
+ /**
+ * Returns <code>true</code> if the glyphs are rendered as superscript,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the glyphs are rendered as superscript,
+ * <code>false</code> otherwise
+ */
+ public boolean isSuperscript()
+ {
+ return superscript;
+ }
+
+ /**
+ * Sets the superscript flag.
+ *
+ * @param flag <code>true</code> if the glyphs are rendered as superscript,
+ * <code>false</code> otherwise
+ */
+ protected void setSuperscript(boolean flag)
+ {
+ superscript = flag;
+ }
+
+ /**
+ * Returns <code>true</code> if the glyphs are rendered strike-through,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the glyphs are rendered strike-through,
+ * <code>false</code> otherwise
+ */
+ public boolean isStrikeThrough()
+ {
+ return strikeThrough;
+ }
+
+ /**
+ * Sets the strike-through flag.
+ *
+ * @param flag <code>true</code> if the glyphs are rendered strike-through,
+ * <code>false</code> otherwise
+ */
+ protected void setStrikeThrough(boolean flag)
+ {
+ strikeThrough = flag;
}
}
diff --git a/libjava/classpath/javax/swing/text/LayoutQueue.java b/libjava/classpath/javax/swing/text/LayoutQueue.java
index 83433b6eef5..b0c84b972b2 100644
--- a/libjava/classpath/javax/swing/text/LayoutQueue.java
+++ b/libjava/classpath/javax/swing/text/LayoutQueue.java
@@ -57,6 +57,7 @@ public class LayoutQueue
*/
public LayoutQueue()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/text/ParagraphView.java b/libjava/classpath/javax/swing/text/ParagraphView.java
index 6c6006a2a0f..6fb121f949e 100644
--- a/libjava/classpath/javax/swing/text/ParagraphView.java
+++ b/libjava/classpath/javax/swing/text/ParagraphView.java
@@ -59,6 +59,11 @@ public class ParagraphView extends FlowView implements TabExpander
{
super(el, X_AXIS);
}
+ public float getAlignment(int axis)
+ {
+ // FIXME: This is very likely not 100% correct. Work this out.
+ return 0.0F;
+ }
}
/**
@@ -86,4 +91,29 @@ public class ParagraphView extends FlowView implements TabExpander
{
return new Row(getElement());
}
+
+ /**
+ * Returns the alignment for this paragraph view for the specified axis.
+ * For the X_AXIS the paragraph view will be aligned at it's left edge
+ * (0.0F). For the Y_AXIS the paragraph view will be aligned at the
+ * center of it's first row.
+ *
+ * @param axis the axis which is examined
+ *
+ * @return the alignment for this paragraph view for the specified axis
+ */
+ public float getAlignment(int axis)
+ {
+ if (axis == X_AXIS)
+ return 0.0F;
+ else if (getViewCount() > 0)
+ {
+
+ float prefHeight = getPreferredSpan(Y_AXIS);
+ float firstRowHeight = getView(0).getPreferredSpan(Y_AXIS);
+ return (firstRowHeight / 2.F) / prefHeight;
+ }
+ else
+ return 0.0F;
+ }
}
diff --git a/libjava/classpath/javax/swing/text/PlainDocument.java b/libjava/classpath/javax/swing/text/PlainDocument.java
index 71070e92da7..9e600c4c908 100644
--- a/libjava/classpath/javax/swing/text/PlainDocument.java
+++ b/libjava/classpath/javax/swing/text/PlainDocument.java
@@ -132,8 +132,8 @@ public class PlainDocument extends AbstractDocument
// collapse elements if the removal spans more than 1 line
Element newEl = createLeafElement(rootElement,
SimpleAttributeSet.EMPTY,
- start, end - len);
- rootElement.replace(i1, i2 - i1, new Element[]{ newEl });
+ start, end);
+ rootElement.replace(i1, i2 - i1 + 1, new Element[]{ newEl });
}
}
@@ -147,4 +147,28 @@ public class PlainDocument extends AbstractDocument
Element root = getDefaultRootElement();
return root.getElement(root.getElementIndex(pos));
}
+
+ /**
+ * Inserts a string into the document. If the document property
+ * '<code>filterNewLines</code>' is set to <code>Boolean.TRUE</code>, then
+ * all newlines in the inserted string are replaced by space characters,
+ * otherwise the superclasses behaviour is executed.
+ *
+ * Inserting content causes a write lock to be acquired during this method
+ * call.
+ *
+ * @param offs the offset at which to insert the string
+ * @param str the string to be inserted
+ * @param atts the text attributes of the string to be inserted
+ *
+ * @throws BadLocationException
+ */
+ public void insertString(int offs, String str, AttributeSet atts)
+ throws BadLocationException
+ {
+ String string = str;
+ if (Boolean.TRUE.equals(getProperty("filterNewlines")))
+ string = str.replaceAll("\n", " ");
+ super.insertString(offs, string, atts);
+ }
}
diff --git a/libjava/classpath/javax/swing/text/PlainView.java b/libjava/classpath/javax/swing/text/PlainView.java
index 91d7547e77c..9f5ee8ad3c8 100644
--- a/libjava/classpath/javax/swing/text/PlainView.java
+++ b/libjava/classpath/javax/swing/text/PlainView.java
@@ -46,15 +46,35 @@ import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
-public class PlainView extends View
- implements TabExpander
+import javax.swing.SwingConstants;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentEvent.ElementChange;
+
+public class PlainView extends View implements TabExpander
{
Color selectedColor;
Color unselectedColor;
+
+ /**
+ * The color that is used to draw disabled text fields.
+ */
+ Color disabledColor;
+
Font font;
+ /** The length of the longest line in the Document **/
+ float maxLineLength = -1;
+
+ /** The longest line in the Document **/
+ Element longestLine = null;
+
protected FontMetrics metrics;
+ /**
+ * The instance returned by {@link #getLineBuffer()}.
+ */
+ private transient Segment lineBuffer;
+
public PlainView(Element elem)
{
super(elem);
@@ -104,7 +124,7 @@ public class PlainView extends View
// Get the rectangle for position.
Element line = getElement().getElement(lineIndex);
int lineStart = line.getStartOffset();
- Segment segment = new Segment();
+ Segment segment = getLineBuffer();
document.getText(lineStart, position - lineStart, segment);
int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,
this, lineStart);
@@ -129,7 +149,9 @@ public class PlainView extends View
}
catch (BadLocationException e)
{
- // This should never happen.
+ AssertionError ae = new AssertionError("Unexpected bad location");
+ ae.initCause(e);
+ throw ae;
}
}
@@ -137,7 +159,7 @@ public class PlainView extends View
throws BadLocationException
{
g.setColor(selectedColor);
- Segment segment = new Segment();
+ Segment segment = getLineBuffer();
getDocument().getText(p0, p1 - p0, segment);
return Utilities.drawTabbedText(segment, x, y, g, this, 0);
}
@@ -145,8 +167,13 @@ public class PlainView extends View
protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1)
throws BadLocationException
{
- g.setColor(unselectedColor);
- Segment segment = new Segment();
+ JTextComponent textComponent = (JTextComponent) getContainer();
+ if (textComponent.isEnabled())
+ g.setColor(unselectedColor);
+ else
+ g.setColor(disabledColor);
+
+ Segment segment = getLineBuffer();
getDocument().getText(p0, p1 - p0, segment);
return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
}
@@ -161,7 +188,8 @@ public class PlainView extends View
g.setFont(textComponent.getFont());
selectedColor = textComponent.getSelectedTextColor();
unselectedColor = textComponent.getForeground();
-
+ disabledColor = textComponent.getDisabledTextColor();
+
Rectangle rect = s.getBounds();
// FIXME: Text may be scrolled.
@@ -176,9 +204,19 @@ public class PlainView extends View
}
}
+ /**
+ * Returns the tab size of a tab. Checks the Document's
+ * properties for PlainDocument.tabSizeAttribute and returns it if it is
+ * defined, otherwise returns 8.
+ *
+ * @return the tab size.
+ */
protected int getTabSize()
{
- return 8;
+ Object tabSize = getDocument().getProperty(PlainDocument.tabSizeAttribute);
+ if (tabSize == null)
+ return 8;
+ return ((Integer)tabSize).intValue();
}
/**
@@ -191,10 +229,54 @@ public class PlainView extends View
*/
public float nextTabStop(float x, int tabStop)
{
- float tabSizePixels = getTabSize() + metrics.charWidth('m');
+ float tabSizePixels = getTabSize() * metrics.charWidth('m');
return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels;
}
+ /**
+ * Returns the length of the longest line, used for getting the span
+ * @return the length of the longest line
+ */
+ float determineMaxLineLength()
+ {
+ // if the longest line is cached, return the cached value
+ if (maxLineLength != -1)
+ return maxLineLength;
+
+ // otherwise we have to go through all the lines and find it
+ Element el = getElement();
+ Segment seg = getLineBuffer();
+ float span = 0;
+ for (int i = 0; i < el.getElementCount(); i++)
+ {
+ Element child = el.getElement(i);
+ int start = child.getStartOffset();
+ int end = child.getEndOffset();
+ try
+ {
+ el.getDocument().getText(start, end - start, seg);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError ae = new AssertionError("Unexpected bad location");
+ ae.initCause(ex);
+ throw ae;
+ }
+
+ if (seg == null || seg.array == null || seg.count == 0)
+ continue;
+
+ int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
+ if (width > span)
+ {
+ longestLine = child;
+ span = width;
+ }
+ }
+ maxLineLength = span;
+ return maxLineLength;
+ }
+
public float getPreferredSpan(int axis)
{
if (axis != X_AXIS && axis != Y_AXIS)
@@ -205,36 +287,16 @@ public class PlainView extends View
float span = 0;
Element el = getElement();
- Document doc = el.getDocument();
- Segment seg = new Segment();
switch (axis)
{
case X_AXIS:
- // calculate the maximum of the line's widths
- for (int i = 0; i < el.getElementCount(); i++)
- {
- Element child = el.getElement(i);
- int start = child.getStartOffset();
- int end = child.getEndOffset();
- try {
- doc.getText(start, start + end, seg);
- }
- catch (BadLocationException ex)
- {
- // throw new ClasspathAssertionError
- // ("no BadLocationException should be thrown here");
- }
- int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
- span = Math.max(span, width);
- }
- break;
+ span = determineMaxLineLength();
case Y_AXIS:
default:
span = metrics.getHeight() * el.getElementCount();
break;
}
-
return span;
}
@@ -252,8 +314,251 @@ public class PlainView extends View
*/
public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
{
- // FIXME: not implemented
- return 0;
+ Rectangle rec = a.getBounds();
+ Document doc = getDocument();
+ Element root = doc.getDefaultRootElement();
+
+ // PlainView doesn't support line-wrapping so we can find out which
+ // Element was clicked on just by the y-position
+ int lineClicked = (int) (y - rec.y) / metrics.getHeight();
+ if (lineClicked >= root.getElementCount())
+ return getEndOffset() - 1;
+
+ Element line = root.getElement(lineClicked);
+ Segment s = getLineBuffer();
+ int start = line.getStartOffset();
+ // We don't want the \n at the end of the line.
+ int end = line.getEndOffset() - 1;
+ try
+ {
+ doc.getText(start, end - start, s);
+ }
+ catch (BadLocationException ble)
+ {
+ AssertionError ae = new AssertionError("Unexpected bad location");
+ ae.initCause(ble);
+ throw ae;
+ }
+
+ int pos = Utilities.getTabbedTextOffset(s, metrics, rec.x, (int)x, this, start);
+ return Math.max (0, pos);
+ }
+
+ /**
+ * Since insertUpdate and removeUpdate each deal with children
+ * Elements being both added and removed, they both have to perform
+ * the same checks. So they both simply call this method.
+ * @param changes the DocumentEvent for the changes to the Document.
+ * @param a the allocation of the View.
+ * @param f the ViewFactory to use for rebuilding.
+ */
+ protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f)
+ {
+ Element el = getElement();
+ ElementChange ec = changes.getChange(el);
+
+ // If ec is null then no lines were added or removed, just
+ // repaint the changed line
+ if (ec == null)
+ {
+ int line = getElement().getElementIndex(changes.getOffset());
+ damageLineRange(line, line, a, getContainer());
+ return;
+ }
+
+ Element[] removed = ec.getChildrenRemoved();
+ Element[] newElements = ec.getChildrenAdded();
+
+ // If no Elements were added or removed, we just want to repaint
+ // the area containing the line that was modified
+ if (removed == null && newElements == null)
+ {
+ int line = getElement().getElementIndex(changes.getOffset());
+ damageLineRange(line, line, a, getContainer());
+ return;
+ }
+
+ // Check to see if we removed the longest line, if so we have to
+ // search through all lines and find the longest one again
+ if (removed != null)
+ {
+ for (int i = 0; i < removed.length; i++)
+ if (removed[i].equals(longestLine))
+ {
+ // reset maxLineLength and search through all lines for longest one
+ maxLineLength = -1;
+ determineMaxLineLength();
+ ((JTextComponent)getContainer()).repaint();
+ return;
+ }
+ }
+
+ // If we've reached here, that means we haven't removed the longest line
+ if (newElements == null)
+ {
+ // No lines were added, just repaint the container and exit
+ ((JTextComponent)getContainer()).repaint();
+ return;
+ }
+
+ // Make sure we have the metrics
+ updateMetrics();
+
+ // If we've reached here, that means we haven't removed the longest line
+ // and we have added at least one line, so we have to check if added lines
+ // are longer than the previous longest line
+ Segment seg = getLineBuffer();
+ float longestNewLength = 0;
+ Element longestNewLine = null;
+
+ // Loop through the added lines to check their length
+ for (int i = 0; i < newElements.length; i++)
+ {
+ Element child = newElements[i];
+ int start = child.getStartOffset();
+ int end = child.getEndOffset();
+ try
+ {
+ el.getDocument().getText(start, end - start, seg);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError ae = new AssertionError("Unexpected bad location");
+ ae.initCause(ex);
+ throw ae;
+ }
+
+ if (seg == null || seg.array == null || seg.count == 0)
+ continue;
+
+ int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
+ if (width > longestNewLength)
+ {
+ longestNewLine = child;
+ longestNewLength = width;
+ }
+ }
+
+ // Check if the longest of the new lines is longer than our previous
+ // longest line, and if so update our values
+ if (longestNewLength > maxLineLength)
+ {
+ maxLineLength = longestNewLength;
+ longestLine = longestNewLine;
+ }
+ // Repaint the container
+ ((JTextComponent)getContainer()).repaint();
+ }
+
+ /**
+ * This method is called when something is inserted into the Document
+ * that this View is displaying.
+ *
+ * @param changes the DocumentEvent for the changes.
+ * @param a the allocation of the View
+ * @param f the ViewFactory used to rebuild
+ */
+ public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f)
+ {
+ updateDamage(changes, a, f);
+ }
+
+ /**
+ * This method is called when something is removed from the Document
+ * that this View is displaying.
+ *
+ * @param changes the DocumentEvent for the changes.
+ * @param a the allocation of the View
+ * @param f the ViewFactory used to rebuild
+ */
+ public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f)
+ {
+ updateDamage(changes, a, f);
+ }
+
+ /**
+ * This method is called when attributes were changed in the
+ * Document in a location that this view is responsible for.
+ */
+ public void changedUpdate (DocumentEvent changes, Shape a, ViewFactory f)
+ {
+ updateDamage(changes, a, f);
+ }
+
+ /**
+ * Repaint the given line range. This is called from insertUpdate,
+ * changedUpdate, and removeUpdate when no new lines were added
+ * and no lines were removed, to repaint the line that was
+ * modified.
+ *
+ * @param line0 the start of the range
+ * @param line1 the end of the range
+ * @param a the rendering region of the host
+ * @param host the Component that uses this View (used to call repaint
+ * on that Component)
+ *
+ * @since 1.4
+ */
+ protected void damageLineRange (int line0, int line1, Shape a, Component host)
+ {
+ if (a == null)
+ return;
+
+ Rectangle rec0 = lineToRect(a, line0);
+ Rectangle rec1 = lineToRect(a, line1);
+
+ if (rec0 == null || rec1 == null)
+ // something went wrong, repaint the entire host to be safe
+ host.repaint();
+ else
+ {
+ Rectangle repaintRec = rec0.union(rec1);
+ host.repaint();
+ }
+ }
+
+ /**
+ * Provides a {@link Segment} object, that can be used to fetch text from
+ * the document.
+ *
+ * @returna {@link Segment} object, that can be used to fetch text from
+ * the document
+ */
+ protected Segment getLineBuffer()
+ {
+ if (lineBuffer == null)
+ lineBuffer = new Segment();
+ return lineBuffer;
+ }
+
+ /**
+ * Returns the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction <code>d</code>.
+ *
+ * @param c the text component
+ * @param pos the document position
+ * @param b the bias for <code>pos</code>
+ * @param d the direction, must be either {@link SwingConstants#NORTH},
+ * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
+ * {@link SwingConstants#EAST}
+ * @param biasRet an array of {@link Position.Bias} that can hold at least
+ * one element, which is filled with the bias of the return position
+ * on method exit
+ *
+ * @return the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction
+ * <code>d</code>
+ *
+ * @throws BadLocationException if <code>pos</code> is not a valid offset in
+ * the document model
+ */
+ public int getNextVisualPositionFrom(JTextComponent c, int pos,
+ Position.Bias b, int d,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ // TODO: Implement this properly.
+ throw new AssertionError("Not implemented yet.");
}
}
diff --git a/libjava/classpath/javax/swing/text/Segment.java b/libjava/classpath/javax/swing/text/Segment.java
index 92d850016d9..84e0e700f2e 100644
--- a/libjava/classpath/javax/swing/text/Segment.java
+++ b/libjava/classpath/javax/swing/text/Segment.java
@@ -39,8 +39,7 @@ package javax.swing.text;
import java.text.CharacterIterator;
-public class Segment
- implements Cloneable, CharacterIterator
+public class Segment implements Cloneable, CharacterIterator
{
private boolean partialReturn;
private int current;
@@ -51,6 +50,7 @@ public class Segment
public Segment()
{
+ // Nothing to do here.
}
public Segment(char[] array, int offset, int count)
diff --git a/libjava/classpath/javax/swing/text/SimpleAttributeSet.java b/libjava/classpath/javax/swing/text/SimpleAttributeSet.java
index 3ef5db61d43..0c9f607b196 100644
--- a/libjava/classpath/javax/swing/text/SimpleAttributeSet.java
+++ b/libjava/classpath/javax/swing/text/SimpleAttributeSet.java
@@ -45,6 +45,9 @@ import java.util.Hashtable;
public class SimpleAttributeSet
implements MutableAttributeSet, Serializable, Cloneable
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 8267656273837665219L;
+
public static final AttributeSet EMPTY = new SimpleAttributeSet();
Hashtable tab;
@@ -84,12 +87,34 @@ public class SimpleAttributeSet
return s;
}
+ /**
+ * Returns true if the given name and value represent an attribute
+ * found either in this AttributeSet or in its resolve parent hierarchy.
+ * @param name the key for the attribute
+ * @param value the value for the attribute
+ * @return true if the attribute is found here or in this set's resolve
+ * parent hierarchy
+ */
public boolean containsAttribute(Object name, Object value)
{
+ return (tab.containsKey(name) && tab.get(name).equals(value)) ||
+ (getResolveParent() != null && getResolveParent().
+ containsAttribute(name, value));
+ }
+
+ /**
+ * Returns true if the given name and value are found in this AttributeSet.
+ * Does not check the resolve parent.
+ * @param name the key for the attribute
+ * @param value the value for the attribute
+ * @return true if the attribute is found in this AttributeSet
+ */
+ boolean containsAttributeLocally(Object name, Object value)
+ {
return tab.containsKey(name)
&& tab.get(name).equals(value);
}
-
+
public boolean containsAttributes(AttributeSet attributes)
{
Enumeration e = attributes.getAttributeNames();
@@ -110,9 +135,9 @@ public class SimpleAttributeSet
public boolean equals(Object obj)
{
- return (obj != null)
- && (obj instanceof SimpleAttributeSet)
- && ((SimpleAttributeSet)obj).tab.equals(this.tab);
+ return
+ (obj instanceof AttributeSet)
+ && this.isEqual((AttributeSet) obj);
}
public Object getAttribute(Object name)
@@ -157,10 +182,16 @@ public class SimpleAttributeSet
{
return tab.isEmpty();
}
-
+
+ /**
+ * Returns true if the given set has the same number of attributes
+ * as this set and <code>containsAttributes(attr)</code> returns
+ * true.
+ */
public boolean isEqual(AttributeSet attr)
{
- return this.equals(attr);
+ return getAttributeCount() == attr.getAttributeCount()
+ && this.containsAttributes(attr);
}
public void removeAttribute(Object name)
@@ -168,9 +199,21 @@ public class SimpleAttributeSet
tab.remove(name);
}
+ /**
+ * Removes attributes from this set if they are found in the
+ * given set. Only attributes whose key AND value are removed.
+ * Removes attributes only from this set, not from the resolving parent.
+ */
public void removeAttributes(AttributeSet attributes)
{
- removeAttributes(attributes.getAttributeNames());
+ Enumeration e = attributes.getAttributeNames();
+ while (e.hasMoreElements())
+ {
+ Object name = e.nextElement();
+ Object val = attributes.getAttribute(name);
+ if (containsAttributeLocally(name, val))
+ removeAttribute(name);
+ }
}
public void removeAttributes(Enumeration names)
diff --git a/libjava/classpath/javax/swing/text/StringContent.java b/libjava/classpath/javax/swing/text/StringContent.java
index bedf480d4ec..7db377a1c9b 100644
--- a/libjava/classpath/javax/swing/text/StringContent.java
+++ b/libjava/classpath/javax/swing/text/StringContent.java
@@ -56,6 +56,9 @@ import javax.swing.undo.UndoableEdit;
*/
public final class StringContent implements AbstractDocument.Content, Serializable
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 4755994433709540381L;
+
// This is package-private to avoid an accessor method.
char[] content;
diff --git a/libjava/classpath/javax/swing/text/StyleConstants.java b/libjava/classpath/javax/swing/text/StyleConstants.java
index 3f973f22631..598eaf621bc 100644
--- a/libjava/classpath/javax/swing/text/StyleConstants.java
+++ b/libjava/classpath/javax/swing/text/StyleConstants.java
@@ -54,11 +54,13 @@ public class StyleConstants
public static final Object BidiLevel = CharacterConstants.BidiLevel;
public static final Object Bold = CharacterConstants.Bold;
public static final Object ComponentAttribute = CharacterConstants.ComponentAttribute;
- public static final Object FontFamily = CharacterConstants.Family;
+ public static final Object Family = CharacterConstants.Family;
+ public static final Object FontFamily = CharacterConstants.Family;
public static final Object FontSize = CharacterConstants.Size;
public static final Object Foreground = CharacterConstants.Foreground;
public static final Object IconAttribute = CharacterConstants.IconAttribute;
public static final Object Italic = CharacterConstants.Italic;
+ public static final Object Size = CharacterConstants.Size;
public static final Object StrikeThrough = CharacterConstants.StrikeThrough;
public static final Object Subscript = CharacterConstants.Subscript;
public static final Object Superscript = CharacterConstants.Superscript;
@@ -109,7 +111,7 @@ public class StyleConstants
if (a.isDefined(Background))
return (Color) a.getAttribute(Background);
else
- return Color.BLACK;
+ return Color.WHITE;
}
public static int getBidiLevel(AttributeSet a)
diff --git a/libjava/classpath/javax/swing/text/StyleContext.java b/libjava/classpath/javax/swing/text/StyleContext.java
index ae11622ffc6..6c4e299455f 100644
--- a/libjava/classpath/javax/swing/text/StyleContext.java
+++ b/libjava/classpath/javax/swing/text/StyleContext.java
@@ -57,9 +57,15 @@ import javax.swing.event.EventListenerList;
public class StyleContext
implements Serializable, AbstractDocument.AttributeContext
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 8042858831190784241L;
+
public class NamedStyle
implements Serializable, Style
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -6690628971806226374L;
+
protected ChangeEvent changeEvent;
protected EventListenerList listenerList;
@@ -288,7 +294,7 @@ public class StyleContext
public boolean equals(Object obj)
{
return
- (obj instanceof SmallAttributeSet)
+ (obj instanceof AttributeSet)
&& this.isEqual((AttributeSet)obj);
}
@@ -300,9 +306,14 @@ public class StyleContext
return attrs[i+1];
}
- Object p = getResolveParent();
- if (p != null && p instanceof AttributeSet)
- return (((AttributeSet)p).getAttribute(key));
+ // Check the resolve parent, unless we're looking for the
+ // ResolveAttribute, which would cause an infinite loop
+ if (!(key.equals(ResolveAttribute)))
+ {
+ Object p = getResolveParent();
+ if (p != null && p instanceof AttributeSet)
+ return (((AttributeSet)p).getAttribute(key));
+ }
return null;
}
diff --git a/libjava/classpath/javax/swing/text/StyledDocument.java b/libjava/classpath/javax/swing/text/StyledDocument.java
index ea277540f23..168e1b116f3 100644
--- a/libjava/classpath/javax/swing/text/StyledDocument.java
+++ b/libjava/classpath/javax/swing/text/StyledDocument.java
@@ -45,101 +45,96 @@ import java.awt.Font;
* @author Andrew Selkirk
* @version 1.0
*/
-public interface StyledDocument extends Document {
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * addStyle
- * @param nm TODO
- * @param rent TODO
- * @returns Style
- */
- Style addStyle(String nm, Style parent);
-
- /**
- * removeStyle
- * @param nm TODO
- */
- void removeStyle(String nm);
-
- /**
- * getStyle
- * @param nm TODO
- * @returns Style
- */
- Style getStyle(String nm);
-
- /**
- * setCharacterAttributes
- * @param offset TODO
- * @param length TODO
- * @param set TODO
- * @param replace TODO
- */
- void setCharacterAttributes(int offset, int length,
- AttributeSet set, boolean replace);
-
- /**
- * setParagraphAttributes
- * @param offset TODO
- * @param length TODO
- * @param set TODO
- * @param replace TODO
- */
- void setParagraphAttributes(int offset, int length,
- AttributeSet set, boolean replace);
-
- /**
- * getLogicalStyle
- * @param position TODO
- * @returns Style
- */
- Style getLogicalStyle(int position);
-
- /**
- * setLogicalStyle
- * @param position TODO
- * @param style TODO
- */
- void setLogicalStyle(int position, Style style);
-
- /**
- * getParagraphElement
- * @param position TODO
- * @returns Element
- */
- Element getParagraphElement(int position);
-
- /**
- * getCharacterElement
- * @param position TODO
- * @returns Element
- */
- Element getCharacterElement(int position);
-
- /**
- * getForeground
- * @param set TODO
- * @returns Color
- */
- Color getForeground(AttributeSet set);
-
- /**
- * getBackground
- * @param set TODO
- * @returns Color
- */
- Color getBackground(AttributeSet set);
-
- /**
- * getFont
- * @param set TODO
- * @returns Font
- */
- Font getFont(AttributeSet set);
-
-
-} // StyledDocument
+public interface StyledDocument extends Document
+{
+ /**
+ * addStyle
+ * @param nm TODO
+ * @param parent TODO
+ * @returns Style
+ */
+ Style addStyle(String nm, Style parent);
+
+ /**
+ * removeStyle
+ * @param nm TODO
+ */
+ void removeStyle(String nm);
+
+ /**
+ * getStyle
+ * @param nm TODO
+ * @returns Style
+ */
+ Style getStyle(String nm);
+
+ /**
+ * setCharacterAttributes
+ * @param offset TODO
+ * @param length TODO
+ * @param set TODO
+ * @param replace TODO
+ */
+ void setCharacterAttributes(int offset, int length, AttributeSet set,
+ boolean replace);
+
+ /**
+ * setParagraphAttributes
+ * @param offset TODO
+ * @param length TODO
+ * @param set TODO
+ * @param replace TODO
+ */
+ void setParagraphAttributes(int offset, int length, AttributeSet set,
+ boolean replace);
+
+ /**
+ * getLogicalStyle
+ * @param position TODO
+ * @returns Style
+ */
+ Style getLogicalStyle(int position);
+
+ /**
+ * setLogicalStyle
+ * @param position TODO
+ * @param style TODO
+ */
+ void setLogicalStyle(int position, Style style);
+
+ /**
+ * getParagraphElement
+ * @param position TODO
+ * @returns Element
+ */
+ Element getParagraphElement(int position);
+
+ /**
+ * getCharacterElement
+ * @param position TODO
+ * @returns Element
+ */
+ Element getCharacterElement(int position);
+
+ /**
+ * getForeground
+ * @param set TODO
+ * @returns Color
+ */
+ Color getForeground(AttributeSet set);
+
+ /**
+ * getBackground
+ * @param set TODO
+ * @returns Color
+ */
+ Color getBackground(AttributeSet set);
+
+ /**
+ * getFont
+ * @param set TODO
+ * @returns Font
+ */
+ Font getFont(AttributeSet set);
+
+}
diff --git a/libjava/classpath/javax/swing/text/StyledEditorKit.java b/libjava/classpath/javax/swing/text/StyledEditorKit.java
index 89c4cf18ee4..e71f992b534 100644
--- a/libjava/classpath/javax/swing/text/StyledEditorKit.java
+++ b/libjava/classpath/javax/swing/text/StyledEditorKit.java
@@ -40,13 +40,9 @@ package javax.swing.text;
import java.awt.Color;
import java.awt.event.ActionEvent;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.io.Serializable;
import javax.swing.Action;
import javax.swing.JEditorPane;
-import javax.swing.JTextPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
@@ -460,11 +456,11 @@ public class StyledEditorKit extends DefaultEditorKit
* <code>StyledEditorKit</code>, namely the following types of Elements:
*
* <ul>
- * <li>{@link AbstractDocument.ContentElementName}</li>
- * <li>{@link AbstractDocument.ParagraphElementName}</li>
- * <li>{@link AbstractDocument.SectionElementName}</li>
- * <li>{@link StyleContext.ComponentElementName}</li>
- * <li>{@link StyleContext.IconElementName}</li>
+ * <li>{@link AbstractDocument#ContentElementName}</li>
+ * <li>{@link AbstractDocument#ParagraphElementName}</li>
+ * <li>{@link AbstractDocument#SectionElementName}</li>
+ * <li>{@link StyleConstants#ComponentElementName}</li>
+ * <li>{@link StyleConstants#IconElementName}</li>
* </ul>
*/
static class StyledViewFactory
@@ -667,11 +663,11 @@ public class StyledEditorKit extends DefaultEditorKit
* namely the following types of <code>Element</code>s:
*
* <ul>
- * <li>{@link AbstractDocument.ContentElementName}</li>
- * <li>{@link AbstractDocument.ParagraphElementName}</li>
- * <li>{@link AbstractDocument.SectionElementName}</li>
- * <li>{@link StyleContext.ComponentElementName}</li>
- * <li>{@link StyleContext.IconElementName}</li>
+ * <li>{@link AbstractDocument#ContentElementName}</li>
+ * <li>{@link AbstractDocument#ParagraphElementName}</li>
+ * <li>{@link AbstractDocument#SectionElementName}</li>
+ * <li>{@link StyleConstants#ComponentElementName}</li>
+ * <li>{@link StyleConstants#IconElementName}</li>
* </ul>
*
* @return a {@link ViewFactory} that is able to create {@link View}s
diff --git a/libjava/classpath/javax/swing/text/TabSet.java b/libjava/classpath/javax/swing/text/TabSet.java
index 146f545aac7..ecad9444ea5 100644
--- a/libjava/classpath/javax/swing/text/TabSet.java
+++ b/libjava/classpath/javax/swing/text/TabSet.java
@@ -41,6 +41,9 @@ import java.io.Serializable;
public class TabSet implements Serializable
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 2367703481999080593L;
+
TabStop[] tabs;
public TabSet(TabStop[] t)
diff --git a/libjava/classpath/javax/swing/text/TabStop.java b/libjava/classpath/javax/swing/text/TabStop.java
index 032da8bca46..56f862fdae4 100644
--- a/libjava/classpath/javax/swing/text/TabStop.java
+++ b/libjava/classpath/javax/swing/text/TabStop.java
@@ -41,6 +41,9 @@ import java.io.Serializable;
public class TabStop implements Serializable
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -5381995917363605058L;
+
public static final int ALIGN_LEFT = 0;
public static final int ALIGN_RIGHT = 1;
public static final int ALIGN_CENTER = 2;
diff --git a/libjava/classpath/javax/swing/text/Utilities.java b/libjava/classpath/javax/swing/text/Utilities.java
index d40408ddc3f..7830b2fca04 100644
--- a/libjava/classpath/javax/swing/text/Utilities.java
+++ b/libjava/classpath/javax/swing/text/Utilities.java
@@ -40,6 +40,11 @@ package javax.swing.text;
import java.awt.FontMetrics;
import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.text.BreakIterator;
+
+import javax.swing.SwingConstants;
/**
* A set of utilities to deal with text. This is used by several other classes
@@ -195,4 +200,409 @@ public class Utilities
return maxWidth;
}
+
+ /**
+ * Provides a facility to map screen coordinates into a model location. For a
+ * given text fragment and start location within this fragment, this method
+ * determines the model location so that the resulting fragment fits best
+ * into the span <code>[x0, x]</code>.
+ *
+ * The parameter <code>round</code> controls which model location is returned
+ * if the view coordinates are on a character: If <code>round</code> is
+ * <code>true</code>, then the result is rounded up to the next character, so
+ * that the resulting fragment is the smallest fragment that is larger than
+ * the specified span. If <code>round</code> is <code>false</code>, then the
+ * resulting fragment is the largest fragment that is smaller than the
+ * specified span.
+ *
+ * @param s the text segment
+ * @param fm the font metrics to use
+ * @param x0 the starting screen location
+ * @param x the target screen location at which the requested fragment should
+ * end
+ * @param te the tab expander to use; if this is <code>null</code>, TABs are
+ * expanded to one space character
+ * @param p0 the starting model location
+ * @param round if <code>true</code> round up to the next location, otherwise
+ * round down to the current location
+ *
+ * @return the model location, so that the resulting fragment fits within the
+ * specified span
+ */
+ public static final int getTabbedTextOffset(Segment s, FontMetrics fm, int x0,
+ int x, TabExpander te, int p0,
+ boolean round)
+ {
+ // At the end of the for loop, this holds the requested model location
+ int pos;
+ int currentX = x0;
+
+ for (pos = p0; pos < s.count; pos++)
+ {
+ char nextChar = s.array[s.offset+pos];
+ if (nextChar == 0)
+ {
+ if (! round)
+ pos--;
+ break;
+ }
+ if (nextChar != '\t')
+ currentX += fm.charWidth(nextChar);
+ else
+ {
+ if (te == null)
+ currentX += fm.charWidth(' ');
+ else
+ currentX = (int) te.nextTabStop(currentX, pos);
+ }
+ if (currentX > x)
+ {
+ if (! round)
+ pos--;
+ break;
+ }
+ }
+ return pos;
+ }
+
+ /**
+ * Provides a facility to map screen coordinates into a model location. For a
+ * given text fragment and start location within this fragment, this method
+ * determines the model location so that the resulting fragment fits best
+ * into the span <code>[x0, x]</code>.
+ *
+ * This method rounds up to the next location, so that the resulting fragment
+ * will be the smallest fragment of the text, that is greater than the
+ * specified span.
+ *
+ * @param s the text segment
+ * @param fm the font metrics to use
+ * @param x0 the starting screen location
+ * @param x the target screen location at which the requested fragment should
+ * end
+ * @param te the tab expander to use; if this is <code>null</code>, TABs are
+ * expanded to one space character
+ * @param p0 the starting model location
+ *
+ * @return the model location, so that the resulting fragment fits within the
+ * specified span
+ */
+ public static final int getTabbedTextOffset(Segment s, FontMetrics fm, int x0,
+ int x, TabExpander te, int p0)
+ {
+ return getTabbedTextOffset(s, fm, x0, x, te, p0, true);
+ }
+
+ /**
+ * Finds the start of the next word for the given offset.
+ *
+ * @param c
+ * the text component
+ * @param offs
+ * the offset in the document
+ * @return the location in the model of the start of the next word.
+ * @throws BadLocationException
+ * if the offset is invalid.
+ */
+ public static final int getNextWord(JTextComponent c, int offs)
+ throws BadLocationException
+ {
+ if (offs < 0 || offs > (c.getText().length() - 1))
+ throw new BadLocationException("invalid offset specified", offs);
+ String text = c.getText();
+ BreakIterator wb = BreakIterator.getWordInstance();
+ wb.setText(text);
+ int last = wb.following(offs);
+ int current = wb.next();
+ while (current != BreakIterator.DONE)
+ {
+ for (int i = last; i < current; i++)
+ {
+ // FIXME: Should use isLetter(int) and text.codePointAt(int)
+ // instead, but isLetter(int) isn't implemented yet
+ if (Character.isLetter(text.charAt(i)))
+ return last;
+ }
+ last = current;
+ current = wb.next();
+ }
+ return BreakIterator.DONE;
+ }
+
+ /**
+ * Finds the start of the previous word for the given offset.
+ *
+ * @param c
+ * the text component
+ * @param offs
+ * the offset in the document
+ * @return the location in the model of the start of the previous word.
+ * @throws BadLocationException
+ * if the offset is invalid.
+ */
+ public static final int getPreviousWord(JTextComponent c, int offs)
+ throws BadLocationException
+ {
+ if (offs < 0 || offs > (c.getText().length() - 1))
+ throw new BadLocationException("invalid offset specified", offs);
+ String text = c.getText();
+ BreakIterator wb = BreakIterator.getWordInstance();
+ wb.setText(text);
+ int last = wb.preceding(offs);
+ int current = wb.previous();
+
+ while (current != BreakIterator.DONE)
+ {
+ for (int i = last; i < offs; i++)
+ {
+ // FIXME: Should use isLetter(int) and text.codePointAt(int)
+ // instead, but isLetter(int) isn't implemented yet
+ if (Character.isLetter(text.charAt(i)))
+ return last;
+ }
+ last = current;
+ current = wb.previous();
+ }
+ return 0;
+ }
+
+ /**
+ * Finds the start of a word for the given location.
+ * @param c the text component
+ * @param offs the offset location
+ * @return the location of the word beginning
+ * @throws BadLocationException if the offset location is invalid
+ */
+ public static final int getWordStart(JTextComponent c, int offs)
+ throws BadLocationException
+ {
+ if (offs < 0 || offs >= c.getText().length())
+ throw new BadLocationException("invalid offset specified", offs);
+
+ String text = c.getText();
+ BreakIterator wb = BreakIterator.getWordInstance();
+ wb.setText(text);
+ if (wb.isBoundary(offs))
+ return offs;
+ return wb.preceding(offs);
+ }
+
+ /**
+ * Finds the end of a word for the given location.
+ * @param c the text component
+ * @param offs the offset location
+ * @return the location of the word end
+ * @throws BadLocationException if the offset location is invalid
+ */
+ public static final int getWordEnd(JTextComponent c, int offs)
+ throws BadLocationException
+ {
+ if (offs < 0 || offs >= c.getText().length())
+ throw new BadLocationException("invalid offset specified", offs);
+
+ String text = c.getText();
+ BreakIterator wb = BreakIterator.getWordInstance();
+ wb.setText(text);
+ return wb.following(offs);
+ }
+
+ /**
+ * Get the model position of the end of the row that contains the
+ * specified model position. Return null if the given JTextComponent
+ * does not have a size.
+ * @param c the JTextComponent
+ * @param offs the model position
+ * @return the model position of the end of the row containing the given
+ * offset
+ * @throws BadLocationException if the offset is invalid
+ */
+ public static final int getRowEnd(JTextComponent c, int offs)
+ throws BadLocationException
+ {
+ String text = c.getText();
+ if (text == null)
+ return -1;
+
+ // Do a binary search for the smallest position X > offs
+ // such that that character at positino X is not on the same
+ // line as the character at position offs
+ int high = offs + ((text.length() - 1 - offs) / 2);
+ int low = offs;
+ int oldHigh = text.length() + 1;
+ while (true)
+ {
+ if (c.modelToView(high).y != c.modelToView(offs).y)
+ {
+ oldHigh = high;
+ high = low + ((high + 1 - low) / 2);
+ if (oldHigh == high)
+ return high - 1;
+ }
+ else
+ {
+ low = high;
+ high += ((oldHigh - high) / 2);
+ if (low == high)
+ return low;
+ }
+ }
+ }
+
+ /**
+ * Get the model position of the start of the row that contains the specified
+ * model position. Return null if the given JTextComponent does not have a
+ * size.
+ *
+ * @param c the JTextComponent
+ * @param offs the model position
+ * @return the model position of the start of the row containing the given
+ * offset
+ * @throws BadLocationException if the offset is invalid
+ */
+ public static final int getRowStart(JTextComponent c, int offs)
+ throws BadLocationException
+ {
+ String text = c.getText();
+ if (text == null)
+ return -1;
+
+ // Do a binary search for the greatest position X < offs
+ // such that the character at position X is not on the same
+ // row as the character at position offs
+ int high = offs;
+ int low = 0;
+ int oldLow = 0;
+ while (true)
+ {
+ if (c.modelToView(low).y != c.modelToView(offs).y)
+ {
+ oldLow = low;
+ low = high - ((high + 1 - low) / 2);
+ if (oldLow == low)
+ return low + 1;
+ }
+ else
+ {
+ high = low;
+ low -= ((low - oldLow) / 2);
+ if (low == high)
+ return low;
+ }
+ }
+ }
+
+ /**
+ * Determine where to break the text in the given Segment, attempting to find
+ * a word boundary.
+ * @param s the Segment that holds the text
+ * @param metrics the font metrics used for calculating the break point
+ * @param x0 starting view location representing the start of the text
+ * @param x the target view location
+ * @param e the TabExpander used for expanding tabs (if this is null tabs
+ * are expanded to 1 space)
+ * @param startOffset the offset in the Document of the start of the text
+ * @return the offset at which we should break the text
+ */
+ public static final int getBreakLocation(Segment s, FontMetrics metrics,
+ int x0, int x, TabExpander e,
+ int startOffset)
+ {
+ int mark = Utilities.getTabbedTextOffset(s, metrics, x0, x, e, startOffset);
+ BreakIterator breaker = BreakIterator.getWordInstance();
+ breaker.setText(s.toString());
+
+ // If mark is equal to the end of the string, just use that position
+ if (mark == s.count)
+ return mark;
+
+ // Try to find a word boundary previous to the mark at which we
+ // can break the text
+ int preceding = breaker.preceding(mark + 1);
+
+ if (preceding != 0)
+ return preceding;
+ else
+ // If preceding is 0 we couldn't find a suitable word-boundary so
+ // just break it on the character boundary
+ return mark;
+ }
+
+ /**
+ * Returns the paragraph element in the text component <code>c</code> at
+ * the specified location <code>offset</code>.
+ *
+ * @param c the text component
+ * @param offset the offset of the paragraph element to return
+ *
+ * @return the paragraph element at <code>offset</code>
+ */
+ public static final Element getParagraphElement(JTextComponent c, int offset)
+ {
+ Document doc = c.getDocument();
+ Element par = null;
+ if (doc instanceof StyledDocument)
+ {
+ StyledDocument styledDoc = (StyledDocument) doc;
+ par = styledDoc.getParagraphElement(offset);
+ }
+ else
+ {
+ Element root = c.getDocument().getDefaultRootElement();
+ int parIndex = root.getElementIndex(offset);
+ par = root.getElement(parIndex);
+ }
+ return par;
+ }
+
+ /**
+ * Returns the document position that is closest above to the specified x
+ * coordinate in the row containing <code>offset</code>.
+ *
+ * @param c the text component
+ * @param offset the offset
+ * @param x the x coordinate
+ *
+ * @return the document position that is closest above to the specified x
+ * coordinate in the row containing <code>offset</code>
+ *
+ * @throws BadLocationException if <code>offset</code> is not a valid offset
+ */
+ public static final int getPositionAbove(JTextComponent c, int offset, int x)
+ throws BadLocationException
+ {
+ View rootView = c.getUI().getRootView(c);
+ Rectangle r = c.modelToView(offset);
+ int offs = c.viewToModel(new Point(x, r.y));
+ int pos = rootView.getNextVisualPositionFrom(c, offs,
+ Position.Bias.Forward,
+ SwingConstants.NORTH,
+ new Position.Bias[1]);
+ return pos;
+ }
+
+ /**
+ * Returns the document position that is closest below to the specified x
+ * coordinate in the row containing <code>offset</code>.
+ *
+ * @param c the text component
+ * @param offset the offset
+ * @param x the x coordinate
+ *
+ * @return the document position that is closest above to the specified x
+ * coordinate in the row containing <code>offset</code>
+ *
+ * @throws BadLocationException if <code>offset</code> is not a valid offset
+ */
+ public static final int getPositionBelow(JTextComponent c, int offset, int x)
+ throws BadLocationException
+ {
+ View rootView = c.getUI().getRootView(c);
+ Rectangle r = c.modelToView(offset);
+ int offs = c.viewToModel(new Point(x, r.y));
+ int pos = rootView.getNextVisualPositionFrom(c, offs,
+ Position.Bias.Forward,
+ SwingConstants.SOUTH,
+ new Position.Bias[1]);
+ return pos;
+ }
}
diff --git a/libjava/classpath/javax/swing/text/View.java b/libjava/classpath/javax/swing/text/View.java
index 24efba9a1bc..daab347d731 100644
--- a/libjava/classpath/javax/swing/text/View.java
+++ b/libjava/classpath/javax/swing/text/View.java
@@ -43,7 +43,6 @@ import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
-import javax.swing.JComponent;
import javax.swing.SwingConstants;
import javax.swing.event.DocumentEvent;
@@ -87,9 +86,9 @@ public abstract class View implements SwingConstants
{
View parent = getParent();
if (parent == null)
- throw new AssertionError("The parent of a View must not be null.");
-
- return parent.getContainer();
+ return null;
+ else
+ return parent.getContainer();
}
public Document getDocument()
@@ -508,6 +507,30 @@ public abstract class View implements SwingConstants
}
/**
+ * Maps a position in the document into the coordinate space of the View.
+ * The output rectangle usually reflects the font height but has a width
+ * of zero.
+ *
+ * This method is deprecated and calls
+ * {@link #modelToView(int, Position.Bias, int, Position.Bias, Shape)} with
+ * a bias of {@link Position.Bias#Forward}.
+ *
+ * @param pos the position of the character in the model
+ * @param a the area that is occupied by the view
+ *
+ * @return a rectangle that gives the location of the document position
+ * inside the view coordinate space
+ *
+ * @throws BadLocationException if <code>pos</code> is invalid
+ *
+ * @deprecated Use {@link #modelToView(int, Shape, Position.Bias)} instead.
+ */
+ public Shape modelToView(int pos, Shape a) throws BadLocationException
+ {
+ return modelToView(pos, a, Position.Bias.Forward);
+ }
+
+ /**
* Maps coordinates from the <code>View</code>'s space into a position
* in the document model.
*
@@ -521,6 +544,25 @@ public abstract class View implements SwingConstants
*/
public abstract int viewToModel(float x, float y, Shape a, Position.Bias[] b);
+ /**
+ * Maps coordinates from the <code>View</code>'s space into a position
+ * in the document model. This method is deprecated and only there for
+ * compatibility.
+ *
+ * @param x the x coordinate in the view space
+ * @param y the y coordinate in the view space
+ * @param a the allocation of this <code>View</code>
+ *
+ * @return the position in the document that corresponds to the screen
+ * coordinates <code>x, y</code>
+ *
+ * @deprecated Use {@link #viewToModel(float, float, Shape, Position.Bias[])}
+ * instead.
+ */
+ public int viewToModel(float x, float y, Shape a)
+ {
+ return viewToModel(x, y, a, new Position.Bias[0]);
+ }
/**
* Dumps the complete View hierarchy. This method can be used for debugging
@@ -552,4 +594,30 @@ public abstract class View implements SwingConstants
for (int i = 0; i < count; ++i)
getView(i).dump(indent + 1);
}
+
+ /**
+ * Returns the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction <code>d</code>.
+ *
+ * @param c the text component
+ * @param pos the document position
+ * @param b the bias for <code>pos</code>
+ * @param d the direction, must be either {@link SwingConstants#NORTH},
+ * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
+ * {@link SwingConstants#EAST}
+ * @param biasRet an array of {@link Position.Bias} that can hold at least
+ * one element, which is filled with the bias of the return position
+ * on method exit
+ *
+ * @return the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction
+ * <code>d</code>
+ *
+ * @throws BadLocationException if <code>pos</code> is not a valid offset in
+ * the document model
+ */
+ public abstract int getNextVisualPositionFrom(JTextComponent c, int pos,
+ Position.Bias b, int d,
+ Position.Bias[] biasRet)
+ throws BadLocationException;
}
diff --git a/libjava/classpath/javax/swing/text/WrappedPlainView.java b/libjava/classpath/javax/swing/text/WrappedPlainView.java
new file mode 100644
index 00000000000..b90519046ae
--- /dev/null
+++ b/libjava/classpath/javax/swing/text/WrappedPlainView.java
@@ -0,0 +1,700 @@
+/* WrappedPlainView.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.SwingConstants;
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.Position.Bias;
+
+/**
+ * @author abalkiss
+ *
+ */
+public class WrappedPlainView extends BoxView implements TabExpander
+{
+ /** The color for selected text **/
+ Color selectedColor;
+
+ /** The color for unselected text **/
+ Color unselectedColor;
+
+ /** The color for disabled components **/
+ Color disabledColor;
+
+ /** Stores the font metrics **/
+ protected FontMetrics metrics;
+
+ /** Whether or not to wrap on word boundaries **/
+ boolean wordWrap;
+
+ /** A ViewFactory that creates WrappedLines **/
+ ViewFactory viewFactory = new WrappedLineCreator();
+
+ /** The start of the selected text **/
+ int selectionStart;
+
+ /** The end of the selected text **/
+ int selectionEnd;
+
+ /**
+ * The instance returned by {@link #getLineBuffer()}.
+ */
+ private transient Segment lineBuffer;
+
+ public WrappedPlainView (Element elem)
+ {
+ this (elem, false);
+ }
+
+ public WrappedPlainView (Element elem, boolean wordWrap)
+ {
+ super (elem, Y_AXIS);
+ this.wordWrap = wordWrap;
+ }
+
+ /**
+ * Provides access to the Segment used for retrievals from the Document.
+ * @return the Segment.
+ */
+ protected final Segment getLineBuffer()
+ {
+ if (lineBuffer == null)
+ lineBuffer = new Segment();
+ return lineBuffer;
+ }
+
+ /**
+ * Returns the next tab stop position after a given reference position.
+ *
+ * This implementation ignores the <code>tabStop</code> argument.
+ *
+ * @param x the current x position in pixels
+ * @param tabStop the position within the text stream that the tab occured at
+ */
+ public float nextTabStop(float x, int tabStop)
+ {
+ JTextComponent host = (JTextComponent)getContainer();
+ float tabSizePixels = getTabSize()
+ * host.getFontMetrics(host.getFont()).charWidth('m');
+ return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels;
+ }
+
+ /**
+ * Returns the tab size for the Document based on
+ * PlainDocument.tabSizeAttribute, defaulting to 8 if this property is
+ * not defined
+ *
+ * @return the tab size.
+ */
+ protected int getTabSize()
+ {
+ Object tabSize = getDocument().getProperty(PlainDocument.tabSizeAttribute);
+ if (tabSize == null)
+ return 8;
+ return ((Integer)tabSize).intValue();
+ }
+
+ /**
+ * Draws a line of text, suppressing white space at the end and expanding
+ * tabs. Calls drawSelectedText and drawUnselectedText.
+ * @param p0 starting document position to use
+ * @param p1 ending document position to use
+ * @param g graphics context
+ * @param x starting x position
+ * @param y starting y position
+ */
+ protected void drawLine(int p0, int p1, Graphics g, int x, int y)
+ {
+ try
+ {
+ // We have to draw both selected and unselected text. There are
+ // several cases:
+ // - entire range is unselected
+ // - entire range is selected
+ // - start of range is selected, end of range is unselected
+ // - start of range is unselected, end of range is selected
+ // - middle of range is selected, start and end of range is unselected
+
+ // entire range unselected:
+ if ((selectionStart == selectionEnd) ||
+ (p0 > selectionEnd || p1 < selectionStart))
+ drawUnselectedText(g, x, y, p0, p1);
+
+ // entire range selected
+ else if (p0 >= selectionStart && p1 <= selectionEnd)
+ drawSelectedText(g, x, y, p0, p1);
+
+ // start of range selected, end of range unselected
+ else if (p0 >= selectionStart)
+ {
+ x = drawSelectedText(g, x, y, p0, selectionEnd);
+ drawUnselectedText(g, x, y, selectionEnd, p1);
+ }
+
+ // start of range unselected, end of range selected
+ else if (selectionStart > p0 && selectionEnd > p1)
+ {
+ x = drawUnselectedText(g, x, y, p0, selectionStart);
+ drawSelectedText(g, x, y, selectionStart, p1);
+ }
+
+ // middle of range selected
+ else if (selectionStart > p0)
+ {
+ x = drawUnselectedText(g, x, y, p0, selectionStart);
+ x = drawSelectedText(g, x, y, selectionStart, selectionEnd);
+ drawUnselectedText(g, x, y, selectionEnd, p1);
+ }
+ }
+ catch (BadLocationException ble)
+ {
+ // shouldn't happen
+ }
+ }
+
+ /**
+ * Renders the range of text as selected text. Just paints the text
+ * in the color specified by the host component. Assumes the highlighter
+ * will render the selected background.
+ * @param g the graphics context
+ * @param x the starting X coordinate
+ * @param y the starting Y coordinate
+ * @param p0 the starting model location
+ * @param p1 the ending model location
+ * @return the X coordinate of the end of the text
+ * @throws BadLocationException if the given range is invalid
+ */
+ protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1)
+ throws BadLocationException
+ {
+ g.setColor(selectedColor);
+ Segment segment = getLineBuffer();
+ getDocument().getText(p0, p1 - p0, segment);
+ return Utilities.drawTabbedText(segment, x, y, g, this, p0);
+ }
+
+ /**
+ * Renders the range of text as normal unhighlighted text.
+ * @param g the graphics context
+ * @param x the starting X coordinate
+ * @param y the starting Y coordinate
+ * @param p0 the starting model location
+ * @param p1 the end model location
+ * @return the X location of the end off the range
+ * @throws BadLocationException if the range given is invalid
+ */
+ protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1)
+ throws BadLocationException
+ {
+ JTextComponent textComponent = (JTextComponent) getContainer();
+ if (textComponent.isEnabled())
+ g.setColor(unselectedColor);
+ else
+ g.setColor(disabledColor);
+
+ Segment segment = getLineBuffer();
+ getDocument().getText(p0, p1 - p0, segment);
+ return Utilities.drawTabbedText(segment, x, y, g, this, p0);
+ }
+
+ /**
+ * Loads the children to initiate the view. Called by setParent.
+ * Creates a WrappedLine for each child Element.
+ */
+ protected void loadChildren (ViewFactory f)
+ {
+ Element root = getElement();
+ int numChildren = root.getElementCount();
+ if (numChildren == 0)
+ return;
+
+ View[] children = new View[numChildren];
+ for (int i = 0; i < numChildren; i++)
+ children[i] = new WrappedLine(root.getElement(i));
+ replace(0, 0, children);
+ }
+
+ /**
+ * Calculates the break position for the text between model positions
+ * p0 and p1. Will break on word boundaries or character boundaries
+ * depending on the break argument given in construction of this
+ * WrappedPlainView. Used by the nested WrappedLine class to determine
+ * when to start the next logical line.
+ * @param p0 the start model position
+ * @param p1 the end model position
+ * @return the model position at which to break the text
+ */
+ protected int calculateBreakPosition(int p0, int p1)
+ {
+ Container c = getContainer();
+ Rectangle alloc = c.isValid() ? c.getBounds()
+ : new Rectangle(c.getPreferredSize());
+ updateMetrics();
+ try
+ {
+ getDocument().getText(p0, p1 - p0, getLineBuffer());
+ }
+ catch (BadLocationException ble)
+ {
+ // this shouldn't happen
+ }
+ // FIXME: Should we account for the insets of the container?
+ if (wordWrap)
+ return p0
+ + Utilities.getBreakLocation(lineBuffer, metrics, alloc.x,
+ alloc.x + alloc.width, this, 0);
+ else
+ {
+ return p0
+ + Utilities.getTabbedTextOffset(lineBuffer, metrics, alloc.x,
+ alloc.x + alloc.width, this, 0);
+ }
+ }
+
+ void updateMetrics()
+ {
+ Container component = getContainer();
+ metrics = component.getFontMetrics(component.getFont());
+ }
+
+ /**
+ * Determines the preferred span along the given axis. Implemented to
+ * cache the font metrics and then call the super classes method.
+ */
+ public float getPreferredSpan (int axis)
+ {
+ updateMetrics();
+ return super.getPreferredSpan(axis);
+ }
+
+ /**
+ * Determines the minimum span along the given axis. Implemented to
+ * cache the font metrics and then call the super classes method.
+ */
+ public float getMinimumSpan (int axis)
+ {
+ updateMetrics();
+ return super.getMinimumSpan(axis);
+ }
+
+ /**
+ * Determines the maximum span along the given axis. Implemented to
+ * cache the font metrics and then call the super classes method.
+ */
+ public float getMaximumSpan (int axis)
+ {
+ updateMetrics();
+ return super.getMaximumSpan(axis);
+ }
+
+ /**
+ * Called when something was inserted. Overridden so that
+ * the view factory creates WrappedLine views.
+ */
+ public void insertUpdate (DocumentEvent e, Shape a, ViewFactory f)
+ {
+ super.insertUpdate(e, a, viewFactory);
+ // FIXME: could improve performance by repainting only the necessary area
+ getContainer().repaint();
+ }
+
+ /**
+ * Called when something is removed. Overridden so that
+ * the view factory creates WrappedLine views.
+ */
+ public void removeUpdate (DocumentEvent e, Shape a, ViewFactory f)
+ {
+ super.removeUpdate(e, a, viewFactory);
+ // FIXME: could improve performance by repainting only the necessary area
+ getContainer().repaint();
+ }
+
+ /**
+ * Called when the portion of the Document that this View is responsible
+ * for changes. Overridden so that the view factory creates
+ * WrappedLine views.
+ */
+ public void changedUpdate (DocumentEvent e, Shape a, ViewFactory f)
+ {
+ super.changedUpdate(e, a, viewFactory);
+ // FIXME: could improve performance by repainting only the necessary area
+ getContainer().repaint();
+ }
+
+ class WrappedLineCreator implements ViewFactory
+ {
+ // Creates a new WrappedLine
+ public View create(Element elem)
+ {
+ return new WrappedLine(elem);
+ }
+ }
+
+ /**
+ * Renders the <code>Element</code> that is associated with this
+ * <code>View</code>. Caches the metrics and then calls
+ * super.paint to paint all the child views.
+ *
+ * @param g the <code>Graphics</code> context to render to
+ * @param a the allocated region for the <code>Element</code>
+ */
+ public void paint(Graphics g, Shape a)
+ {
+ JTextComponent comp = (JTextComponent)getContainer();
+ selectionStart = comp.getSelectionStart();
+ selectionEnd = comp.getSelectionEnd();
+ updateMetrics();
+ super.paint(g, a);
+ }
+
+ /**
+ * Sets the size of the View. Implemented to update the metrics
+ * and then call super method.
+ */
+ public void setSize (float width, float height)
+ {
+ updateMetrics();
+ if (width != getWidth())
+ preferenceChanged(null, true, true);
+ super.setSize(width, height);
+ }
+
+ class WrappedLine extends View
+ {
+ /** Used to cache the number of lines for this View **/
+ int numLines;
+
+ public WrappedLine(Element elem)
+ {
+ super(elem);
+ determineNumLines();
+ }
+
+ /**
+ * Renders this (possibly wrapped) line using the given Graphics object
+ * and on the given rendering surface.
+ */
+ public void paint(Graphics g, Shape s)
+ {
+ // Ensure metrics are up-to-date.
+ updateMetrics();
+ JTextComponent textComponent = (JTextComponent) getContainer();
+
+ g.setFont(textComponent.getFont());
+ selectedColor = textComponent.getSelectedTextColor();
+ unselectedColor = textComponent.getForeground();
+ disabledColor = textComponent.getDisabledTextColor();
+
+ // FIXME: this is a hack, for some reason textComponent.getSelectedColor
+ // was returning black, which is not visible against a black background
+ selectedColor = Color.WHITE;
+
+ Rectangle rect = s.getBounds();
+ int lineHeight = metrics.getHeight();
+
+ int end = getEndOffset();
+ int currStart = getStartOffset();
+ int currEnd;
+ while (currStart < end)
+ {
+ currEnd = calculateBreakPosition(currStart, end);
+ drawLine(currStart, currEnd, g, rect.x, rect.y);
+ rect.y += lineHeight;
+ if (currEnd == currStart)
+ currStart ++;
+ else
+ currStart = currEnd;
+ }
+ }
+
+ /**
+ * Determines the number of logical lines that the Element
+ * needs to be displayed
+ * @return the number of lines needed to display the Element
+ */
+ int determineNumLines()
+ {
+ numLines = 0;
+ int end = getEndOffset();
+ if (end == 0)
+ return 0;
+
+ int breakPoint;
+ for (int i = getStartOffset(); i < end;)
+ {
+ numLines ++;
+ // careful: check that there's no off-by-one problem here
+ // depending on which position calculateBreakPosition returns
+ breakPoint = calculateBreakPosition(i, end);
+ if (breakPoint == i)
+ i ++;
+ else
+ i = breakPoint;
+ }
+ return numLines;
+ }
+
+ /**
+ * Determines the preferred span for this view along the given axis.
+ *
+ * @param axis the axis (either X_AXIS or Y_AXIS)
+ *
+ * @return the preferred span along the given axis.
+ * @throws IllegalArgumentException if axis is not X_AXIS or Y_AXIS
+ */
+ public float getPreferredSpan(int axis)
+ {
+ if (axis == X_AXIS)
+ return getWidth();
+ else if (axis == Y_AXIS)
+ return numLines * metrics.getHeight();
+
+ throw new IllegalArgumentException("Invalid axis for getPreferredSpan: "
+ + axis);
+ }
+
+ /**
+ * Provides a mapping from model space to view space.
+ *
+ * @param pos the position in the model
+ * @param a the region into which the view is rendered
+ * @param b the position bias (forward or backward)
+ *
+ * @return a box in view space that represents the given position
+ * in model space
+ * @throws BadLocationException if the given model position is invalid
+ */
+ public Shape modelToView(int pos, Shape a, Bias b)
+ throws BadLocationException
+ {
+ Segment s = getLineBuffer();
+ int lineHeight = metrics.getHeight();
+ Rectangle rect = a.getBounds();
+
+ // Return a rectangle with width 1 and height equal to the height
+ // of the text
+ rect.height = lineHeight;
+ rect.width = 1;
+
+ int currLineStart = getStartOffset();
+ int end = getEndOffset();
+
+ if (pos < currLineStart || pos >= end)
+ throw new BadLocationException("invalid offset", pos);
+
+ while (true)
+ {
+ int currLineEnd = calculateBreakPosition(currLineStart, end);
+ // If pos is between currLineStart and currLineEnd then just find
+ // the width of the text from currLineStart to pos and add that
+ // to rect.x
+ if (pos >= currLineStart && pos < currLineEnd || pos == end - 1)
+ {
+ try
+ {
+ getDocument().getText(currLineStart, pos - currLineStart, s);
+ }
+ catch (BadLocationException ble)
+ {
+ // Shouldn't happen
+ }
+ rect.x += Utilities.getTabbedTextWidth(s, metrics, rect.x,
+ WrappedPlainView.this,
+ currLineStart);
+ return rect;
+ }
+ // Increment rect.y so we're checking the next logical line
+ rect.y += lineHeight;
+
+ // Increment currLineStart to the model position of the start
+ // of the next logical line
+ if (currLineEnd == currLineStart)
+ currLineStart = end;
+ else
+ currLineStart = currLineEnd;
+ }
+
+ }
+
+ /**
+ * Provides a mapping from view space to model space.
+ *
+ * @param x the x coordinate in view space
+ * @param y the y coordinate in view space
+ * @param a the region into which the view is rendered
+ * @param b the position bias (forward or backward)
+ *
+ * @return the location in the model that best represents the
+ * given point in view space
+ */
+ public int viewToModel(float x, float y, Shape a, Bias[] b)
+ {
+ Segment s = getLineBuffer();
+ Rectangle rect = a.getBounds();
+ int currLineStart = getStartOffset();
+ int end = getEndOffset();
+ int lineHeight = metrics.getHeight();
+ if (y < rect.y)
+ return currLineStart;
+ if (y > rect.y + rect.height)
+ return end - 1;
+
+ while (true)
+ {
+ int currLineEnd = calculateBreakPosition(currLineStart, end);
+ // If we're at the right y-position that means we're on the right
+ // logical line and we should look for the character
+ if (y >= rect.y && y < rect.y + lineHeight)
+ {
+ // Check if the x position is to the left or right of the text
+ if (x < rect.x)
+ return currLineStart;
+ if (x > rect.x + rect.width)
+ return currLineEnd - 1;
+
+ try
+ {
+ getDocument().getText(currLineStart, end - currLineStart, s);
+ }
+ catch (BadLocationException ble)
+ {
+ // Shouldn't happen
+ }
+ int mark = Utilities.getTabbedTextOffset(s, metrics, rect.x,
+ (int) x,
+ WrappedPlainView.this,
+ currLineStart);
+ return currLineStart + mark;
+ }
+ // Increment rect.y so we're checking the next logical line
+ rect.y += lineHeight;
+
+ // Increment currLineStart to the model position of the start
+ // of the next logical line
+ if (currLineEnd == currLineStart)
+ currLineStart = end;
+ else
+ currLineStart = currLineEnd;
+ }
+ }
+
+ /**
+ * Returns the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction <code>d</code>.
+ *
+ * @param c the text component
+ * @param pos the document position
+ * @param b the bias for <code>pos</code>
+ * @param d the direction, must be either {@link SwingConstants#NORTH},
+ * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
+ * {@link SwingConstants#EAST}
+ * @param biasRet an array of {@link Position.Bias} that can hold at least
+ * one element, which is filled with the bias of the return position
+ * on method exit
+ *
+ * @return the document position that is (visually) nearest to the given
+ * document position <code>pos</code> in the given direction
+ * <code>d</code>
+ *
+ * @throws BadLocationException if <code>pos</code> is not a valid offset
+ * in the document model
+ */
+ public int getNextVisualPositionFrom(JTextComponent c, int pos,
+ Position.Bias b, int d,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ // TODO: Implement this properly.
+ throw new AssertionError("Not implemented yet.");
+ }
+
+ /**
+ * This method is called from insertUpdate and removeUpdate.
+ * If the number of lines in the document has changed, just repaint
+ * the whole thing (note, could improve performance by not repainting
+ * anything above the changes). If the number of lines hasn't changed,
+ * just repaint the given Rectangle.
+ * @param a the Rectangle to repaint if the number of lines hasn't changed
+ */
+ void updateDamage (Rectangle a)
+ {
+ int newNumLines = determineNumLines();
+ if (numLines != newNumLines)
+ {
+ numLines = newNumLines;
+ getContainer().repaint();
+ }
+ else
+ getContainer().repaint(a.x, a.y, a.width, a.height);
+ }
+
+ /**
+ * This method is called when something is inserted into the Document
+ * that this View is displaying.
+ *
+ * @param changes the DocumentEvent for the changes.
+ * @param a the allocation of the View
+ * @param f the ViewFactory used to rebuild
+ */
+ public void insertUpdate (DocumentEvent changes, Shape a, ViewFactory f)
+ {
+ updateDamage((Rectangle)a);
+ }
+
+ /**
+ * This method is called when something is removed from the Document
+ * that this View is displaying.
+ *
+ * @param changes the DocumentEvent for the changes.
+ * @param a the allocation of the View
+ * @param f the ViewFactory used to rebuild
+ */
+ public void removeUpdate (DocumentEvent changes, Shape a, ViewFactory f)
+ {
+ updateDamage((Rectangle)a);
+ }
+ }
+}
diff --git a/libjava/classpath/javax/swing/text/html/CSS.java b/libjava/classpath/javax/swing/text/html/CSS.java
new file mode 100644
index 00000000000..029ad26f8a9
--- /dev/null
+++ b/libjava/classpath/javax/swing/text/html/CSS.java
@@ -0,0 +1,461 @@
+/* CSS.java -- Provides CSS attributes
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text.html;
+
+import java.util.HashMap;
+
+/**
+ * Provides CSS attributes to be used by the HTML view classes. The constants
+ * defined here are used as keys for text attributes for use in
+ * {@link javax.swing.text.AttributeSet}s of {@link javax.swing.text.Element}s.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class CSS
+{
+ /**
+ * Returns an array of all CSS attributes.
+ *
+ * @return All available CSS.Attribute objects.
+ */
+ public static CSS.Attribute[] getAllAttributeKeys()
+ {
+ Object[] src = Attribute.attributeMap.values().toArray();
+ CSS.Attribute[] dst = new CSS.Attribute[ src.length ];
+ System.arraycopy(src, 0, dst, 0, src.length);
+ return dst;
+ }
+
+ /**
+ * Returns an a given CSS attribute.
+ *
+ * @param name - The name of the attribute.
+ * @return The CSS attribute with the given name, or <code>null</code> if
+ * no attribute with that name exists.
+ */
+ public static CSS.Attribute getAttribute(String name)
+ {
+ return (CSS.Attribute)Attribute.attributeMap.get( name );
+ }
+
+ public static final class Attribute
+ {
+ /**
+ * The CSS attribute 'background'.
+ */
+ public static final Attribute BACKGROUND =
+ new Attribute("background", false, null);
+
+ /**
+ * The CSS attribute 'background-attachment'.
+ */
+ public static final Attribute BACKGROUND_ATTACHMENT =
+ new Attribute("background-attachment", false, "scroll");
+
+ /**
+ * The CSS attribute 'background-color'.
+ */
+ public static final Attribute BACKGROUND_COLOR =
+ new Attribute("background-color", false, "transparent");
+
+ /**
+ * The CSS attribute 'background-image'.
+ */
+ public static final Attribute BACKGROUND_IMAGE =
+ new Attribute("background-image", false, "none");
+
+ /**
+ * The CSS attribute 'background-position'.
+ */
+ public static final Attribute BACKGROUND_POSITION =
+ new Attribute("background-position", false, null);
+
+ /**
+ * The CSS attribute 'background-repeat'.
+ */
+ public static final Attribute BACKGROUND_REPEAT =
+ new Attribute("background-repeat", false, "repeat");
+
+ /**
+ * The CSS attribute 'border'.
+ */
+ public static final Attribute BORDER = new Attribute("border", false, null);
+
+ /**
+ * The CSS attribute 'border-bottom'.
+ */
+ public static final Attribute BORDER_BOTTOM =
+ new Attribute("border-bottom", false, null);
+
+ /**
+ * The CSS attribute 'border-bottom-width'.
+ */
+ public static final Attribute BORDER_BOTTOM_WIDTH =
+ new Attribute("border-bottom-width", false, "medium");
+
+ /**
+ * The CSS attribute 'border-color'.
+ */
+ public static final Attribute BORDER_COLOR =
+ new Attribute("border-color", false, "black");
+
+ /**
+ * The CSS attribute 'border-left'.
+ */
+ public static final Attribute BORDER_LEFT =
+ new Attribute("border-left", false, null);
+
+ /**
+ * The CSS attribute 'border-left-width'.
+ */
+ public static final Attribute BORDER_LEFT_WIDTH =
+ new Attribute("border-left-width", false, "medium");
+
+ /**
+ * The CSS attribute 'border-right'.
+ */
+ public static final Attribute BORDER_RIGHT =
+ new Attribute("border-right", false, null);
+
+ /**
+ * The CSS attribute 'border-right-width'.
+ */
+ public static final Attribute BORDER_RIGHT_WIDTH =
+ new Attribute("border-right-width", false, "medium");
+
+ /**
+ * The CSS attribute 'border-style'.
+ */
+ public static final Attribute BORDER_STYLE =
+ new Attribute("border-style", false, "none");
+
+ /**
+ * The CSS attribute 'border-top'.
+ */
+ public static final Attribute BORDER_TOP =
+ new Attribute("border-top", false, null);
+
+ /**
+ * The CSS attribute 'border-top-width'.
+ */
+ public static final Attribute BORDER_TOP_WIDTH =
+ new Attribute("border-top-width", false, "medium");
+
+ /**
+ * The CSS attribute 'border-width'.
+ */
+ public static final Attribute BORDER_WIDTH =
+ new Attribute("border-width", false, "medium");
+
+ /**
+ * The CSS attribute 'clear'.
+ */
+ public static final Attribute CLEAR = new Attribute("clear", false, "none");
+
+ /**
+ * The CSS attribute 'color'.
+ */
+ public static final Attribute COLOR = new Attribute("color", true, "black");
+
+ /**
+ * The CSS attribute 'display'.
+ */
+ public static final Attribute DISPLAY =
+ new Attribute("display", false, "block");
+
+ /**
+ * The CSS attribute 'float'.
+ */
+ public static final Attribute FLOAT = new Attribute("float", false, "none");
+
+ /**
+ * The CSS attribute 'font'.
+ */
+ public static final Attribute FONT = new Attribute("font", true, null);
+
+ /**
+ * The CSS attribute 'font-family'.
+ */
+ public static final Attribute FONT_FAMILY =
+ new Attribute("font-family", true, null);
+
+ /**
+ * The CSS attribute 'font-size'.
+ */
+ public static final Attribute FONT_SIZE =
+ new Attribute("font-size", true, "medium");
+
+ /**
+ * The CSS attribute 'font-style'.
+ */
+ public static final Attribute FONT_STYLE =
+ new Attribute("font-style", true, "normal");
+
+ /**
+ * The CSS attribute 'font-variant'.
+ */
+ public static final Attribute FONT_VARIANT =
+ new Attribute("font-variant", true, "normal");
+
+ /**
+ * The CSS attribute 'font-weight'.
+ */
+ public static final Attribute FONT_WEIGHT =
+ new Attribute("font-weight", true, "normal");
+
+ /**
+ * The CSS attribute 'height'.
+ */
+ public static final Attribute HEIGHT =
+ new Attribute("height", false, "auto");
+
+ /**
+ * The CSS attribute 'letter-spacing'.
+ */
+ public static final Attribute LETTER_SPACING =
+ new Attribute("letter-spacing", true, "normal");
+
+ /**
+ * The CSS attribute 'line-height'.
+ */
+ public static final Attribute LINE_HEIGHT =
+ new Attribute("line-height", true, "normal");
+
+ /**
+ * The CSS attribute 'list-style'.
+ */
+ public static final Attribute LIST_STYLE =
+ new Attribute("list-style", true, null);
+
+ /**
+ * The CSS attribute 'list-style-image'.
+ */
+ public static final Attribute LIST_STYLE_IMAGE =
+ new Attribute("list-style-image", true, "none");
+
+ /**
+ * The CSS attribute 'list-style-position'.
+ */
+ public static final Attribute LIST_STYLE_POSITION =
+ new Attribute("list-style-position", true, "outside");
+
+ /**
+ * The CSS attribute 'list-style-type'.
+ */
+ public static final Attribute LIST_STYLE_TYPE =
+ new Attribute("list-style-type", true, "disc");
+
+ /**
+ * The CSS attribute 'margin'.
+ */
+ public static final Attribute MARGIN = new Attribute("margin", false, null);
+
+ /**
+ * The CSS attribute 'margin-bottom'.
+ */
+ public static final Attribute MARGIN_BOTTOM =
+ new Attribute("margin-bottom", false, "0");
+
+ /**
+ * The CSS attribute 'margin-left'.
+ */
+ public static final Attribute MARGIN_LEFT =
+ new Attribute("margin-left", false, "0");
+
+ /**
+ * The CSS attribute 'margin-right'.
+ */
+ public static final Attribute MARGIN_RIGHT =
+ new Attribute("margin-right", false, "0");
+
+ /**
+ * The CSS attribute 'margin-top'.
+ */
+ public static final Attribute MARGIN_TOP =
+ new Attribute("margin-top", false, "0");
+
+ /**
+ * The CSS attribute 'padding'.
+ */
+ public static final Attribute PADDING =
+ new Attribute("padding", false, null);
+
+ /**
+ * The CSS attribute 'padding-bottom'.
+ */
+ public static final Attribute PADDING_BOTTOM =
+ new Attribute("padding-bottom", false, "0");
+
+ /**
+ * The CSS attribute 'padding-left'.
+ */
+ public static final Attribute PADDING_LEFT =
+ new Attribute("padding-left", false, "0");
+
+ /**
+ * The CSS attribute 'padding-right'.
+ */
+ public static final Attribute PADDING_RIGHT =
+ new Attribute("padding-right", false, "0");
+
+ /**
+ * The CSS attribute 'padding-top'.
+ */
+ public static final Attribute PADDING_TOP =
+ new Attribute("padding-top", false, "0");
+
+ /**
+ * The CSS attribute 'text-align'.
+ */
+ public static final Attribute TEXT_ALIGN =
+ new Attribute("text-align", true, null);
+
+ /**
+ * The CSS attribute 'text-decoration'.
+ */
+ public static final Attribute TEXT_DECORATION =
+ new Attribute("text-decoration", true, "none");
+
+ /**
+ * The CSS attribute 'text-indent'.
+ */
+ public static final Attribute TEXT_INDENT =
+ new Attribute("text-indent", true, "0");
+
+ /**
+ * The CSS attribute 'text-transform'.
+ */
+ public static final Attribute TEXT_TRANSFORM =
+ new Attribute("text-transform", true, "none");
+
+ /**
+ * The CSS attribute 'vertical-align'.
+ */
+ public static final Attribute VERTICAL_ALIGN =
+ new Attribute("vertical-align", false, "baseline");
+
+ /**
+ * The CSS attribute 'white-space'.
+ */
+ public static final Attribute WHITE_SPACE =
+ new Attribute("white-space", true, "normal");
+
+ /**
+ * The CSS attribute 'width'.
+ */
+ public static final Attribute WIDTH =
+ new Attribute("width", false, "auto");
+
+ /**
+ * The CSS attribute 'word-spacing'.
+ */
+ public static final Attribute WORD_SPACING =
+ new Attribute("word-spacing", true, "normal");
+
+ /**
+ * The attribute string.
+ */
+ String attStr;
+
+ /**
+ * Indicates if this attribute should be inherited from it's parent or
+ * not.
+ */
+ boolean isInherited;
+
+ /**
+ * A default value for this attribute if one exists, otherwise null.
+ */
+ String defaultValue;
+
+ /**
+ * A HashMap of all attributes.
+ */
+ static HashMap attributeMap;
+
+ /**
+ * Creates a new Attribute instance with the specified values.
+ *
+ * @param attr the attribute string
+ * @param inherited if the attribute should be inherited or not
+ * @param def a default value; may be <code>null</code>
+ */
+ Attribute(String attr, boolean inherited, String def)
+ {
+ attStr = attr;
+ isInherited = inherited;
+ defaultValue = def;
+ if( attributeMap == null)
+ attributeMap = new HashMap();
+ attributeMap.put( attr, this );
+ }
+
+ /**
+ * Returns the string representation of this attribute as specified
+ * in the CSS specification.
+ */
+ public String toString()
+ {
+ return attStr;
+ }
+
+ /**
+ * Returns <code>true</code> if the attribute should be inherited from
+ * the parent, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the attribute should be inherited from
+ * the parent, <code>false</code> otherwise
+ */
+ public boolean isInherited()
+ {
+ return isInherited;
+ }
+
+ /**
+ * Returns the default value of this attribute if one exists,
+ * <code>null</code> otherwise.
+ *
+ * @return the default value of this attribute if one exists,
+ * <code>null</code> otherwise
+ */
+ public String getDefaultValue()
+ {
+ return defaultValue;
+ }
+ }
+}
diff --git a/libjava/classpath/javax/swing/text/html/HTML.java b/libjava/classpath/javax/swing/text/html/HTML.java
index 3c03a63a471..0b758d2b873 100644
--- a/libjava/classpath/javax/swing/text/html/HTML.java
+++ b/libjava/classpath/javax/swing/text/html/HTML.java
@@ -945,22 +945,22 @@ public class HTML
* This tag is not included into the array, returned by getAllTags().
* toString() returns 'comment'. HTML reader synthesizes this tag.
*/
- public static final Tag COMMENT = new Tag("comment", SYNTETIC);
+ public static final Tag COMMENT = new Tag("comment", SYNTHETIC);
/**
* All text content is labeled with this tag.
* This tag is not included into the array, returned by getAllTags().
* toString() returns 'content'. HTML reader synthesizes this tag.
*/
- public static final Tag CONTENT = new Tag("content", SYNTETIC);
+ public static final Tag CONTENT = new Tag("content", SYNTHETIC);
/**
* All text content must be in a paragraph element.
* If a paragraph didn't exist when content was encountered,
* a paragraph is manufactured.
- * toString() returns 'implied'. HTML reader synthesizes this tag.
+ * toString() returns 'p-implied'. HTML reader synthesizes this tag.
*/
- public static final Tag IMPLIED = new Tag("implied", SYNTETIC);
+ public static final Tag IMPLIED = new Tag("p-implied", SYNTHETIC);
final String name;
final int flags;
@@ -1144,7 +1144,7 @@ public class HTML
*/
boolean isSyntetic()
{
- return (flags & SYNTETIC) != 0;
+ return (flags & SYNTHETIC) != 0;
}
private static void unexpected(Exception ex)
@@ -1185,7 +1185,7 @@ public class HTML
static final int BREAKS = 1;
static final int BLOCK = 2;
static final int PREFORMATTED = 4;
- static final int SYNTETIC = 8;
+ static final int SYNTHETIC = 8;
private static Map tagMap;
private static Map attrMap;
@@ -1196,6 +1196,7 @@ public class HTML
*/
public HTML()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/text/html/HTMLDocument.java b/libjava/classpath/javax/swing/text/html/HTMLDocument.java
index a95e496ec4d..d048a04e614 100644
--- a/libjava/classpath/javax/swing/text/html/HTMLDocument.java
+++ b/libjava/classpath/javax/swing/text/html/HTMLDocument.java
@@ -38,7 +38,14 @@ exception statement from your version. */
package javax.swing.text.html;
+import java.net.URL;
+
+import javax.swing.text.AbstractDocument;
+import javax.swing.text.AttributeSet;
import javax.swing.text.DefaultStyledDocument;
+import javax.swing.text.Element;
+import javax.swing.text.ElementIterator;
+import javax.swing.text.html.HTML.Tag;
/**
* TODO: This class is not yet completetely implemented.
@@ -47,7 +54,215 @@ import javax.swing.text.DefaultStyledDocument;
*/
public class HTMLDocument extends DefaultStyledDocument
{
+ /** A key for document properies. The value for the key is
+ * a Vector of Strings of comments not found in the body.
+ */
+ public static final String AdditionalComments = "AdditionalComments";
+ URL baseURL = null;
+ boolean preservesUnknownTags = true;
+
+ /**
+ * Returns the location against which to resolve relative URLs.
+ * This is the document's URL if the document was loaded from a URL.
+ * If a <code>base</code> tag is found, it will be used.
+ * @return the base URL
+ */
+ public URL getBase()
+ {
+ return baseURL;
+ }
+
+ /**
+ * Sets the location against which to resolve relative URLs.
+ * @param u the new base URL
+ */
+ public void setBase(URL u)
+ {
+ baseURL = u;
+ //TODO: also set the base of the StyleSheet
+ }
+
+ /**
+ * Returns whether or not the parser preserves unknown HTML tags.
+ * @return true if the parser preserves unknown tags
+ */
+ public boolean getPreservesUnknownTags()
+ {
+ return preservesUnknownTags;
+ }
+
+ /**
+ * Sets the behaviour of the parser when it encounters unknown HTML tags.
+ * @param preservesTags true if the parser should preserve unknown tags.
+ */
+ public void setPreservesUnknownTags(boolean preservesTags)
+ {
+ preservesUnknownTags = preservesTags;
+ }
+
+ /**
+ * An iterator to iterate through LeafElements in the document.
+ */
+ class LeafIterator extends Iterator
+ {
+ HTML.Tag tag;
+ HTMLDocument doc;
+ ElementIterator it;
+
+ public LeafIterator (HTML.Tag t, HTMLDocument d)
+ {
+ doc = d;
+ tag = t;
+ it = new ElementIterator(doc);
+ }
+
+ /**
+ * Return the attributes for the tag associated with this iteartor
+ * @return the AttributeSet
+ */
+ public AttributeSet getAttributes()
+ {
+ if (it.current() != null)
+ return it.current().getAttributes();
+ return null;
+ }
+
+ /**
+ * Get the end of the range for the current occurrence of the tag
+ * being defined and having the same attributes.
+ * @return the end of the range
+ */
+ public int getEndOffset()
+ {
+ if (it.current() != null)
+ return it.current().getEndOffset();
+ return -1;
+ }
+
+ /**
+ * Get the start of the range for the current occurrence of the tag
+ * being defined and having the same attributes.
+ * @return the start of the range (-1 if it can't be found).
+ */
+
+ public int getStartOffset()
+ {
+ if (it.current() != null)
+ return it.current().getStartOffset();
+ return -1;
+ }
+
+ /**
+ * Advance the iterator to the next LeafElement .
+ */
+ public void next()
+ {
+ it.next();
+ while (it.current()!= null && !it.current().isLeaf())
+ it.next();
+ }
+
+ /**
+ * Indicates whether or not the iterator currently represents an occurrence
+ * of the tag.
+ * @return true if the iterator currently represents an occurrence of the
+ * tag.
+ */
+ public boolean isValid()
+ {
+ return it.current() != null;
+ }
+
+ /**
+ * Type of tag for this iterator.
+ */
+ public Tag getTag()
+ {
+ return tag;
+ }
+
+ }
+
public void processHTMLFrameHyperlinkEvent(HTMLFrameHyperlinkEvent event)
{
+ // TODO: Implement this properly.
+ }
+
+ /**
+ * Gets an iterator for the given HTML.Tag.
+ * @param t the requested HTML.Tag
+ * @return the Iterator
+ */
+ public HTMLDocument.Iterator getIterator (HTML.Tag t)
+ {
+ return new HTMLDocument.LeafIterator(t, this);
+ }
+
+ /**
+ * An iterator over a particular type of tag.
+ */
+ public abstract static class Iterator
+ {
+ /**
+ * Return the attribute set for this tag.
+ * @return the <code>AttributeSet</code> (null if none found).
+ */
+ public abstract AttributeSet getAttributes();
+
+ /**
+ * Get the end of the range for the current occurrence of the tag
+ * being defined and having the same attributes.
+ * @return the end of the range
+ */
+ public abstract int getEndOffset();
+
+ /**
+ * Get the start of the range for the current occurrence of the tag
+ * being defined and having the same attributes.
+ * @return the start of the range (-1 if it can't be found).
+ */
+ public abstract int getStartOffset();
+
+ /**
+ * Move the iterator forward.
+ */
+ public abstract void next();
+
+ /**
+ * Indicates whether or not the iterator currently represents an occurrence
+ * of the tag.
+ * @return true if the iterator currently represents an occurrence of the
+ * tag.
+ */
+ public abstract boolean isValid();
+
+ /**
+ * Type of tag this iterator represents.
+ * @return the tag.
+ */
+ public abstract HTML.Tag getTag();
+ }
+
+ public class BlockElement extends AbstractDocument.BranchElement
+ {
+ public BlockElement (Element parent, AttributeSet a)
+ {
+ super (parent, a);
+ }
+
+ /**
+ * Gets the resolving parent. Since HTML attributes are not
+ * inherited at the model level, this returns null.
+ */
+ public AttributeSet getResolveParent()
+ {
+ return null;
+ }
+
+ public String getName()
+ {
+ //FIXME: this is supposed to do something different from the super class
+ return super.getName();
+ }
}
}
diff --git a/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java b/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java
index c0182fe6ac9..5189c777539 100644
--- a/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java
+++ b/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java
@@ -43,8 +43,10 @@ import java.io.Reader;
import java.io.Serializable;
import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.StyledEditorKit;
+import javax.swing.text.html.parser.ParserDelegator;
/**
* This class is NOT implemented. This file currently holds only
@@ -96,9 +98,9 @@ public class HTMLEditorKit
/**
* The parser calls this method after it finishes parsing the document.
*/
- public void flush()
- throws BadLocationException
+ public void flush() throws BadLocationException
{
+ // TODO: What to do here, if anything?
}
/**
@@ -108,6 +110,7 @@ public class HTMLEditorKit
*/
public void handleComment(char[] comment, int position)
{
+ // TODO: What to do here, if anything?
}
/**
@@ -118,6 +121,7 @@ public class HTMLEditorKit
*/
public void handleEndOfLineString(String end_of_line)
{
+ // TODO: What to do here, if anything?
}
/**
@@ -129,6 +133,7 @@ public class HTMLEditorKit
*/
public void handleEndTag(HTML.Tag tag, int position)
{
+ // TODO: What to do here, if anything?
}
/**
@@ -139,6 +144,7 @@ public class HTMLEditorKit
*/
public void handleError(String message, int position)
{
+ // TODO: What to do here, if anything?
}
/**
@@ -149,9 +155,9 @@ public class HTMLEditorKit
* @param position The tag position in the text being parsed.
*/
public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet attributes,
- int position
- )
+ int position)
{
+ // TODO: What to do here, if anything?
}
/**
@@ -165,6 +171,7 @@ public class HTMLEditorKit
int position
)
{
+ // TODO: What to do here, if anything?
}
/**
@@ -174,6 +181,7 @@ public class HTMLEditorKit
*/
public void handleText(char[] text, int position)
{
+ // TODO: What to do here, if anything?
}
}
@@ -247,4 +255,26 @@ public class HTMLEditorKit
* The "ident paragraph right" action.
*/
public static final String PARA_INDENT_RIGHT = "html-para-indent-right";
+
+ /**
+ * Create a text storage model for this type of editor.
+ *
+ * @return the model
+ */
+ public Document createDefaultDocument()
+ {
+ HTMLDocument document = new HTMLDocument();
+ return document;
+ }
+
+ /**
+ * Get the parser that this editor kit uses for reading HTML streams. This
+ * method can be overridden to use the alternative parser.
+ *
+ * @return the HTML parser (by default, {@link ParserDelegator}).
+ */
+ protected Parser getParser()
+ {
+ return new ParserDelegator();
+ }
} \ No newline at end of file
diff --git a/libjava/classpath/javax/swing/text/html/HTMLFrameHyperlinkEvent.java b/libjava/classpath/javax/swing/text/html/HTMLFrameHyperlinkEvent.java
index dc0ab10a8f7..e146965d778 100644
--- a/libjava/classpath/javax/swing/text/html/HTMLFrameHyperlinkEvent.java
+++ b/libjava/classpath/javax/swing/text/html/HTMLFrameHyperlinkEvent.java
@@ -41,7 +41,6 @@ package javax.swing.text.html;
import java.net.URL;
import javax.swing.event.HyperlinkEvent;
-import javax.swing.event.HyperlinkEvent.EventType;
import javax.swing.text.Element;
/**
@@ -50,8 +49,7 @@ import javax.swing.text.Element;
*
* @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
*/
-public class HTMLFrameHyperlinkEvent
- extends HyperlinkEvent
+public class HTMLFrameHyperlinkEvent extends HyperlinkEvent
{
private final String target_frame;
diff --git a/libjava/classpath/javax/swing/text/html/parser/ContentModel.java b/libjava/classpath/javax/swing/text/html/parser/ContentModel.java
index deb7b1602bb..70e9c2acbff 100644
--- a/libjava/classpath/javax/swing/text/html/parser/ContentModel.java
+++ b/libjava/classpath/javax/swing/text/html/parser/ContentModel.java
@@ -95,9 +95,12 @@ public final class ContentModel
*/
public int type;
- /** Create a content model initializing all fields to default values. */
+ /**
+ * Create a content model initializing all fields to default values.
+ */
public ContentModel()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/text/html/parser/DTD.java b/libjava/classpath/javax/swing/text/html/parser/DTD.java
index f17ca011ea0..16bc5b0d6af 100644
--- a/libjava/classpath/javax/swing/text/html/parser/DTD.java
+++ b/libjava/classpath/javax/swing/text/html/parser/DTD.java
@@ -81,8 +81,9 @@ public class DTD
{
/**
* The version of the persistent data format.
+ * @specnote This was made <code>final</code> in 1.5.
*/
- public static int FILE_VERSION = 1;
+ public static final int FILE_VERSION = 1;
/**
* The table of existing available DTDs.
@@ -590,8 +591,7 @@ public class DTD
* @param name the name of the entity
* @param type the type of the entity, a bitwise combination
* of GENERAL, PARAMETER, SYSTEM and PUBLIC.
- * @throws an error if the parameter is both GENERAL and PARAMETER
- * of both PUBLIC and SYSTEM.
+ *
* @return the created entity
*/
private Entity newEntity(String name, int type)
diff --git a/libjava/classpath/javax/swing/text/html/parser/DocumentParser.java b/libjava/classpath/javax/swing/text/html/parser/DocumentParser.java
index 164297f1882..062606d17ba 100644
--- a/libjava/classpath/javax/swing/text/html/parser/DocumentParser.java
+++ b/libjava/classpath/javax/swing/text/html/parser/DocumentParser.java
@@ -168,6 +168,7 @@ public class DocumentParser
* specific packages, write your own DTD or obtain the working instance
* of parser in other way, for example, by calling
* {@link javax.swing.text.html.HTMLEditorKit#getParser()}.
+ *
* @param a_dtd a DTD to use.
*/
public DocumentParser(DTD a_dtd)
@@ -212,6 +213,7 @@ public class DocumentParser
*/
protected void handleComment(char[] comment)
{
+ // This default implementation does nothing.
}
/**
@@ -224,6 +226,7 @@ public class DocumentParser
protected void handleEmptyTag(TagElement tag)
throws javax.swing.text.ChangedCharSetException
{
+ // This default implementation does nothing.
}
/**
@@ -234,11 +237,13 @@ public class DocumentParser
*/
protected void handleEndTag(TagElement tag)
{
+ // This default implementation does nothing.
}
/* Handle error that has occured in the given line. */
protected void handleError(int line, String message)
{
+ // This default implementation does nothing.
}
/**
@@ -249,6 +254,7 @@ public class DocumentParser
*/
protected void handleStartTag(TagElement tag)
{
+ // This default implementation does nothing.
}
/**
@@ -257,5 +263,6 @@ public class DocumentParser
*/
protected void handleText(char[] text)
{
+ // This default implementation does nothing.
}
}
diff --git a/libjava/classpath/javax/swing/text/html/parser/Element.java b/libjava/classpath/javax/swing/text/html/parser/Element.java
index 098983c6923..c07c07f5426 100644
--- a/libjava/classpath/javax/swing/text/html/parser/Element.java
+++ b/libjava/classpath/javax/swing/text/html/parser/Element.java
@@ -148,10 +148,10 @@ public final class Element
/**
* The default constructor must have package level access in this
* class. Use DTD.defineElement(..) to create an element when required.
- * @todo MAKE THIS PACKAGE in the final version. Now the Parser needs it!
*/
Element()
{
+ // Nothing to do here.
}
/**
diff --git a/libjava/classpath/javax/swing/text/html/parser/Parser.java b/libjava/classpath/javax/swing/text/html/parser/Parser.java
index 7ff6853da82..a88e9ce1953 100644
--- a/libjava/classpath/javax/swing/text/html/parser/Parser.java
+++ b/libjava/classpath/javax/swing/text/html/parser/Parser.java
@@ -256,6 +256,7 @@ public class Parser
*/
protected void endTag(boolean omitted)
{
+ // This default implementation does nothing.
}
/**
@@ -310,6 +311,7 @@ public class Parser
*/
protected void handleComment(char[] comment)
{
+ // This default implementation does nothing.
}
/**
@@ -333,6 +335,7 @@ public class Parser
protected void handleEmptyTag(TagElement tag)
throws ChangedCharSetException
{
+ // This default implementation does nothing.
}
/**
@@ -343,11 +346,13 @@ public class Parser
*/
protected void handleEndTag(TagElement tag)
{
+ // This default implementation does nothing.
}
/* Handle error that has occured in the given line. */
protected void handleError(int line, String message)
{
+ // This default implementation does nothing.
}
/**
@@ -358,6 +363,7 @@ public class Parser
*/
protected void handleStartTag(TagElement tag)
{
+ // This default implementation does nothing.
}
/**
@@ -376,6 +382,7 @@ public class Parser
*/
protected void handleText(char[] text)
{
+ // This default implementation does nothing.
}
/**
@@ -387,6 +394,7 @@ public class Parser
*/
protected void handleTitle(char[] title)
{
+ // This default implementation does nothing.
}
/**
@@ -420,6 +428,7 @@ public class Parser
*/
protected void markFirstTime(Element element)
{
+ // This default implementation does nothing.
}
/**
@@ -432,5 +441,6 @@ public class Parser
protected void startTag(TagElement tag)
throws ChangedCharSetException
{
+ // This default implementation does nothing.
}
}
diff --git a/libjava/classpath/javax/swing/tree/DefaultMutableTreeNode.java b/libjava/classpath/javax/swing/tree/DefaultMutableTreeNode.java
index e709e2a0449..d9747729317 100644
--- a/libjava/classpath/javax/swing/tree/DefaultMutableTreeNode.java
+++ b/libjava/classpath/javax/swing/tree/DefaultMutableTreeNode.java
@@ -45,7 +45,6 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.NoSuchElementException;
diff --git a/libjava/classpath/javax/swing/tree/DefaultTreeCellEditor.java b/libjava/classpath/javax/swing/tree/DefaultTreeCellEditor.java
index 7a44e738338..2891a778ee9 100644
--- a/libjava/classpath/javax/swing/tree/DefaultTreeCellEditor.java
+++ b/libjava/classpath/javax/swing/tree/DefaultTreeCellEditor.java
@@ -47,7 +47,6 @@ import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
-import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
@@ -56,12 +55,8 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.EventObject;
-import javax.swing.CellRendererPane;
import javax.swing.DefaultCellEditor;
import javax.swing.Icon;
-import javax.swing.JCheckBox;
-import javax.swing.JComboBox;
-import javax.swing.JComponent;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
@@ -354,9 +349,9 @@ public class DefaultTreeCellEditor
/**
* Configures the editing component whenever it is null.
*
- * @param tree- the tree to configure to component for.
- * @param renderer- the renderer used to set up the nodes
- * @param editor- the editor used
+ * @param tree the tree to configure to component for.
+ * @param renderer the renderer used to set up the nodes
+ * @param editor the editor used
*/
private void configureEditingComponent(JTree tree,
DefaultTreeCellRenderer renderer,
@@ -513,6 +508,8 @@ public class DefaultTreeCellEditor
// Cell may not be currently editable, but may need to start timer.
if (shouldStartEditingTimer(event))
startEditingTimer();
+ else if (timer.isRunning())
+ timer.stop();
return false;
}
@@ -605,7 +602,7 @@ public class DefaultTreeCellEditor
/**
* Messaged when the timer fires, this will start the editing session.
*
- * @param @param e - the event that characterizes the action.
+ * @param e the event that characterizes the action.
*/
public void actionPerformed(ActionEvent e)
{
diff --git a/libjava/classpath/javax/swing/tree/DefaultTreeCellRenderer.java b/libjava/classpath/javax/swing/tree/DefaultTreeCellRenderer.java
index 4a353b30176..d1cb9c0e8b7 100644
--- a/libjava/classpath/javax/swing/tree/DefaultTreeCellRenderer.java
+++ b/libjava/classpath/javax/swing/tree/DefaultTreeCellRenderer.java
@@ -419,8 +419,7 @@ public class DefaultTreeCellRenderer
super.setBackground(getBackgroundSelectionColor());
setForeground(getTextSelectionColor());
- if (tree.getLeadSelectionPath() == null ||
- (tree.getLeadSelectionPath().getLastPathComponent()).equals(val))
+ if (hasFocus)
setBorderSelectionColor(UIManager.getLookAndFeelDefaults().
getColor("Tree.selectionBorderColor"));
else
diff --git a/libjava/classpath/javax/swing/tree/DefaultTreeModel.java b/libjava/classpath/javax/swing/tree/DefaultTreeModel.java
index 5b5e0391478..5cf80986061 100644
--- a/libjava/classpath/javax/swing/tree/DefaultTreeModel.java
+++ b/libjava/classpath/javax/swing/tree/DefaultTreeModel.java
@@ -299,6 +299,7 @@ public class DefaultTreeModel
public void insertNodeInto(MutableTreeNode newChild, MutableTreeNode parent,
int index)
{
+ newChild.setParent(parent);
parent.insert(newChild, index);
int[] childIndices = new int[1];
childIndices[0] = index;
diff --git a/libjava/classpath/javax/swing/tree/TreeCellRenderer.java b/libjava/classpath/javax/swing/tree/TreeCellRenderer.java
index ebbe3fa9133..a1808c9ee91 100644
--- a/libjava/classpath/javax/swing/tree/TreeCellRenderer.java
+++ b/libjava/classpath/javax/swing/tree/TreeCellRenderer.java
@@ -46,22 +46,24 @@ import javax.swing.JTree;
* TreeCellRenderer public interface
* @author Andrew Selkirk
*/
-public interface TreeCellRenderer {
+public interface TreeCellRenderer
+{
- /**
- * getTreeCellRendererComponent
- * @param tree TODO
- * @param value TODO
- * @param selected TODO
- * @param expanded TODO
- * @param leaf TODO
- * @param row TODO
- * @param us TODO
- * @returns TODO
- */
- Component getTreeCellRendererComponent(JTree tree,
- Object value, boolean selected, boolean expanded,
- boolean leaf, int row, boolean hasFocus);
+ /**
+ * getTreeCellRendererComponent
+ * @param tree TODO
+ * @param value TODO
+ * @param selected TODO
+ * @param expanded TODO
+ * @param leaf TODO
+ * @param row TODO
+ * @param hasFocus TODO
+ * @returns TODO
+ */
+ Component getTreeCellRendererComponent(JTree tree, Object value,
+ boolean selected, boolean expanded,
+ boolean leaf, int row,
+ boolean hasFocus);
-} // TreeCellRenderer
+}
diff --git a/libjava/classpath/javax/swing/tree/TreeModel.java b/libjava/classpath/javax/swing/tree/TreeModel.java
index 759aaac588c..ec1884efdb7 100644
--- a/libjava/classpath/javax/swing/tree/TreeModel.java
+++ b/libjava/classpath/javax/swing/tree/TreeModel.java
@@ -44,66 +44,62 @@ import javax.swing.event.TreeModelListener;
* TreeModel public interface
* @author Andrew Selkirk
*/
-public interface TreeModel {
-
- //-------------------------------------------------------------
- // Methods ----------------------------------------------------
- //-------------------------------------------------------------
-
- /**
- * getRoot
- * @returns Object
- */
- Object getRoot();
-
- /**
- * getChild
- * @param parent TODO
- * @param index TODO
- * @returns Object
- */
- Object getChild(Object parent, int index);
-
- /**
- * getChildCount
- * @param parent TODO
- * @returns int
- */
- int getChildCount(Object parent);
-
- /**
- * isLeaf
- * @param node TODO
- * @returns boolean
- */
- boolean isLeaf(Object node);
-
- /**
- * valueForPathChanged
- * @param path TODO
- * @param newvalue TODO
- */
- void valueForPathChanged(TreePath path, Object newvalue);
-
- /**
- * getIndexOfChild
- * @param parent TODO
- * @param ild TODO
- * @returns int
- */
- int getIndexOfChild(Object parent, Object child);
-
- /**
- * addTreeModelListener
- * @param listener TODO
- */
- void addTreeModelListener(TreeModelListener listener);
-
- /**
- * removeTreeModelListener
- * @param listener TODO
- */
- void removeTreeModelListener(TreeModelListener listener);
-
-
-} // TreeModel
+public interface TreeModel
+{
+ /**
+ * getRoot
+ * @returns Object
+ */
+ Object getRoot();
+
+ /**
+ * getChild
+ * @param parent TODO
+ * @param index TODO
+ * @returns Object
+ */
+ Object getChild(Object parent, int index);
+
+ /**
+ * getChildCount
+ * @param parent TODO
+ * @returns int
+ */
+ int getChildCount(Object parent);
+
+ /**
+ * isLeaf
+ * @param node TODO
+ * @returns boolean
+ */
+ boolean isLeaf(Object node);
+
+ /**
+ * valueForPathChanged
+ * @param path TODO
+ * @param newvalue TODO
+ */
+ void valueForPathChanged(TreePath path, Object newvalue);
+
+ /**
+ * getIndexOfChild
+ * @param parent TODO
+ * @param child TODO
+ * @returns int
+ */
+ int getIndexOfChild(Object parent, Object child);
+
+ /**
+ * addTreeModelListener
+ * @param listener TODO
+ */
+ void addTreeModelListener(TreeModelListener listener);
+
+ /**
+ * removeTreeModelListener
+ * @param listener TODO
+ */
+ void removeTreeModelListener(TreeModelListener listener);
+
+
+}
diff --git a/libjava/classpath/javax/swing/undo/CannotRedoException.java b/libjava/classpath/javax/swing/undo/CannotRedoException.java
index 7d70a38c2c8..5f22648350a 100644
--- a/libjava/classpath/javax/swing/undo/CannotRedoException.java
+++ b/libjava/classpath/javax/swing/undo/CannotRedoException.java
@@ -44,13 +44,13 @@ package javax.swing.undo;
* @author Andrew Selkirk (aselkirk@sympatico.ca)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-public class CannotRedoException
- extends RuntimeException
+public class CannotRedoException extends RuntimeException
{
/**
* Constructs a new instance of a <code>CannotRedoException</code>.
*/
public CannotRedoException()
{
+ super();
}
}
diff --git a/libjava/classpath/javax/swing/undo/CannotUndoException.java b/libjava/classpath/javax/swing/undo/CannotUndoException.java
index 9fc0ec3bd3a..8d08cda6853 100644
--- a/libjava/classpath/javax/swing/undo/CannotUndoException.java
+++ b/libjava/classpath/javax/swing/undo/CannotUndoException.java
@@ -53,5 +53,6 @@ public class CannotUndoException
*/
public CannotUndoException()
{
+ super();
}
}